Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
LightShaftsPlugin.cs
Go to the documentation of this file.
1 // Copyright (c) 2011 Silicon Studio
2 
3 using System;
4 using System.Collections.Generic;
5 
6 using SiliconStudio.Paradox.DataModel;
7 using SiliconStudio.Paradox.Effects.Data;
8 using SiliconStudio.Paradox.Effects.Modules;
9 using SiliconStudio.Paradox.Games;
10 using SiliconStudio.Paradox.Graphics;
11 using SiliconStudio.Core;
12 using SiliconStudio.Core.Mathematics;
13 using SiliconStudio.Paradox.Shaders;
14 
15 namespace SiliconStudio.Paradox.Effects
16 {
17  /// <summary>
18  /// Light Shaft plugin.
19  /// </summary>
21  {
22  private EffectOld lightShaftsEffect;
23 
24  private RenderPass boundingBoxPass;
25  private RenderPass minMaxPass;
26  private RenderPass lightShaftPass;
27  private RenderPass filterUpscalePass;
28 
29  /// <summary>
30  /// Initializes a new instance of class <see cref="LightShaftsPlugin"/>.
31  /// </summary>
32  public LightShaftsPlugin() : this(null)
33  {
34  }
35 
36  /// <summary>
37  /// Initializes a new instance of class <see cref="LightShaftsPlugin"/>.
38  /// </summary>
39  public LightShaftsPlugin(string name)
40  : base(name)
41  {
42  BoundingBoxes = new List<Mesh>();
43  LightColor = new Color3(1, 1, 1);
44  ExtinctionFactor = 0.001f;
45  ExtinctionRatio = 0.9f;
46  DensityFactor = 0.01f;
47  StepCount = 8;
48  }
49 
50  public ShadowMap ShadowMap { get; set; }
51 
52  public Color3 LightColor
53  {
54  get
55  {
56  return Parameters.TryGet(LightKeys.LightColor);
57  }
58  set
59  {
60  Parameters.Set(LightKeys.LightColor, value);
61  }
62  }
63 
64  public float ExtinctionFactor
65  {
66  get
67  {
68  return Parameters.TryGet(PostEffectLightShaftsKeys.ExtinctionFactor);
69  }
70  set
71  {
72  Parameters.Set(PostEffectLightShaftsKeys.ExtinctionFactor, value);
73  }
74  }
75 
76  public float ExtinctionRatio
77  {
78  get
79  {
80  return Parameters.TryGet(PostEffectLightShaftsKeys.ExtinctionRatio);
81  }
82  set
83  {
84  Parameters.Set(PostEffectLightShaftsKeys.ExtinctionRatio, value);
85  }
86  }
87 
88  public float DensityFactor
89  {
90  get
91  {
92  return Parameters.TryGet(PostEffectLightShaftsKeys.DensityFactor);
93  }
94  set
95  {
96  Parameters.Set(PostEffectLightShaftsKeys.DensityFactor, value);
97  }
98  }
99 
100  public int StepCount { get; set; }
101 
102 
103  public ParameterCollection ViewParameters { get; set; }
104 
106  {
107  get;
108  set;
109  }
110 
111  public DepthStencilBuffer DepthStencil { get; set; }
112 
113  public List<Mesh> BoundingBoxes { get; private set; }
114 
115  public override void Initialize()
116  {
117  base.Initialize();
118 
119  boundingBoxPass = new RenderPass("BoundingBoxPass");
120  minMaxPass = new RenderPass("MinmaxPass");
121  lightShaftPass = new RenderPass("LightShaftPass");
122  filterUpscalePass = new RenderPass("UpscalePass");
123  RenderPass.AddPass(boundingBoxPass, minMaxPass, lightShaftPass, filterUpscalePass);
124 
125  var useUpScaling = false;
126 
127  var bbRenderTargetPlugin = new RenderTargetsPlugin("BoundingBoxRenderTargetPlugin")
128  {
129  EnableSetTargets = true,
130  EnableClearTarget = true,
131  RenderPass = boundingBoxPass,
132  Services = Services,
133  };
134 
135  var minMaxEffectBuilder = this.EffectSystemOld.BuildEffect("MinMax")
136  .Using(new MinMaxShaderPlugin("MinMaxShaderPlugin") { RenderPassPlugin = bbRenderTargetPlugin })
137  .Using(new BasicShaderPlugin("TransformationWVP") { RenderPassPlugin = bbRenderTargetPlugin });
138 
139 
140  var minmaxEffectBuilder = this.EffectSystemOld.BuildEffect("LightShaftsMinMax")
141  .Using(new PostEffectSeparateShaderPlugin() { RenderPass = minMaxPass })
142  .Using(new BasicShaderPlugin("ForwardShadowMapBase") { RenderPass = minMaxPass })
143  .Using(new BasicShaderPlugin(new ShaderClassSource("PostEffectMinMax", "ShadowMapUtils.shadowMapTexture", "PointSampler", 4, 4, 0.0, 1.0)) { RenderPass = minMaxPass });
144 
145  var lightShaftsEffectBuilder = this.EffectSystemOld.BuildEffect("LightShafts")
146  .Using(new PostEffectSeparateShaderPlugin() { RenderPass = lightShaftPass })
147  .Using(new StateShaderPlugin() { UseBlendState = !useUpScaling, RenderPass = lightShaftPass })
148  //.Using(new BasicShaderPlugin(new ShaderClassSource("PostEffectLightShafts", Debug ? 1 : 0, RenderContext.IsZReverse ? 1 : 0, StepCount)) { RenderPass = lightShaftPass });
149  .Using(new BasicShaderPlugin(new ShaderClassSource("PostEffectLightShafts", Debug ? 1 : 0, false ? 1 : 0, StepCount)) { RenderPass = lightShaftPass });
150 
151  if (OfflineCompilation)
152  {
153  minMaxEffectBuilder.InstantiatePermutation();
154  minmaxEffectBuilder.InstantiatePermutation();
155  lightShaftsEffectBuilder.InstantiatePermutation();
156  return;
157  }
158 
159  Parameters.AddSources(ViewParameters);
160  Parameters.Set(RenderTargetKeys.DepthStencilSource, DepthStencil.Texture);
161  Parameters.Set(TexturingKeys.Sampler, GraphicsDevice.SamplerStates.PointClamp);
162 
163  // BoundingBox prepass
164  var gbufferDesc = RenderTarget.Description;
165  var bbRenderTarget = Texture2D.New(GraphicsDevice, gbufferDesc.Width / 8, gbufferDesc.Height / 8, PixelFormat.R32G32_Float, TextureFlags.ShaderResource | TextureFlags.RenderTarget);
166 
167  // Use MinMax Plugin
168  bbRenderTargetPlugin.RenderTarget = bbRenderTarget.ToRenderTarget();
169  bbRenderTargetPlugin.Parameters.AddSources(Parameters);
170  bbRenderTargetPlugin.Apply();
171 
172  EffectOld minMaxEffect = minMaxEffectBuilder.InstantiatePermutation();
173 
174  // Add meshes
175  foreach (var bbMeshData in BoundingBoxes)
176  {
177  // Mesh for MinPass
178  var bbMesh = new EffectMesh(minMaxEffect, bbMeshData).KeepAliveBy(this);
179  // Add mesh
180  // boundingBoxPass.AddPass(bbMesh.EffectMeshPasses[0].EffectPass);
181  RenderSystem.GlobalMeshes.AddMesh(bbMesh);
182  }
183 
184  // MinMax render target
185  var minMaxRenderTarget = Texture2D.New(GraphicsDevice, 256, 256, PixelFormat.R32G32_Float, TextureFlags.ShaderResource | TextureFlags.RenderTarget);
186  minMaxPass.Parameters = new ParameterCollection(null);
187  minMaxPass.Parameters.AddSources(ShadowMap.Parameters);
188  minMaxPass.Parameters.AddSources(Parameters);
189  minMaxPass.Parameters.AddDynamic(PostEffectMinMaxKeys.MinMaxCoords, ParameterDynamicValue.New(LightingPlugin.CascadeTextureCoords, (ref Vector4[] cascadeTextureCoords, ref Vector4 output) =>
190  {
191  output = cascadeTextureCoords[0];
192  }, autoCheckDependencies: false));
193 
194  EffectOld minmaxEffect = minmaxEffectBuilder.InstantiatePermutation();
195 
196  var minMaxMesh = new EffectMesh(minmaxEffect).KeepAliveBy(this);
197  minMaxMesh.Parameters.Set(RenderTargetKeys.RenderTarget, minMaxRenderTarget.ToRenderTarget());
198  RenderSystem.GlobalMeshes.AddMesh(minMaxMesh);
199 
200  // Light Shafts effect
201  var blendStateDesc = new BlendStateDescription();
202  blendStateDesc.SetDefaults();
203  blendStateDesc.AlphaToCoverageEnable = false;
204  blendStateDesc.IndependentBlendEnable = false;
205  blendStateDesc.RenderTargets[0].BlendEnable = true;
206 
207  blendStateDesc.RenderTargets[0].AlphaBlendFunction = BlendFunction.Add;
208  blendStateDesc.RenderTargets[0].AlphaSourceBlend = Blend.One;
209  blendStateDesc.RenderTargets[0].AlphaDestinationBlend = Blend.One;
210 
211  blendStateDesc.RenderTargets[0].ColorBlendFunction = BlendFunction.Add;
212  blendStateDesc.RenderTargets[0].ColorSourceBlend = Blend.One;
213  blendStateDesc.RenderTargets[0].ColorDestinationBlend = Blend.One;
214 
215  blendStateDesc.RenderTargets[0].ColorWriteChannels = ColorWriteChannels.All;
216 
217  var additiveBlending = BlendState.New(GraphicsDevice, blendStateDesc);
218  additiveBlending.Name = "LightShaftAdditiveBlend";
219 
220  var shaftRenderTarget = useUpScaling ? Texture2D.New(GraphicsDevice, gbufferDesc.Width / 2, gbufferDesc.Height / 2, PixelFormat.R16G16B16A16_Float, TextureFlags.ShaderResource | TextureFlags.RenderTarget).ToRenderTarget() : RenderTarget;
221 
222 
223  lightShaftPass.Parameters = new ParameterCollection();
224  lightShaftPass.Parameters.AddSources(ShadowMap.Parameters);
225  lightShaftPass.Parameters.AddSources(Parameters);
226 
227  this.lightShaftsEffect = lightShaftsEffectBuilder.InstantiatePermutation();
228 
229 
230  var mesh = new EffectMesh(lightShaftsEffect).KeepAliveBy(this);
231  mesh.Parameters.Set(TexturingKeys.Texture0, minMaxRenderTarget);
232  mesh.Parameters.Set(TexturingKeys.Texture1, bbRenderTarget);
233  mesh.Parameters.Set(RenderTargetKeys.RenderTarget, shaftRenderTarget);
234 
235  if (!useUpScaling)
236  {
237  mesh.Parameters.Set(EffectPlugin.BlendStateKey, additiveBlending);
238  }
239  RenderSystem.GlobalMeshes.AddMesh(mesh);
240 
241  // Bilateral Gaussian filtering for up-sampling
242  if (useUpScaling)
243  {
244  var bbRenderTargetUpScaleH = Texture2D.New(GraphicsDevice, gbufferDesc.Width, gbufferDesc.Height / 2, PixelFormat.R16G16B16A16_Float, TextureFlags.ShaderResource | TextureFlags.RenderTarget);
245  var bbRenderTargetUpScaleV = RenderTarget;
246  //var bbRenderTargetUpScaleV = GraphicsDevice.RenderTarget2D.New(gbufferDesc.Width, gbufferDesc.Height, PixelFormat.HalfVector4);
247 
248  var blurEffects = new EffectOld[] {
249  this.EffectSystemOld.BuildEffect("BilateralGaussianFiltering")
250  .Using(new PostEffectSeparateShaderPlugin())
251  .Using(new BasicShaderPlugin( new ShaderClassSource("PostEffectBilateralGaussian", 0))),
252  this.EffectSystemOld.BuildEffect("BilateralGaussianFiltering")
253  .Using(new StateShaderPlugin() { UseBlendState = true })
254  .Using(new PostEffectSeparateShaderPlugin())
255  .Using(new BasicShaderPlugin( new ShaderClassSource("PostEffectBilateralGaussian", 1))),
256  };
257 
258  Texture2D textureSourceH = (Texture2D)shaftRenderTarget.Texture;
259  Texture2D textureSourceV = bbRenderTargetUpScaleH;
260  RenderTarget renderTargetH = bbRenderTargetUpScaleH.ToRenderTarget();
261  RenderTarget renderTargetV = bbRenderTargetUpScaleV;
262 
263  var blurQuadMesh = new EffectMesh[2];
264  for (int i = 0; i < 2; ++i)
265  {
266  blurQuadMesh[i] = new EffectMesh(blurEffects[i]).KeepAliveBy(this);
267  filterUpscalePass.AddPass(blurQuadMesh[i].EffectPass);
268  RenderSystem.GlobalMeshes.AddMesh(blurQuadMesh[i]);
269  }
270 
271  blurQuadMesh[0].Parameters.Set(TexturingKeys.Texture0, textureSourceH);
272  blurQuadMesh[1].Parameters.Set(TexturingKeys.Texture0, textureSourceV);
273  blurQuadMesh[0].Parameters.Set(RenderTargetKeys.RenderTarget, renderTargetH);
274  blurQuadMesh[1].Parameters.Set(RenderTargetKeys.RenderTarget, renderTargetV);
275 
276  // Additive blending for 2nd render target
277  blurQuadMesh[1].Parameters.Set(EffectPlugin.BlendStateKey, additiveBlending);
278  }
279  }
280 
281  /// <summary>
282  /// Offset of the shadow map.
283  /// </summary>
284  internal static readonly ParameterKey<Vector3> ShadowLightOffset = ParameterKeys.Value(ParameterDynamicValue.New<Vector3, ShadowMapData>(LightingPlugin.ViewProjectionArray, CalculateShadowLightOffset));
285 
286  /// <summary>
287  /// Offset of the shadow map.
288  /// </summary>
289  internal static readonly ParameterKey<Matrix> ShadowViewProjection = ParameterKeys.Value(ParameterDynamicValue.New<Matrix, ShadowMapData>(LightingPlugin.ViewProjectionArray, CalculateShadowViewProjection));
290 
291  /// <summary>
292  /// Size factor of the current shadow map texture.
293  /// </summary>
294  internal static readonly ParameterKey<Vector4> ShadowTextureFactor = ParameterKeys.Value(ParameterDynamicValue.New<Vector4, Vector4[]>(LightingPlugin.CascadeTextureCoords, CalculateShadowTextureFactor));
295 
296  private static void CalculateShadowViewProjection(ref ShadowMapData cascadeData, ref Matrix output)
297  {
298  output = cascadeData.ViewProjCaster0;
299  }
300 
301  private static void CalculateShadowLightOffset(ref ShadowMapData cascadeData, ref Vector3 output)
302  {
303  output = cascadeData.Offset0;
304  }
305 
306  private static void CalculateShadowTextureFactor(ref Vector4[] textureCoords, ref Vector4 output)
307  {
308  output = textureCoords[0];
309  }
310  }
311 }
Key of an effect parameter.
Definition: ParameterKey.cs:15
TODO: Update summary.
LightShaftsPlugin()
Initializes a new instance of class LightShaftsPlugin.
Represents a color in the form of rgb.
Definition: Color3.cs:41
Basic shader plugin built directly from shader source file.
Represents a three dimensional mathematical vector.
Definition: Vector3.cs:42
Represents a ShadowMap.
Definition: ShadowMap.cs:11
Performs primitive-based rendering, creates resources, handles system-level variables, adjusts gamma ramp levels, and creates shaders. See The+GraphicsDevice+class to learn more about the class.
Represents a four dimensional mathematical vector.
Definition: Vector4.cs:42
LightShaftsPlugin(string name)
Initializes a new instance of class LightShaftsPlugin.
A Texture 2D frontend to SharpDX.Direct3D11.Texture2D.
Definition: Texture2D.cs:37
Level10 render pass using a depth buffer and a render target.
ColorWriteChannels
Identify which components of each pixel of a render target are writable during blending.
SiliconStudio.Core.Mathematics.Vector3 Vector3
RenderPass is a hierarchy that defines how to collect and render meshes.
Definition: RenderPass.cs:19
A container to handle a hierarchical collection of effect variables.
Represents a 4x4 mathematical matrix.
Definition: Matrix.cs:47