Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
LightingPrepassShaderPlugin.cs
Go to the documentation of this file.
1 // Copyright (c) 2011 Silicon Studio
2 
3 using System;
4 using System.Collections.Generic;
5 using System.Linq;
6 using System.Runtime.InteropServices;
7 using SiliconStudio.Paradox.Effects.Data;
8 using SiliconStudio.Paradox.Effects.Modules;
9 using SiliconStudio.Paradox.Graphics;
10 using SiliconStudio.Core.Mathematics;
11 using SiliconStudio.Paradox.Shaders;
12 
15 
16 namespace SiliconStudio.Paradox.Effects
17 {
18  internal class LightingPrepassShaderPlugin : ShaderPlugin<LightingPrepassPlugin>
19  {
20  public static readonly ParameterKey<LightData> LightInfos = ParameterKeys.ArrayValue(new LightData[64]);
21  public static readonly ParameterKey<int> LightCount = LightPrepassKeys.LightCount;
22  public static readonly ParameterKey<int> TileIndex = LightPrepassKeys.TileIndex;
23 
24  [ThreadStatic]
25  private static LightData[] currentTiles;
26 
27 
28  public LightingPrepassShaderPlugin()
29  {
30  }
31 
32  public LightingPrepassShaderPlugin(string name)
33  : base(name)
34  {
35  }
36 
37  public bool Debug { get; set; }
38 
39  public override void SetupShaders(EffectMesh effectMesh)
40  {
41  // Use the standard or debug shader
42  var lightPrepassShader = new ShaderClassSource(string.Format("LightPrepass{0}", Debug ? "Debug" : string.Empty));
43  DefaultShaderPass.Shader.Mixins.Add(lightPrepassShader);
44  DefaultShaderPass.Shader.Compositions.Add("DiffuseColor", new ShaderClassSource("ComputeBRDFColorFresnel"));
45  DefaultShaderPass.Shader.Compositions.Add("DiffuseLighting", new ShaderClassSource("ComputeBRDFDiffuseLambert"));
46  DefaultShaderPass.Shader.Compositions.Add("SpecularColor", new ShaderClassSource("ComputeBRDFColor"));
47  DefaultShaderPass.Shader.Compositions.Add("SpecularLighting", new ShaderClassSource("ComputeBRDFColorSpecularBlinnPhong"));
48  }
49 
50  public override void SetupResources(EffectMesh effectMesh)
51  {
52  var blendStateDesc = new BlendStateDescription();
53  blendStateDesc.SetDefaults();
54  blendStateDesc.AlphaToCoverageEnable = false;
55  blendStateDesc.IndependentBlendEnable = false;
56  blendStateDesc.RenderTargets[0].BlendEnable = true;
57 
58  blendStateDesc.RenderTargets[0].AlphaBlendFunction = BlendFunction.Add;
59  blendStateDesc.RenderTargets[0].AlphaSourceBlend = Blend.One;
60  blendStateDesc.RenderTargets[0].AlphaDestinationBlend = Blend.One;
61 
62  blendStateDesc.RenderTargets[0].ColorBlendFunction = BlendFunction.Add;
63  blendStateDesc.RenderTargets[0].ColorSourceBlend = Blend.One;
64  blendStateDesc.RenderTargets[0].ColorDestinationBlend = Blend.One;
65 
66  blendStateDesc.RenderTargets[0].ColorWriteChannels = ColorWriteChannels.All;
67 
68  // "LightPrePassAdditiveBlend"
69  Effect.Parameters.Set(BlendStateKey, BlendState.New(GraphicsDevice, blendStateDesc));
70 
71  if (Debug)
72  {
73  var rasterizer = RasterizerState.New(GraphicsDevice, new RasterizerStateDescription() { FillMode = FillMode.Wireframe });
74  rasterizer.Name = "LightPrePassWireFrame";
75  Effect.Parameters.Set(RasterizerStateKey, rasterizer);
76  }
77 
78  Effect.PrepareMesh += SetupMeshResources;
79  Effect.UpdateMeshData += UpdateMeshResources;
80  }
81 
82  private void SetupMeshResources(EffectOld effect, EffectMesh effectMesh)
83  {
84  // Generates a quad for post effect rendering (should be utility function)
85  var vertices = new[]
86  {
87  -1.0f, 1.0f,
88  1.0f, 1.0f,
89  -1.0f, -1.0f,
90  1.0f, -1.0f,
91  };
92 
93  // Use the quad for this effectMesh
94  effectMesh.MeshData.Draw = new MeshDraw
95  {
96  DrawCount = 4,
97  PrimitiveType = PrimitiveType.TriangleStrip,
98  VertexBuffers = new[]
99  {
101  }
102  };
103  }
104 
105  private void UpdateMeshResources(EffectOld effect, EffectMesh effectMesh)
106  {
107  var oldStartPass = effectMesh.Render;
108 
109  // TODO: Integrate StageStatus.Apply in API
110  // Temporarely, use AddEnd as StageStatus.Apply is appended to AddStart after this code is executed
111  effectMesh.Render.Set = (context) =>
112  {
113  int tileIndex = context.Parameters.Get(TileIndex);
114  var tiles = RenderPassPlugin.Tiles[tileIndex];
115 
116  var mainParameters = RenderPassPlugin.GBufferPlugin.MainPlugin.ViewParameters;
117 
118  Matrix projMatrix;
119  mainParameters.Get(TransformationKeys.Projection, out projMatrix);
120  context.Parameters.Set(TransformationKeys.Projection, projMatrix);
121 
122  // Use depth buffer generated by GBuffer pass
123  context.Parameters.Set(RenderTargetKeys.DepthStencilSource, RenderPassPlugin.GBufferPlugin.DepthStencil.Texture);
124 
125  if (currentTiles == null)
126  currentTiles = new LightData[LightingPrepassPlugin.MaxLightsPerTileDrawCall];
127 
128  //((Paradox.Framework.Graphics.Direct3D.GraphicsDevice)context.GraphicsDevice).NativeDeviceContext.InputAssembler.InputLayout = null;
129 
130  for (int i = 0; i < (tiles.Count + LightingPrepassPlugin.MaxLightsPerTileDrawCall - 1) / LightingPrepassPlugin.MaxLightsPerTileDrawCall; ++i)
131  {
132  int lightCount = Math.Min(tiles.Count - i * LightingPrepassPlugin.MaxLightsPerTileDrawCall, LightingPrepassPlugin.MaxLightsPerTileDrawCall);
133  //effectMesh.Parameters.Set(LightCount, lightCount);
134  //effectMesh.Parameters.Set(LightInfos, RenderPassPlugin.Tiles[tileIndex].Skip(i * LightingPrepassPlugin.MaxLightsPerTileDrawCall).Take(lightCount).ToArray());
135 
136  var startLightIndex = i * LightingPrepassPlugin.MaxLightsPerTileDrawCall;
137  for (int lightIndex = 0; lightIndex < lightCount; ++lightIndex)
138  currentTiles[lightIndex] = RenderPassPlugin.Tiles[tileIndex][startLightIndex + lightIndex];
139  context.Parameters.Set(LightCount, lightCount);
140  context.Parameters.Set(LightInfos, currentTiles);
141 
142  // Render this tile
143  oldStartPass.Invoke(context);
144  }
145  };
146  }
147 
148  [StructLayout(LayoutKind.Sequential, Pack = 4)]
149  public struct LightData
150  {
152  public float LightRadius;
153 
155  public float LightIntensity;
156 
157  }
158  }
159 }
The layout of a vertex buffer with a set of VertexElement.
Represents a two dimensional mathematical vector.
Definition: Vector2.cs:42
Represents a color in the form of rgb.
Definition: Color3.cs:41
Represents a three dimensional mathematical vector.
Definition: Vector3.cs:42
All-in-One Buffer class linked SharpDX.Direct3D11.Buffer.
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.
static Buffer New(GraphicsDevice device, BufferDescription description, PixelFormat viewFormat=PixelFormat.None)
Creates a new Buffer instance.
Definition: Buffer.cs:343
static VertexElement Position(PixelFormat format, int offsetInBytes=AppendAligned)
Declares a VertexElement with the semantic "POSITION".
ColorWriteChannels
Identify which components of each pixel of a render target are writable during blending.
SiliconStudio.Paradox.Graphics.PrimitiveType PrimitiveType
PrimitiveType
Defines how vertex data is ordered.
SiliconStudio.Paradox.Graphics.Buffer Buffer
A description of a single element for the input-assembler stage. This structure is related to Direct3...
Binding structure that specifies a vertex buffer and other per-vertex parameters (such as offset and ...
Represents a 4x4 mathematical matrix.
Definition: Matrix.cs:47