- Main Page
- Classes
- Files

- File List

# C:/Users/Andreas Schiffler/Desktop/SVN/NewGamePhysics/NewGamePhysics/GraphicalElements/BloomOverlay.cs

    00001 ﻿//-----------------------------------------------------------------------------
    00002 // BloomOverlay.cs
    00003 // (A. Schiffler, 2009)
    00004 //-----------------------------------------------------------------------------
    00005
    00006 namespace NewGamePhysics.GraphicalElements
    00007 {
    00008     using System;
    00009     using System.Collections.Generic;
    00010     using System.Linq;
    00011     using System.Text;
    00012
    00013     using Microsoft.Xna.Framework;
    00014     using Microsoft.Xna.Framework.Content;
    00015     using Microsoft.Xna.Framework.Graphics;
    00016
    00017     using NewGamePhysics.StateManager;
    00018     using NewGamePhysics.Utilities;
    00019     using NewGamePhysics.Mathematics;
    00020
    00024     public class BloomOverlay : GraphicalElementBase
    00025     {
    00029         private Effect extractEffect;
    00030
    00034         private Effect filterEffect;
    00035
    00039         private Effect combineEffect;
    00040
    00044         private ResolveTexture2D resolveTarget;
    00045
    00049         private RenderTarget2D renderTarget1;
    00050
    00054         private RenderTarget2D renderTarget2;
    00055
    00059         float[] tapWeights;
    00060
    00064         Vector2[] horizontalTapOffsets;
    00065
    00069         Vector2[] verticalTapOffsets;
    00070
    00074         EffectParameter weightsParameter;
    00075
    00079         EffectParameter offsetsParameter;
    00080
    00085         public BloomOverlay(
    00086             ScreenManager screenManager) : base(screenManager)
    00087         {
    00088         }
    00089
    00093         public void LoadContent()
    00094         {
    00095             this.extractEffect =
    00096                 this.ScreenManager.Game.Content.Load<Effect>("Effects/ThresholdAndRescale");
    00097             this.filterEffect =
    00098                 this.ScreenManager.Game.Content.Load<Effect>("Effects/TapFilter15");
    00099             this.combineEffect =
    00100                 this.ScreenManager.Game.Content.Load<Effect>("Effects/Combine");
    00101
    00102             // Look up the resolution and format of our main backbuffer.
    00103             PresentationParameters presentationParams =
    00104                 this.ScreenManager.GraphicsDevice.PresentationParameters;
    00105             int width = presentationParams.BackBufferWidth;
    00106             int height = presentationParams.BackBufferHeight;
    00107             SurfaceFormat format = presentationParams.BackBufferFormat;
    00108
    00109             // Create a texture for reading back the backbuffer contents.
    00110             this.resolveTarget = new ResolveTexture2D(
    00111                 this.ScreenManager.GraphicsDevice,
    00112                 width,
    00113                 height,
    00114                 1,
    00115                 format);
    00116
    00117             // Create half-size bloom render targets
    00118             width /= 2;
    00119             height /= 2;
    00120             renderTarget1 = new RenderTarget2D(
    00121                 this.ScreenManager.GraphicsDevice,
    00122                 width,
    00123                 height,
    00124                 1,
    00125                 format,
    00126                 this.ScreenManager.GraphicsDevice.DepthStencilBuffer.MultiSampleType,
    00127                 this.ScreenManager.GraphicsDevice.PresentationParameters.MultiSampleQuality);
    00128             renderTarget2 = new RenderTarget2D(
    00129                 this.ScreenManager.GraphicsDevice,
    00130                 width,
    00131                 height,
    00132                 1,
    00133                 format,
    00134                 this.ScreenManager.GraphicsDevice.DepthStencilBuffer.MultiSampleType,
    00135                 this.ScreenManager.GraphicsDevice.PresentationParameters.MultiSampleQuality);
    00136
    00137             // Get filter parameters
    00138             this.weightsParameter = this.filterEffect.Parameters["TapWeights"];
    00139             this.offsetsParameter = this.filterEffect.Parameters["TapOffsets"];
    00140
    00141             // Calculate steps in filter
    00142             int tapCount = weightsParameter.Elements.Count;
    00143             int tapSteps = tapCount / 2;
    00144
    00145             // Calculate tap filter weights and offsets
    00146             this.tapWeights = new float[tapCount];
    00147             this.horizontalTapOffsets = new Vector2[tapCount];
    00148             this.verticalTapOffsets = new Vector2[tapCount];
    00149             float dx = 1.0f / width;
    00150             float dy = 1.0f / height;
    00151             double size = 2.0;
    00152             float weightSum = (float)Gaussian.DistributionValue(size, 0.0);
    00153             this.tapWeights[0] = weightSum;
    00154             this.verticalTapOffsets[0] = new Vector2();
    00155             this.horizontalTapOffsets[0] = new Vector2();
    00156             for (int i = 0; i < tapSteps; i++)
    00157             {
    00158                 // Store weights for the positive and negative taps.
    00159                 float weight = (float)Gaussian.DistributionValue(size, (double)(i + 1));
    00160                 int left = i * 2 + 1;
    00161                 int right = i * 2 + 2;
    00162                 this.tapWeights[right] = weight;
    00163                 this.tapWeights[left] = weight;
    00164                 weightSum += (2.0f * weight);
    00165
    00166                 // Store Offsets
    00167                 float sampleOffset = right + 0.5f;
    00168                 this.horizontalTapOffsets[right] = new Vector2(dx, 0.0f) * sampleOffset;
    00169                 this.horizontalTapOffsets[left] = new Vector2(-dx, 0.0f) * sampleOffset;
    00170                 this.verticalTapOffsets[right] = new Vector2(0.0f, dy) * sampleOffset;
    00171                 this.verticalTapOffsets[left] = new Vector2(0.0f, -dy) * sampleOffset;
    00172             }
    00173
    00174             // Normalize weights
    00175             for (int i = 1; i < tapCount; i++)
    00176             {
    00177                 this.tapWeights[i] /= weightSum;
    00178             }
    00179         }
    00180
    00184         public void UnloadContent()
    00185         {
    00186             resolveTarget.Dispose();
    00187             renderTarget1.Dispose();
    00188             renderTarget2.Dispose();
    00189         }
    00190
    00196         public void Draw(GameTime gameTime)
    00197         {
    00198             // Resolve the scene into a texture, so we can
    00199             // use it as input data for the bloom processing.
    00200             this.ScreenManager.GraphicsDevice.ResolveBackBuffer(resolveTarget);
    00201
    00202             // Pass 1: draw the scene into rendertarget 1, using a
    00203             // shader that extracts only the brightest parts of the image.
    00204             this.extractEffect.Parameters["threshold"].SetValue(0.0f);
    00205             DrawQuadWithEffect(resolveTarget, renderTarget1, this.extractEffect);
    00206
    00207             // Pass 2: draw from rendertarget 1 into rendertarget 2,
    00208             // using a shader to apply a horizontal gaussian blur filter.
    00209             // Look up the sample weight and offset effect parameters.
    00210             this.weightsParameter.SetValue(tapWeights);
    00211             this.offsetsParameter.SetValue(horizontalTapOffsets);
    00212             DrawQuadWithEffect(renderTarget1.GetTexture(), renderTarget2, this.filterEffect);
    00213
    00214             // Pass 3: draw from rendertarget 2 back into rendertarget 1,
    00215             // using a shader to apply a vertical gaussian blur filter.
    00216             this.weightsParameter.SetValue(tapWeights);
    00217             this.offsetsParameter.SetValue(verticalTapOffsets);
    00218             DrawQuadWithEffect(renderTarget2.GetTexture(), renderTarget1, this.filterEffect);
    00219
    00220             // Pass 4: draw both rendertarget 1 and the original scene
    00221             // image back into the main backbuffer, using a shader that
    00222             // combines them to produce the final bloomed result
    00223             this.ScreenManager.GraphicsDevice.Textures[1] = resolveTarget;
    00224             this.combineEffect.Parameters["CombineIntensity"].SetValue(2.0f);
    00225             Viewport viewport = this.ScreenManager.GraphicsDevice.Viewport;
    00226             this.ScreenManager.SpriteBatch.Begin(
    00227                 SpriteBlendMode.None,
    00228                 SpriteSortMode.Immediate,
    00229                 SaveStateMode.None);
    00230             this.combineEffect.Begin();
    00231             this.combineEffect.CurrentTechnique.Passes[0].Begin();
    00232             this.ScreenManager.SpriteBatch.Draw(
    00233                 renderTarget1.GetTexture(),
    00234                 new Rectangle(0, 0, viewport.Width, viewport.Height),
    00235                 Color.White);
    00236             this.ScreenManager.SpriteBatch.End();
    00237             this.combineEffect.CurrentTechnique.Passes[0].End();
    00238             this.combineEffect.End();
    00239         }
    00240
    00247         private void DrawQuadWithEffect(
    00248             Texture2D texture,
    00249             RenderTarget2D renderTarget,
    00250             Effect effect)
    00251         {
    00252             this.ScreenManager.GraphicsDevice.SetRenderTarget(0, renderTarget);
    00253             this.ScreenManager.SpriteBatch.Begin(
    00254                 SpriteBlendMode.None,
    00255                 SpriteSortMode.Immediate,
    00256                 SaveStateMode.None);
    00257             effect.Begin();
    00258             effect.CurrentTechnique.Passes[0].Begin();
    00259             this.ScreenManager.SpriteBatch.Draw(
    00260                 texture,
    00261                 new Rectangle(0, 0, renderTarget.Width, renderTarget.Height),
    00262                 Color.White);
    00263             this.ScreenManager.SpriteBatch.End();
    00264             effect.CurrentTechnique.Passes[0].End();
    00265             effect.End();
    00266             this.ScreenManager.GraphicsDevice.SetRenderTarget(0, null);
    00267         }
    00268     }
    00269 }