4 using System.Collections.Generic;
5 using SiliconStudio.Paradox.DataModel;
6 using SiliconStudio.Paradox.Effects.Modules;
7 using SiliconStudio.Paradox.Games;
8 using SiliconStudio.Paradox.Graphics;
9 using SiliconStudio.Core;
10 using SiliconStudio.Core.Collections;
11 using SiliconStudio.Core.Mathematics;
14 namespace SiliconStudio.
Paradox.Effects
21 private EffectOld[] lightDeferredEffects =
new EffectOld[2];
27 public const int TileCountX = 16;
28 public const int TileCountY = 10;
29 public const int MaxLightsPerTileDrawCall = 64;
48 public EffectOld Lights {
get;
private set; }
50 public string[] BasePlugins {
get; set; }
60 public override void Load()
64 Parameters.AddSources(GBufferPlugin.MainPlugin.ViewParameters);
66 Lights = this.EffectSystemOld.BuildEffect(
"Lights").Using(
new LightPlugin()).InstantiatePermutation();
69 for (
int i = 0; i < 2; ++i)
77 debugRenderPass =
new RenderPass(
"LightPrePassDebug").KeepAliveBy(ActiveObjects);
78 GBufferPlugin.MainPlugin.RenderPass.AddPass(debugRenderPass);
82 var renderPass = i == 1 ? debugRenderPass :
RenderPass;
84 var lightDeferredEffectBuilder = this.EffectSystemOld.BuildEffect(
"LightPrePass" + (debug ?
"Debug" : string.Empty)).KeepAliveBy(ActiveObjects);
85 foreach (var effectPlugin
in BasePlugins)
87 lightDeferredEffectBuilder.Using(
new BasicShaderPlugin(effectPlugin) { Services = Services,
RenderPassPlugin =
this,
RenderPass = renderPass });
89 lightDeferredEffectBuilder.Using(
new LightingPrepassShaderPlugin(
"LightPreShaderPass" + (debug ?
"Debug" :
string.Empty)) { Services = Services,
RenderPassPlugin =
this,
RenderPass = renderPass, Debug = debug });
91 lightDeferredEffects[i] = lightDeferredEffectBuilder.InstantiatePermutation().KeepAliveBy(ActiveObjects);
94 if (OfflineCompilation)
98 var mainBackBuffer = graphicsDeviceService.GraphicsDevice.BackBuffer;
99 var lightTexture = Texture2D.New(
GraphicsDevice, mainBackBuffer.Width, mainBackBuffer.Height, PixelFormat.R16G16B16A16_Float, TextureFlags.ShaderResource | TextureFlags.RenderTarget);
100 lightTexture.Name =
"LightTexture";
101 LightTexture = lightTexture.ToRenderTarget();
104 Parameters.Set(LightDeferredShadingKeys.LightTexture, lightTexture);
110 GBufferPlugin.MainTargetPlugin.Parameters.Set(LightDeferredShadingKeys.LightTexture, lightTexture);
114 CreatePrePassMesh(debugRenderPass,
true);
119 GBufferPlugin.MainPlugin.RenderPass.RemovePass(debugRenderPass);
120 debugRenderPass = null;
125 private void CreatePrePassMesh(
RenderPass renderPass,
bool debug)
127 var lightDeferredEffect = lightDeferredEffects[debug ? 1 : 0];
130 for (
int i = 0; i < Tiles.Length; ++i)
135 renderPass.StartPass.AddLast = (threadContext) =>
138 var mainBackBuffer = graphicsDeviceService.GraphicsDevice.BackBuffer;
139 threadContext.GraphicsDevice.SetViewport(
new Viewport(0, 0, mainBackBuffer.Width, mainBackBuffer.Height));
140 if (threadContext.FirstContext)
144 threadContext.GraphicsDevice.SetRenderTarget(GBufferPlugin.MainTargetPlugin.RenderTarget);
148 threadContext.GraphicsDevice.Clear(LightTexture,
new Color(0.0f, 0.0f, 0.0f, 0.0f));
149 threadContext.GraphicsDevice.SetRenderTarget(LightTexture);
153 for (
int i = 0; i < Tiles.Length; ++i)
157 var lightAttenuationCutoff = 0.1f;
160 var mainParameters = GBufferPlugin.MainPlugin.ViewParameters;
161 mainParameters.Get(TransformationKeys.View, out viewMatrix);
163 mainParameters.Get(TransformationKeys.Projection, out projMatrix);
165 for (
int index = 0; index < lights.Meshes.Count; index++)
167 LightingPrepassShaderPlugin.LightData lightData;
169 var lightMesh = lights.Meshes[index];
171 lightMesh.Parameters.TryGet(LightKeys.LightPosition, out lightPos);
172 Vector3.TransformCoordinate(ref lightPos, ref viewMatrix, out lightData.LightPosVS);
173 lightMesh.Parameters.TryGet(LightKeys.LightColor, out lightData.DiffuseColor);
174 lightMesh.Parameters.TryGet(LightKeys.LightIntensity, out lightData.LightIntensity);
175 lightMesh.Parameters.TryGet(LightKeys.LightRadius, out lightData.LightRadius);
185 lightData.DiffuseColor.Pow(Color.DefaultGamma);
186 lightData.LightIntensity = (float)Math.
Pow(lightData.LightIntensity,
Color.DefaultGamma);
188 float lightDistanceMax = CalculateMaxDistance(lightData.LightIntensity, lightData.LightRadius, lightAttenuationCutoff);
189 var clipRegion = ComputeClipRegion(lightData.LightPosVS, lightDistanceMax, ref projMatrix);
191 var tileStartX = (int)((clipRegion.X * 0.5f + 0.5f) * TileCountX);
192 var tileEndX = (int)((clipRegion.Z * 0.5f + 0.5f) * TileCountX);
193 var tileStartY = (int)((clipRegion.Y * 0.5f + 0.5f) * TileCountY);
194 var tileEndY = (int)((clipRegion.W * 0.5f + 0.5f) * TileCountY);
197 if (lightData.LightPosVS.Z + lightDistanceMax < 0.0f)
200 for (
int y = tileStartY;
y <= tileEndY; ++
y)
202 if (y < 0 || y >= TileCountY)
204 for (
int x = tileStartX; x <= tileEndX; ++x)
206 if (x < 0 || x >= TileCountX)
208 Tiles[
y * TileCountX + x].Add(lightData);
214 var lightDeferredMesh =
new EffectMesh(lightDeferredEffect).KeepAliveBy(ActiveObjects);
215 RenderSystem.GlobalMeshes.AddMesh(lightDeferredMesh);
217 renderPass.EndPass.AddLast = (context) =>
220 context.Parameters.Reset(LightingPrepassShaderPlugin.LightCount);
221 context.Parameters.Reset(LightingPrepassShaderPlugin.LightInfos);
222 context.Parameters.Reset(LightingPrepassShaderPlugin.TileIndex);
223 context.Parameters.Reset(TransformationKeys.Projection);
224 context.Parameters.Reset(RenderTargetKeys.DepthStencilSource);
227 var tileRenderPasses =
new RenderPass[TileCountX * TileCountY];
228 for (
int i = 0; i < tileRenderPasses.Length; ++i)
231 tileRenderPasses[i] =
new RenderPass(
"Lighting Tile");
232 tileRenderPasses[i].StartPass.AddLast = (context) => { context.Parameters.Set(LightingPrepassShaderPlugin.TileIndex, tileIndex); };
233 throw new NotImplementedException();
237 throw new NotImplementedException();
245 float CalculateMaxDistance(
float lightIntensity,
float lightRadius,
float cutoff)
248 return (
float)(lightRadius * Math.Sqrt(lightIntensity / cutoff));
251 void UpdateClipRegionRoot(
float nc,
259 float nz = (lightRadius - nc * lc) / lz;
260 float pz = (lc * lc + lz * lz - lightRadius * lightRadius) /
261 (lz - (nz / nc) * lc);
265 float c = -nz * cameraScale / nc;
268 clipMin = Math.Max(clipMin, c);
272 clipMax = Math.Min(clipMax, c);
277 void UpdateClipRegion(
float lc,
284 float rSq = lightRadius * lightRadius;
285 float lcSqPluslzSq = lc * lc + lz * lz;
286 float d = rSq * lc * lc - lcSqPluslzSq * (rSq - lz * lz);
290 float a = lightRadius * lc;
291 float b = (float)Math.Sqrt(d);
292 float nx0 = (a +
b) / lcSqPluslzSq;
293 float nx1 = (a -
b) / lcSqPluslzSq;
295 UpdateClipRegionRoot(nx0, lc, lz, lightRadius, cameraScale, ref clipMin, ref clipMax);
296 UpdateClipRegionRoot(nx1, lc, lz, lightRadius, cameraScale, ref clipMin, ref clipMax);
300 private Vector4 ComputeClipRegion(
Vector3 lightPosView,
float lightRadius, ref
Matrix projection)
303 var clipRegion =
new Vector4(1.0f, 1.0f, 0.0f, 0.0f);
305 var clipMin =
new Vector2(-1.0f, -1.0f);
306 var clipMax =
new Vector2(1.0f, 1.0f);
308 UpdateClipRegion(lightPosView.
X, lightPosView.
Z, lightRadius, projection.M11, ref clipMin.X, ref clipMax.X);
309 UpdateClipRegion(lightPosView.
Y, lightPosView.
Z, lightRadius, projection.M22, ref clipMin.Y, ref clipMax.Y);
311 clipRegion =
new Vector4(clipMin.X, clipMin.Y, clipMax.X, clipMax.Y);
Service providing method to access GraphicsDevice life-cycle.
SiliconStudio.Paradox.Games.Mathematics.Vector2 Vector2
float Y
The Y component of the vector.
A renderable texture view.
virtual RenderTarget RenderTarget
Gets or sets the render target.
Plugin used to render to a GBuffer from a MainPlugin.
override void Initialize()
_In_ size_t _In_ DXGI_FORMAT _In_ size_t _In_ float size_t y
LightingPrepassPlugin(string name)
Initializes a new instance of the LightingPrepassPlugin class.
float X
The X component of the vector.
Represents a three dimensional mathematical vector.
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.
void Pow(float exponent)
Raises the exponent for each components.
LightingPrepassPlugin()
Initializes a new instance of the LightingPrepassPlugin class.
Represents a four dimensional mathematical vector.
SiliconStudio.Core.Mathematics.Color Color
Defines the window dimensions of a render-target surface onto which a 3D volume projects.
Represents a 32-bit color (4 bytes) in the form of RGBA (in byte order: R, G, B, A).
SiliconStudio.Paradox.Graphics.Buffer Buffer
A Texture 2D frontend to SharpDX.Direct3D11.Texture2D.
readonly Texture Texture
The underlying texture.
float Z
The Z component of the vector.
RenderPass is a hierarchy that defines how to collect and render meshes.
Deffered lighting plugin.
Represents a 4x4 mathematical matrix.