浏览代码

Add BloomSample sample

espes 13 年之前
父节点
当前提交
fef3fdeb6f

+ 317 - 0
BloomSample/BloomComponent.cs

@@ -0,0 +1,317 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// BloomComponent.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+#endregion
+
+#region Using Statements
+using System;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Content;
+using Microsoft.Xna.Framework.Graphics;
+#endregion
+
+namespace BloomPostprocess
+{
+    public class BloomComponent : DrawableGameComponent
+    {
+        #region Fields
+
+        SpriteBatch spriteBatch;
+
+        Effect bloomExtractEffect;
+        Effect bloomCombineEffect;
+        Effect gaussianBlurEffect;
+
+        RenderTarget2D sceneRenderTarget;
+        RenderTarget2D renderTarget1;
+        RenderTarget2D renderTarget2;
+
+
+        // Choose what display settings the bloom should use.
+        public BloomSettings Settings
+        {
+            get { return settings; }
+            set { settings = value; }
+        }
+
+        BloomSettings settings = BloomSettings.PresetSettings[0];
+
+
+        // Optionally displays one of the intermediate buffers used
+        // by the bloom postprocess, so you can see exactly what is
+        // being drawn into each rendertarget.
+        public enum IntermediateBuffer
+        {
+            PreBloom,
+            BlurredHorizontally,
+            BlurredBothWays,
+            FinalResult,
+        }
+
+        public IntermediateBuffer ShowBuffer
+        {
+            get { return showBuffer; }
+            set { showBuffer = value; }
+        }
+
+        IntermediateBuffer showBuffer = IntermediateBuffer.FinalResult;
+
+
+        #endregion
+
+        #region Initialization
+
+
+        public BloomComponent(Game game)
+            : base(game)
+        {
+            if (game == null)
+                throw new ArgumentNullException("game");
+        }
+
+
+        /// <summary>
+        /// Load your graphics content.
+        /// </summary>
+        protected override void LoadContent()
+        {
+            spriteBatch = new SpriteBatch(GraphicsDevice);
+
+            bloomExtractEffect = Game.Content.Load<Effect>("BloomExtract");
+            bloomCombineEffect = Game.Content.Load<Effect>("BloomCombine");
+            gaussianBlurEffect = Game.Content.Load<Effect>("GaussianBlur");
+
+            // Look up the resolution and format of our main backbuffer.
+            PresentationParameters pp = GraphicsDevice.PresentationParameters;
+
+            int width = pp.BackBufferWidth;
+            int height = pp.BackBufferHeight;
+
+            SurfaceFormat format = pp.BackBufferFormat;
+
+            // Create a texture for rendering the main scene, prior to applying bloom.
+            sceneRenderTarget = new RenderTarget2D(GraphicsDevice, width, height, false,
+                                                   format, pp.DepthStencilFormat, pp.MultiSampleCount,
+                                                   RenderTargetUsage.DiscardContents);
+
+            // Create two rendertargets for the bloom processing. These are half the
+            // size of the backbuffer, in order to minimize fillrate costs. Reducing
+            // the resolution in this way doesn't hurt quality, because we are going
+            // to be blurring the bloom images in any case.
+            width /= 2;
+            height /= 2;
+
+            renderTarget1 = new RenderTarget2D(GraphicsDevice, width, height, false, format, DepthFormat.None);
+            renderTarget2 = new RenderTarget2D(GraphicsDevice, width, height, false, format, DepthFormat.None);
+        }
+
+
+        /// <summary>
+        /// Unload your graphics content.
+        /// </summary>
+        protected override void UnloadContent()
+        {
+            sceneRenderTarget.Dispose();
+            renderTarget1.Dispose();
+            renderTarget2.Dispose();
+        }
+
+
+        #endregion
+
+        #region Draw
+
+
+        /// <summary>
+        /// This should be called at the very start of the scene rendering. The bloom
+        /// component uses it to redirect drawing into its custom rendertarget, so it
+        /// can capture the scene image in preparation for applying the bloom filter.
+        /// </summary>
+        public void BeginDraw()
+        {
+            if (Visible)
+            {
+                GraphicsDevice.SetRenderTarget(sceneRenderTarget);
+            }
+        }
+
+
+        /// <summary>
+        /// This is where it all happens. Grabs a scene that has already been rendered,
+        /// and uses postprocess magic to add a glowing bloom effect over the top of it.
+        /// </summary>
+        public override void Draw(GameTime gameTime)
+        {
+            GraphicsDevice.SamplerStates[1] = SamplerState.LinearClamp;
+
+            // Pass 1: draw the scene into rendertarget 1, using a
+            // shader that extracts only the brightest parts of the image.
+            bloomExtractEffect.Parameters["BloomThreshold"].SetValue(
+                Settings.BloomThreshold);
+
+            DrawFullscreenQuad(sceneRenderTarget, renderTarget1,
+                               bloomExtractEffect,
+                               IntermediateBuffer.PreBloom);
+
+            // Pass 2: draw from rendertarget 1 into rendertarget 2,
+            // using a shader to apply a horizontal gaussian blur filter.
+            SetBlurEffectParameters(1.0f / (float)renderTarget1.Width, 0);
+
+            DrawFullscreenQuad(renderTarget1, renderTarget2,
+                               gaussianBlurEffect,
+                               IntermediateBuffer.BlurredHorizontally);
+
+            // Pass 3: draw from rendertarget 2 back into rendertarget 1,
+            // using a shader to apply a vertical gaussian blur filter.
+            SetBlurEffectParameters(0, 1.0f / (float)renderTarget1.Height);
+
+            DrawFullscreenQuad(renderTarget2, renderTarget1,
+                               gaussianBlurEffect,
+                               IntermediateBuffer.BlurredBothWays);
+
+            // Pass 4: draw both rendertarget 1 and the original scene
+            // image back into the main backbuffer, using a shader that
+            // combines them to produce the final bloomed result.
+            GraphicsDevice.SetRenderTarget(null);
+
+            EffectParameterCollection parameters = bloomCombineEffect.Parameters;
+
+            parameters["BloomIntensity"].SetValue(Settings.BloomIntensity);
+            parameters["BaseIntensity"].SetValue(Settings.BaseIntensity);
+            parameters["BloomSaturation"].SetValue(Settings.BloomSaturation);
+            parameters["BaseSaturation"].SetValue(Settings.BaseSaturation);
+
+            GraphicsDevice.Textures[1] = sceneRenderTarget;
+
+            Viewport viewport = GraphicsDevice.Viewport;
+
+            DrawFullscreenQuad(renderTarget1,
+                               viewport.Width, viewport.Height,
+                               bloomCombineEffect,
+                               IntermediateBuffer.FinalResult);
+        }
+
+
+        /// <summary>
+        /// Helper for drawing a texture into a rendertarget, using
+        /// a custom shader to apply postprocessing effects.
+        /// </summary>
+        void DrawFullscreenQuad(Texture2D texture, RenderTarget2D renderTarget,
+                                Effect effect, IntermediateBuffer currentBuffer)
+        {
+            GraphicsDevice.SetRenderTarget(renderTarget);
+
+            DrawFullscreenQuad(texture,
+                               renderTarget.Width, renderTarget.Height,
+                               effect, currentBuffer);
+        }
+
+
+        /// <summary>
+        /// Helper for drawing a texture into the current rendertarget,
+        /// using a custom shader to apply postprocessing effects.
+        /// </summary>
+        void DrawFullscreenQuad(Texture2D texture, int width, int height,
+                                Effect effect, IntermediateBuffer currentBuffer)
+        {
+            // If the user has selected one of the show intermediate buffer options,
+            // we still draw the quad to make sure the image will end up on the screen,
+            // but might need to skip applying the custom pixel shader.
+            if (showBuffer < currentBuffer)
+            {
+                effect = null;
+            }
+
+            spriteBatch.Begin(0, BlendState.Opaque, null, null, null, effect);
+            spriteBatch.Draw(texture, new Rectangle(0, 0, width, height), Color.White);
+            spriteBatch.End();
+        }
+
+
+        /// <summary>
+        /// Computes sample weightings and texture coordinate offsets
+        /// for one pass of a separable gaussian blur filter.
+        /// </summary>
+        void SetBlurEffectParameters(float dx, float dy)
+        {
+            // Look up the sample weight and offset effect parameters.
+            EffectParameter weightsParameter, offsetsParameter;
+
+            weightsParameter = gaussianBlurEffect.Parameters["SampleWeights"];
+            offsetsParameter = gaussianBlurEffect.Parameters["SampleOffsets"];
+
+            // Look up how many samples our gaussian blur effect supports.
+            int sampleCount = weightsParameter.Elements.Count;
+
+            // Create temporary arrays for computing our filter settings.
+            float[] sampleWeights = new float[sampleCount];
+            Vector2[] sampleOffsets = new Vector2[sampleCount];
+
+            // The first sample always has a zero offset.
+            sampleWeights[0] = ComputeGaussian(0);
+            sampleOffsets[0] = new Vector2(0);
+
+            // Maintain a sum of all the weighting values.
+            float totalWeights = sampleWeights[0];
+
+            // Add pairs of additional sample taps, positioned
+            // along a line in both directions from the center.
+            for (int i = 0; i < sampleCount / 2; i++)
+            {
+                // Store weights for the positive and negative taps.
+                float weight = ComputeGaussian(i + 1);
+
+                sampleWeights[i * 2 + 1] = weight;
+                sampleWeights[i * 2 + 2] = weight;
+
+                totalWeights += weight * 2;
+
+                // To get the maximum amount of blurring from a limited number of
+                // pixel shader samples, we take advantage of the bilinear filtering
+                // hardware inside the texture fetch unit. If we position our texture
+                // coordinates exactly halfway between two texels, the filtering unit
+                // will average them for us, giving two samples for the price of one.
+                // This allows us to step in units of two texels per sample, rather
+                // than just one at a time. The 1.5 offset kicks things off by
+                // positioning us nicely in between two texels.
+                float sampleOffset = i * 2 + 1.5f;
+
+                Vector2 delta = new Vector2(dx, dy) * sampleOffset;
+
+                // Store texture coordinate offsets for the positive and negative taps.
+                sampleOffsets[i * 2 + 1] = delta;
+                sampleOffsets[i * 2 + 2] = -delta;
+            }
+
+            // Normalize the list of sample weightings, so they will always sum to one.
+            for (int i = 0; i < sampleWeights.Length; i++)
+            {
+                sampleWeights[i] /= totalWeights;
+            }
+
+            // Tell the effect about our new filter settings.
+            weightsParameter.SetValue(sampleWeights);
+            offsetsParameter.SetValue(sampleOffsets);
+        }
+
+
+        /// <summary>
+        /// Evaluates a single point on the gaussian falloff curve.
+        /// Used for setting up the blur filter weightings.
+        /// </summary>
+        float ComputeGaussian(float n)
+        {
+            float theta = Settings.BlurAmount;
+
+            return (float)((1.0 / Math.Sqrt(2 * Math.PI * theta)) *
+                           Math.Exp(-(n * n) / (2 * theta * theta)));
+        }
+
+
+        #endregion
+    }
+}

+ 101 - 0
BloomSample/BloomSample.MacOS.csproj

@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>10.0.0</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{A93553D9-11E5-4B0B-9809-4E4765D5FD8F}</ProjectGuid>
+    <ProjectTypeGuids>{948B3504-5B70-4649-8FE4-BDE1FB46EC69};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <OutputType>Exe</OutputType>
+    <RootNamespace>BloomSample</RootNamespace>
+    <AssemblyName>BloomSample</AssemblyName>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug</OutputPath>
+    <DefineConstants>DEBUG;</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <EnablePackageSigning>false</EnablePackageSigning>
+    <IncludeMonoRuntime>false</IncludeMonoRuntime>
+    <ConsolePause>false</ConsolePause>
+    <EnableCodeSigning>false</EnableCodeSigning>
+    <CreatePackage>false</CreatePackage>
+    <CodeSigningKey>Mac Developer</CodeSigningKey>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>none</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release</OutputPath>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <EnablePackageSigning>false</EnablePackageSigning>
+    <IncludeMonoRuntime>false</IncludeMonoRuntime>
+    <LinkMode>Full</LinkMode>
+    <ConsolePause>false</ConsolePause>
+    <EnableCodeSigning>false</EnableCodeSigning>
+    <CreatePackage>false</CreatePackage>
+    <CodeSigningKey>Mac Developer</CodeSigningKey>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'AppStore|AnyCPU' ">
+    <DebugType>none</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\AppStore</OutputPath>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <PackageSigningKey>3rd Party Mac Developer Installer</PackageSigningKey>
+    <IncludeMonoRuntime>true</IncludeMonoRuntime>
+    <LinkMode>Full</LinkMode>
+    <EnablePackageSigning>true</EnablePackageSigning>
+    <ConsolePause>false</ConsolePause>
+    <EnableCodeSigning>true</EnableCodeSigning>
+    <CreatePackage>true</CreatePackage>
+    <CodeSigningKey>3rd Party Mac Developer Application</CodeSigningKey>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Xml" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="MonoMac" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\MonoGame.Framework\MonoGame.Framework.MacOS.csproj">
+      <Project>{36C538E6-C32A-4A8D-A39C-566173D7118E}</Project>
+      <Name>MonoGame.Framework.MacOS</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\ThirdParty\Lidgren.Network\Lidgren.Network.MacOS.csproj">
+      <Project>{AE483C29-042E-4226-BA52-D247CE7676DA}</Project>
+      <Name>Lidgren.Network.MacOS</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Main.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="BloomComponent.cs" />
+    <Compile Include="BloomSettings.cs" />
+    <Compile Include="Game.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Info.plist" />
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <Import Project="$(MSBuildExtensionsPath)\Mono\MonoMac\v0.0\Mono.MonoMac.targets" />
+  <ItemGroup>
+    <Folder Include="Content\" />
+  </ItemGroup>
+  <ItemGroup>
+    <Content Include="Content\BloomCombine.xnb" />
+    <Content Include="Content\BloomExtract.xnb" />
+    <Content Include="Content\GaussianBlur.xnb" />
+    <Content Include="Content\engine_diff_tex_0.xnb" />
+    <Content Include="Content\hudFont.xnb" />
+    <Content Include="Content\sunset.xnb" />
+    <Content Include="Content\tank.xnb" />
+    <Content Include="Content\turret_alt_diff_tex_0.xnb" />
+  </ItemGroup>
+</Project>

+ 82 - 0
BloomSample/BloomSettings.cs

@@ -0,0 +1,82 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// BloomSettings.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+#endregion
+
+namespace BloomPostprocess
+{
+    /// <summary>
+    /// Class holds all the settings used to tweak the bloom effect.
+    /// </summary>
+    public class BloomSettings
+    {
+        #region Fields
+
+
+        // Name of a preset bloom setting, for display to the user.
+        public readonly string Name;
+
+
+        // Controls how bright a pixel needs to be before it will bloom.
+        // Zero makes everything bloom equally, while higher values select
+        // only brighter colors. Somewhere between 0.25 and 0.5 is good.
+        public readonly float BloomThreshold;
+
+
+        // Controls how much blurring is applied to the bloom image.
+        // The typical range is from 1 up to 10 or so.
+        public readonly float BlurAmount;
+
+
+        // Controls the amount of the bloom and base images that
+        // will be mixed into the final scene. Range 0 to 1.
+        public readonly float BloomIntensity;
+        public readonly float BaseIntensity;
+
+
+        // Independently control the color saturation of the bloom and
+        // base images. Zero is totally desaturated, 1.0 leaves saturation
+        // unchanged, while higher values increase the saturation level.
+        public readonly float BloomSaturation;
+        public readonly float BaseSaturation;
+
+
+        #endregion
+
+
+        /// <summary>
+        /// Constructs a new bloom settings descriptor.
+        /// </summary>
+        public BloomSettings(string name, float bloomThreshold, float blurAmount,
+                             float bloomIntensity, float baseIntensity,
+                             float bloomSaturation, float baseSaturation)
+        {
+            Name = name;
+            BloomThreshold = bloomThreshold;
+            BlurAmount = blurAmount;
+            BloomIntensity = bloomIntensity;
+            BaseIntensity = baseIntensity;
+            BloomSaturation = bloomSaturation;
+            BaseSaturation = baseSaturation;
+        }
+        
+
+        /// <summary>
+        /// Table of preset bloom settings, used by the sample program.
+        /// </summary>
+        public static BloomSettings[] PresetSettings =
+        {
+            //                Name           Thresh  Blur Bloom  Base  BloomSat BaseSat
+            new BloomSettings("Default",     0.25f,  4,   1.25f, 1,    1,       1),
+            new BloomSettings("Soft",        0,      3,   1,     1,    1,       1),
+            new BloomSettings("Desaturated", 0.5f,   8,   2,     1,    0,       1),
+            new BloomSettings("Saturated",   0.25f,  4,   2,     1,    2,       0),
+            new BloomSettings("Blurry",      0,      2,   1,     0.1f, 1,       1),
+            new BloomSettings("Subtle",      0.5f,   2,   1,     1,    1,       1),
+        };
+    }
+}

二进制
BloomSample/Content/BloomCombine.xnb


二进制
BloomSample/Content/BloomExtract.xnb


二进制
BloomSample/Content/GaussianBlur.xnb


二进制
BloomSample/Content/engine_diff_tex_0.xnb


二进制
BloomSample/Content/hudFont.xnb


二进制
BloomSample/Content/sunset.xnb


二进制
BloomSample/Content/tank.xnb


二进制
BloomSample/Content/turret_alt_diff_tex_0.xnb


+ 254 - 0
BloomSample/Game.cs

@@ -0,0 +1,254 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// Game.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+#endregion
+
+#region Using Statements
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Content;
+using Microsoft.Xna.Framework.Graphics;
+using Microsoft.Xna.Framework.Input;
+#endregion
+
+namespace BloomPostprocess
+{
+    /// <summary>
+    /// Sample showing how to implement a bloom postprocess,
+    /// adding a glowing effect over the top of an existing scene.
+    /// </summary>
+    public class BloomPostprocessGame : Microsoft.Xna.Framework.Game
+    {
+        #region Fields
+
+        GraphicsDeviceManager graphics;
+
+        BloomComponent bloom;
+
+        int bloomSettingsIndex = 0;
+
+        SpriteBatch spriteBatch;
+        SpriteFont spriteFont;
+        Texture2D background;
+        Model model;
+
+        KeyboardState lastKeyboardState = new KeyboardState();
+        GamePadState lastGamePadState = new GamePadState();
+        KeyboardState currentKeyboardState = new KeyboardState();
+        GamePadState currentGamePadState = new GamePadState();
+
+        #endregion
+
+        #region Initialization
+
+
+        public BloomPostprocessGame()
+        {
+            Content.RootDirectory = "Content";
+
+            graphics = new GraphicsDeviceManager(this);
+
+            bloom = new BloomComponent(this);
+
+            Components.Add(bloom);
+        }
+
+
+        /// <summary>
+        /// Load your graphics content.
+        /// </summary>
+        protected override void LoadContent()
+        {
+            spriteBatch = new SpriteBatch(graphics.GraphicsDevice);
+            spriteFont = Content.Load<SpriteFont>("hudFont");
+            background = Content.Load<Texture2D>("sunset");
+            model = Content.Load<Model>("tank");
+        }
+
+
+        #endregion
+
+        #region Update and Draw
+
+
+        /// <summary>
+        /// Allows the game to run logic.
+        /// </summary>
+        protected override void Update(GameTime gameTime)
+        {
+            HandleInput();
+
+            base.Update(gameTime);
+        }
+
+
+        /// <summary>
+        /// This is called when the game should draw itself.
+        /// </summary>
+        protected override void Draw(GameTime gameTime)
+        {
+            GraphicsDevice device = graphics.GraphicsDevice;
+            Viewport viewport = device.Viewport;
+
+            bloom.BeginDraw();
+
+            device.Clear(Color.Black);
+
+            // Draw the background image.
+            spriteBatch.Begin(0, BlendState.Opaque);
+            
+            spriteBatch.Draw(background,
+                             new Rectangle(0, 0, viewport.Width, viewport.Height),
+                             Color.White);
+            
+            spriteBatch.End();
+
+            // Draw the spinning model.
+            device.DepthStencilState = DepthStencilState.Default;
+
+            DrawModel(gameTime);
+
+            // Draw other components (which includes the bloom).
+            base.Draw(gameTime);
+
+            // Display some text over the top. Note how we draw this after the bloom,
+            // because we don't want the text to be affected by the postprocessing.
+            DrawOverlayText();
+        }
+
+
+        /// <summary>
+        /// Helper for drawing the spinning 3D model.
+        /// </summary>
+        void DrawModel(GameTime gameTime)
+        {
+            float time = (float)gameTime.TotalGameTime.TotalSeconds;
+
+            Viewport viewport = graphics.GraphicsDevice.Viewport;
+            float aspectRatio = (float)viewport.Width / (float)viewport.Height;
+
+            // Create camera matrices.
+            Matrix world = Matrix.CreateRotationY(time * 0.42f);
+            
+            Matrix view = Matrix.CreateLookAt(new Vector3(750, 100, 0),
+                                              new Vector3(0, 300, 0),
+                                              Vector3.Up);
+
+            Matrix projection = Matrix.CreatePerspectiveFieldOfView(1, aspectRatio,
+                                                                    1, 10000);
+
+            // Look up the bone transform matrices.
+            Matrix[] transforms = new Matrix[model.Bones.Count];
+
+            model.CopyAbsoluteBoneTransformsTo(transforms);
+
+            // Draw the model.
+            foreach (ModelMesh mesh in model.Meshes)
+            {
+                foreach (BasicEffect effect in mesh.Effects)
+                {
+                    effect.World = transforms[mesh.ParentBone.Index] * world;
+                    effect.View = view;
+                    effect.Projection = projection;
+
+                    effect.EnableDefaultLighting();
+
+                    // Override the default specular color to make it nice and bright,
+                    // so we'll get some decent glints that the bloom can key off.
+                    effect.SpecularColor = Vector3.One;
+                }
+
+                mesh.Draw();
+            }
+        }
+
+
+        /// <summary>
+        /// Displays an overlay showing what the controls are,
+        /// and which settings are currently selected.
+        /// </summary>
+        void DrawOverlayText()
+        {
+            string text = "A = settings (" + bloom.Settings.Name + ")\n" +
+                          "B = toggle bloom (" + (bloom.Visible ? "on" : "off") + ")\n" +
+                          "X = show buffer (" + bloom.ShowBuffer.ToString() + ")";
+
+            spriteBatch.Begin();
+
+            // Draw the string twice to create a drop shadow, first colored black
+            // and offset one pixel to the bottom right, then again in white at the
+            // intended position. This makes text easier to read over the background.
+            spriteBatch.DrawString(spriteFont, text, new Vector2(65, 65), Color.Black);
+            spriteBatch.DrawString(spriteFont, text, new Vector2(64, 64), Color.White);
+
+            spriteBatch.End();
+        }
+
+
+        #endregion
+
+        #region Handle Input
+
+
+        /// <summary>
+        /// Handles input for quitting or changing the bloom settings.
+        /// </summary>
+        private void HandleInput()
+        {
+            lastKeyboardState = currentKeyboardState;
+            lastGamePadState = currentGamePadState;
+
+            currentKeyboardState = Keyboard.GetState();
+            currentGamePadState = GamePad.GetState(PlayerIndex.One);
+
+            // Check for exit.
+            if (currentKeyboardState.IsKeyDown(Keys.Escape) ||
+                currentGamePadState.Buttons.Back == ButtonState.Pressed)
+            {
+                Exit();
+            }
+
+            // Switch to the next bloom settings preset?
+            if ((currentGamePadState.Buttons.A == ButtonState.Pressed &&
+                 lastGamePadState.Buttons.A != ButtonState.Pressed) ||
+                (currentKeyboardState.IsKeyDown(Keys.A) &&
+                 lastKeyboardState.IsKeyUp(Keys.A)))
+            {
+                bloomSettingsIndex = (bloomSettingsIndex + 1) %
+                                     BloomSettings.PresetSettings.Length;
+             
+                bloom.Settings = BloomSettings.PresetSettings[bloomSettingsIndex];
+                bloom.Visible = true;
+            }
+
+            // Toggle bloom on or off?
+            if ((currentGamePadState.Buttons.B == ButtonState.Pressed &&
+                 lastGamePadState.Buttons.B != ButtonState.Pressed) ||
+                (currentKeyboardState.IsKeyDown(Keys.B) &&
+                 lastKeyboardState.IsKeyUp(Keys.B)))
+            {
+                bloom.Visible = !bloom.Visible;
+            }
+
+            // Cycle through the intermediate buffer debug display modes?
+            if ((currentGamePadState.Buttons.X == ButtonState.Pressed &&
+                 lastGamePadState.Buttons.X != ButtonState.Pressed) ||
+                (currentKeyboardState.IsKeyDown(Keys.X) &&
+                 lastKeyboardState.IsKeyUp(Keys.X)))
+            {
+                bloom.Visible = true;
+                bloom.ShowBuffer++;
+
+                if (bloom.ShowBuffer > BloomComponent.IntermediateBuffer.FinalResult)
+                    bloom.ShowBuffer= 0;
+            }
+        }
+
+
+        #endregion
+    }
+
+}

+ 16 - 0
BloomSample/Info.plist

@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleIdentifier</key>
+	<string>com.yourcompany.BloomSample</string>
+	<key>CFBundleName</key>
+	<string>BloomSample</string>
+	<key>CFBundleVersion</key>
+	<string>1</string>
+	<key>LSMinimumSystemVersion</key>
+	<string>10.6</string>
+	<key>NSPrincipalClass</key>
+	<string>NSApplication</string>
+</dict>
+</plist>

+ 45 - 0
BloomSample/Main.cs

@@ -0,0 +1,45 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using MonoMac.AppKit;
+using MonoMac.Foundation;
+
+namespace BloomPostprocess
+{
+	static class Program
+	{
+		/// <summary>
+		/// The main entry point for the application.
+		/// </summary>
+		static void Main (string[] args)
+		{
+			NSApplication.Init ();
+			
+			using (var p = new NSAutoreleasePool ()) {
+				NSApplication.SharedApplication.Delegate = new AppDelegate ();
+				NSApplication.Main (args);
+			}
+
+
+		}
+	}
+
+	class AppDelegate : NSApplicationDelegate
+	{
+		BloomPostprocessGame game;
+
+		public override void FinishedLaunching (MonoMac.Foundation.NSObject notification)
+		{
+			game = new BloomPostprocessGame ();
+			game.Run ();
+		}
+		
+		public override bool ApplicationShouldTerminateAfterLastWindowClosed (NSApplication sender)
+		{
+			return true;
+		}
+	}  
+}
+
+

+ 30 - 0
BloomSample/Properties/AssemblyInfo.cs

@@ -0,0 +1,30 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// AssemblyInfo.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+#endregion
+
+#region Using Statements
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+#endregion
+
+//Descriptive Assembly attributes
+[assembly: AssemblyTitle("Bloom Postprocess")]
+[assembly: AssemblyProduct("Bloom Postprocess")]
+[assembly: AssemblyDescription("This sample shows how to use bloom post-processing filters to add a glow effect over the top of an existing scene.")]
+[assembly: AssemblyCompany("Microsoft")]
+
+[assembly: AssemblyCopyright("Copyright © Microsoft 2007")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: AssemblyVersion("1.0.0.0")]
+
+//ComVisible is false for this component.
+[assembly: ComVisible(false)]
+[assembly: Guid("01a21a09-e2a4-473d-bc16-d7f157cc1c78")]
+

+ 22 - 0
MonoGame.Samples.MacOS.sln

@@ -105,6 +105,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FarseerPhysicsEngine", "Far
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FarseerSamples.MacOS", "FarseerSamples\FarseerSamples.MacOS.csproj", "{1221EA03-CCB7-4BC1-90C8-8B9816E1758D}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BloomSample.MacOS", "BloomSample\BloomSample.MacOS.csproj", "{A93553D9-11E5-4B0B-9809-4E4765D5FD8F}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -639,6 +641,26 @@ Global
 		{A82EAD58-40D7-49BE-8F24-09FEA34F9E55}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
 		{A82EAD58-40D7-49BE-8F24-09FEA34F9E55}.Release|x86.ActiveCfg = Release|Any CPU
 		{A82EAD58-40D7-49BE-8F24-09FEA34F9E55}.Release|x86.Build.0 = Release|Any CPU
+		{A93553D9-11E5-4B0B-9809-4E4765D5FD8F}.AppStore|Any CPU.ActiveCfg = AppStore|Any CPU
+		{A93553D9-11E5-4B0B-9809-4E4765D5FD8F}.AppStore|Any CPU.Build.0 = AppStore|Any CPU
+		{A93553D9-11E5-4B0B-9809-4E4765D5FD8F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{A93553D9-11E5-4B0B-9809-4E4765D5FD8F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{A93553D9-11E5-4B0B-9809-4E4765D5FD8F}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+		{A93553D9-11E5-4B0B-9809-4E4765D5FD8F}.Debug|iPhone.Build.0 = Debug|Any CPU
+		{A93553D9-11E5-4B0B-9809-4E4765D5FD8F}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{A93553D9-11E5-4B0B-9809-4E4765D5FD8F}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{A93553D9-11E5-4B0B-9809-4E4765D5FD8F}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{A93553D9-11E5-4B0B-9809-4E4765D5FD8F}.Debug|x86.Build.0 = Debug|Any CPU
+		{A93553D9-11E5-4B0B-9809-4E4765D5FD8F}.Distribution|Any CPU.ActiveCfg = Debug|Any CPU
+		{A93553D9-11E5-4B0B-9809-4E4765D5FD8F}.Distribution|Any CPU.Build.0 = Debug|Any CPU
+		{A93553D9-11E5-4B0B-9809-4E4765D5FD8F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{A93553D9-11E5-4B0B-9809-4E4765D5FD8F}.Release|Any CPU.Build.0 = Release|Any CPU
+		{A93553D9-11E5-4B0B-9809-4E4765D5FD8F}.Release|iPhone.ActiveCfg = Release|Any CPU
+		{A93553D9-11E5-4B0B-9809-4E4765D5FD8F}.Release|iPhone.Build.0 = Release|Any CPU
+		{A93553D9-11E5-4B0B-9809-4E4765D5FD8F}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{A93553D9-11E5-4B0B-9809-4E4765D5FD8F}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+		{A93553D9-11E5-4B0B-9809-4E4765D5FD8F}.Release|x86.ActiveCfg = Release|Any CPU
+		{A93553D9-11E5-4B0B-9809-4E4765D5FD8F}.Release|x86.Build.0 = Release|Any CPU
 		{AE483C29-042E-4226-BA52-D247CE7676DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{AE483C29-042E-4226-BA52-D247CE7676DA}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{AE483C29-042E-4226-BA52-D247CE7676DA}.Distribution|Any CPU.ActiveCfg = Debug|Any CPU