00001
00002
00003
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
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
00110 this.resolveTarget = new ResolveTexture2D(
00111 this.ScreenManager.GraphicsDevice,
00112 width,
00113 height,
00114 1,
00115 format);
00116
00117
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
00138 this.weightsParameter = this.filterEffect.Parameters["TapWeights"];
00139 this.offsetsParameter = this.filterEffect.Parameters["TapOffsets"];
00140
00141
00142 int tapCount = weightsParameter.Elements.Count;
00143 int tapSteps = tapCount / 2;
00144
00145
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
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
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
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
00199
00200 this.ScreenManager.GraphicsDevice.ResolveBackBuffer(resolveTarget);
00201
00202
00203
00204 this.extractEffect.Parameters["threshold"].SetValue(0.0f);
00205 DrawQuadWithEffect(resolveTarget, renderTarget1, this.extractEffect);
00206
00207
00208
00209
00210 this.weightsParameter.SetValue(tapWeights);
00211 this.offsetsParameter.SetValue(horizontalTapOffsets);
00212 DrawQuadWithEffect(renderTarget1.GetTexture(), renderTarget2, this.filterEffect);
00213
00214
00215
00216 this.weightsParameter.SetValue(tapWeights);
00217 this.offsetsParameter.SetValue(verticalTapOffsets);
00218 DrawQuadWithEffect(renderTarget2.GetTexture(), renderTarget1, this.filterEffect);
00219
00220
00221
00222
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 }