5 using System.Collections.Generic;
7 using SiliconStudio.Core;
8 using SiliconStudio.Core.Mathematics;
9 using SiliconStudio.Paradox.DataModel;
10 using SiliconStudio.Paradox.Effects.Modules.Processors;
11 using SiliconStudio.Paradox.Effects.Modules.Shadowmap;
12 using SiliconStudio.Paradox.Engine;
13 using SiliconStudio.Paradox.EntityModel;
14 using SiliconStudio.Paradox.Graphics;
15 using SiliconStudio.Paradox.Shaders.Compiler;
19 namespace SiliconStudio.
Paradox.Effects.Modules.Renderers
23 #region Static members
47 #region Internal static members
49 internal static Dictionary<ParameterKey, LightingDeferredSemantic> LightParametersDict =
new Dictionary<ParameterKey, LightingDeferredSemantic>
51 { LightingPrepassRenderer.PointLightInfos, LightingDeferredSemantic.PointLightInfos },
52 { DeferredPointLightingKeys.LightAttenuationCutoff, LightingDeferredSemantic.LightAttenuationCutoff },
53 { LightingPrepassRenderer.DirectLightInfos, LightingDeferredSemantic.DirectLightInfos },
54 { LightingPrepassRenderer.SpotLightInfos, LightingDeferredSemantic.SpotLightInfos },
55 { LightingPrepassRenderer.LightCount, LightingDeferredSemantic.LightCount }
60 #region Constant values
62 public const int TileCountX = 16;
64 public const int TileCountY = 10;
66 public const float AttenuationCutoff = 0.1f;
69 public const int MaxPointLightsPerTileDrawCall = 64;
71 public const int MaxDirectLightsPerTileDrawCall = 1;
73 public const int MaxSpotLightsPerTileDrawCall = 1;
75 public const int MaxSpotShadowLightsPerTileDrawCall = 1;
77 public const int MaxDirectShadowLightsPerTileDrawCall = 1;
81 #region Private members
83 private string effectName;
85 private ShadowMapReceiverInfo[] receiverInfos;
87 private ShadowMapReceiverVsmInfo[] receiverVsmInfos;
89 private ShadowMapCascadeReceiverInfo[] cascadeInfos;
93 private List<EntityLightShadow> validLights;
95 private List<EntityLightShadow> pointLights;
97 private List<EntityLightShadow> spotLights;
99 private List<EntityLightShadow> spotShadowLights;
101 private List<EntityLightShadow> directionalLights;
103 private List<EntityLightShadow> directionalShadowLights;
105 private List<PointLightData> pointLightDatas;
107 private List<SpotLightData> spotLightDatas;
109 private List<DirectLightData> directionalLightDatas;
111 private Dictionary<int, List<int>> regroupedTiles;
113 private List<PointLightData>[] tilesGroups =
new List<PointLightData>[TileCountX * TileCountY];
129 private Effect pointLightingPrepassEffect;
131 private Effect spotLightingPrepassEffect;
133 private Effect directLightingPrepassEffect;
135 private Dictionary<ShadowEffectInfo, Effect> shadowEffects;
137 private Dictionary<ShadowEffectInfo, List<EntityLightShadow>> shadowLights;
139 private Dictionary<ShadowEffectInfo, List<DirectLightData>> directShadowLightDatas;
141 private Dictionary<ShadowEffectInfo, List<SpotLightData>> spotShadowLightDatas;
143 private Dictionary<Effect, LightingDeferredParameters[]> lightingConfigurationsPerEffect;
145 private Dictionary<ParameterKey, LightingDeferredSemantic> lightingParameterSemantics;
171 validLights =
new List<EntityLightShadow>();
172 pointLights =
new List<EntityLightShadow>();
173 spotLights =
new List<EntityLightShadow>();
174 spotShadowLights =
new List<EntityLightShadow>();
175 directionalLights =
new List<EntityLightShadow>();
176 directionalShadowLights =
new List<EntityLightShadow>();
177 pointLightDatas =
new List<PointLightData>();
178 spotLightDatas =
new List<SpotLightData>();
179 directionalLightDatas =
new List<DirectLightData>();
180 regroupedTiles =
new Dictionary<int, List<int>>();
181 lightingConfigurationsPerEffect =
new Dictionary<Effect, LightingDeferredParameters[]>();
182 lightingParameterSemantics =
new Dictionary<ParameterKey, LightingDeferredSemantic>();
183 shadowEffects =
new Dictionary<ShadowEffectInfo, Effect>();
184 shadowLights =
new Dictionary<ShadowEffectInfo, List<EntityLightShadow>>();
185 directShadowLightDatas =
new Dictionary<ShadowEffectInfo, List<DirectLightData>>();
186 spotShadowLightDatas =
new Dictionary<ShadowEffectInfo, List<SpotLightData>>();
188 receiverInfos =
new ShadowMapReceiverInfo[4];
189 receiverVsmInfos =
new ShadowMapReceiverVsmInfo[4];
190 cascadeInfos =
new ShadowMapCascadeReceiverInfo[16];
193 this.effectName = effectName;
194 this.depthStencilTexture = depthStencilTexture;
195 this.gbufferTexture = gbufferTexture;
196 DebugName = string.Format(
"LightingPrepass [{0}]", effectName);
201 #region Public methods
209 for (
int i = 0; i < tilesGroups.Length; ++i)
210 tilesGroups[i] =
new List<PointLightData>();
212 pointLightingPrepassEffect = EffectSystem.LoadEffect(effectName +
".ParadoxPointPrepassLighting");
213 CreateLightingUpdateInfo(pointLightingPrepassEffect);
215 spotLightingPrepassEffect = EffectSystem.LoadEffect(effectName +
".ParadoxSpotPrepassLighting");
216 CreateLightingUpdateInfo(spotLightingPrepassEffect);
231 directLightingPrepassEffect = EffectSystem.LoadEffect(effectName +
".ParadoxDirectPrepassLighting");
232 CreateLightingUpdateInfo(directLightingPrepassEffect);
236 for (var cascadeCount = 1; cascadeCount < 5; ++cascadeCount)
244 var lightTexture = Texture2D.New(
GraphicsDevice, GraphicsDevice.BackBuffer.Width, GraphicsDevice.BackBuffer.Height, PixelFormat.R16G16B16A16_Float, TextureFlags.ShaderResource | TextureFlags.RenderTarget);
245 lightRenderTarget = lightTexture.ToRenderTarget();
248 Pass.Parameters.Set(RenderTargetKeys.DepthStencilSource, depthStencilTexture);
249 Pass.Parameters.Set(GBufferBaseKeys.GBufferTexture, gbufferTexture);
250 Pass.Parameters.Set(LightDeferredShadingKeys.LightTexture, lightTexture);
266 VertexBuffers =
new[]
274 vertexArrayObject = VertexArrayObject.New(GraphicsDevice, pointLightingPrepassEffect.InputSignature, meshDraw.VertexBuffers);
278 blendStateDesc.SetDefaults();
279 blendStateDesc.AlphaToCoverageEnable =
false;
280 blendStateDesc.IndependentBlendEnable =
false;
281 blendStateDesc.RenderTargets[0].BlendEnable =
true;
283 blendStateDesc.RenderTargets[0].AlphaBlendFunction = BlendFunction.Add;
284 blendStateDesc.RenderTargets[0].AlphaSourceBlend = Blend.One;
285 blendStateDesc.RenderTargets[0].AlphaDestinationBlend = Blend.One;
287 blendStateDesc.RenderTargets[0].ColorBlendFunction = BlendFunction.Add;
288 blendStateDesc.RenderTargets[0].ColorSourceBlend = Blend.One;
289 blendStateDesc.RenderTargets[0].ColorDestinationBlend = Blend.One;
293 accumulationBlendState = BlendState.New(GraphicsDevice, blendStateDesc);
301 lightRenderTarget.Dispose();
302 lightRenderTarget.Texture.Dispose();
303 lightRenderTarget = null;
308 #region Private methods
312 parameters.Set(ShadowMapParameters.ShadowMapCascadeCount, cascadeCount);
313 parameters.Set(ShadowMapParameters.FilterType, filterType);
319 ShadowEffectInfo seiDirect;
320 seiDirect.LightType = LightType.Directional;
321 seiDirect.CascadeCount = cascadeCount;
322 seiDirect.Filter = filterType;
323 AddEffect(seiDirect, cascadeCount, parameters, directShadowLightDatas);
329 ShadowEffectInfo seiSpot;
330 seiSpot.LightType = LightType.Spot;
331 seiSpot.CascadeCount = cascadeCount;
332 seiSpot.Filter = filterType;
334 AddEffect(seiSpot, cascadeCount, parameters, spotShadowLightDatas);
337 private void AddEffect<T>(ShadowEffectInfo sei,
int cascadeCount,
CompilerParameters parameters, Dictionary<ShadowEffectInfo, List<T>> lightDatas)
339 var effect = EffectSystem.LoadEffect(effectName +
".ParadoxShadowPrepassLighting", parameters);
340 var lightingGroupInfo = CreateLightingUpdateInfo(effect);
341 lightingGroupInfo.ShadowParameters =
new List<ShadowUpdateInfo>
343 LightingProcessorHelpers.CreateShadowUpdateInfo(0, cascadeCount)
346 shadowEffects.Add(sei, effect);
347 shadowLights.Add(sei,
new List<EntityLightShadow>());
348 lightDatas.Add(sei,
new List<T>());
358 var entitySystem = Services.GetServiceAs<
EntitySystem>();
359 if (entitySystem == null)
362 if (lightProcessor == null)
366 var hasShadowRenderer = RenderSystem.Pipeline.GetProcessor<ShadowMapRenderer>() != null;
369 foreach (var light
in lightProcessor.Lights)
371 if (light.Value.Light.Deferred && light.Value.Light.Enabled)
373 validLights.Add(light.Value);
375 switch (light.Value.Light.Type)
377 case LightType.Point:
378 pointLights.Add(light.Value);
380 case LightType.Spherical:
382 case LightType.Directional:
383 if (hasShadowRenderer && light.Value.HasShadowMap && lightProcessor.ActiveShadowMaps.Contains(light.Value.ShadowMap))
384 directionalShadowLights.Add(light.Value);
386 directionalLights.Add(light.Value);
389 if (hasShadowRenderer && light.Value.HasShadowMap && lightProcessor.ActiveShadowMaps.Contains(light.Value.ShadowMap))
390 spotShadowLights.Add(light.Value);
392 spotLights.Add(light.Value);
398 foreach (var light
in pointLights)
403 data.LightIntensity = light.Light.Intensity;
404 data.LightPosition =
new Vector3(light.Entity.Transformation.WorldMatrix.M41, light.Entity.Transformation.WorldMatrix.M42, light.Entity.Transformation.WorldMatrix.M43);
405 data.LightPosition /= light.Entity.Transformation.WorldMatrix.M44;
406 data.LightRadius = light.Light.DecayStart;
411 pointLightDatas.Add(data);
414 foreach (var light
in directionalLights)
415 directionalLightDatas.Add(GetDirectLightData(light));
417 foreach (var light
in directionalShadowLights)
419 ShadowEffectInfo sei;
420 sei.LightType = LightType.Directional;
421 sei.CascadeCount = light.Light.ShadowMapCascadeCount;
424 List<DirectLightData> dataList;
425 if (directShadowLightDatas.TryGetValue(sei, out dataList))
427 dataList.Add(GetDirectLightData(light));
428 shadowLights[sei].Add(light);
432 foreach (var light
in spotLights)
433 spotLightDatas.Add(GetSpotLightData(light));
435 foreach (var light
in spotShadowLights)
437 ShadowEffectInfo sei;
438 sei.LightType = LightType.Spot;
439 sei.CascadeCount = light.Light.ShadowMapCascadeCount;
442 List<SpotLightData> dataList;
443 if (spotShadowLightDatas.TryGetValue(sei, out dataList))
445 dataList.Add(GetSpotLightData(light));
446 shadowLights[sei].Add(light);
457 private void EndRender(RenderContext context)
462 spotShadowLights.Clear();
463 directionalLights.Clear();
464 directionalShadowLights.Clear();
465 pointLightDatas.Clear();
466 spotLightDatas.Clear();
467 directionalLightDatas.Clear();
469 foreach(var lightList
in shadowLights)
470 lightList.Value.Clear();
471 foreach (var dataList
in directShadowLightDatas)
472 dataList.Value.Clear();
473 foreach (var dataList
in spotShadowLightDatas)
474 dataList.Value.Clear();
476 regroupedTiles.Clear();
477 lightingParameterSemantics.Clear();
510 CreateLightingUpdateInfo(pointLightingPrepassEffect);
511 CreateLightingUpdateInfo(spotLightingPrepassEffect);
512 CreateLightingUpdateInfo(directLightingPrepassEffect);
513 foreach (var shadowEffect
in shadowEffects)
514 CreateLightingUpdateInfo(shadowEffect.Value);
517 UpdateLightDatas(context);
520 if (pointLights.Count == 0 && spotLights.Count == 0 && directionalLights.Count == 0 && directionalShadowLights.Count == 0 && spotShadowLights.Count == 0)
522 GraphicsDevice.Clear(lightRenderTarget,
new Color4(1.0f, 1.0f, 1.0f, 0.0f));
527 GraphicsDevice.Clear(lightRenderTarget,
new Color4(0.0f, 0.0f, 0.0f, 0.0f));
528 GraphicsDevice.SetRenderTarget(lightRenderTarget);
532 GraphicsDevice.SetBlendState(null);
535 GraphicsDevice.SetDepthStencilState(GraphicsDevice.DepthStencilStates.None);
539 context.Parameters.Set(MaterialKeys.SpecularIntensity, 1.0f);
541 UpdateTiles(Pass.Parameters);
544 var hasPreviousLighting = RenderTileForDirectLights(context);
547 hasPreviousLighting |= RenderTileForSpotLights(context, hasPreviousLighting);
550 foreach (var lightList
in shadowLights)
552 if (lightList.Value.Count > 0)
554 var effect = shadowEffects[lightList.Key];
556 if ((lightList.Key.LightType ==
LightType.Directional && RenderTileForDirectShadowLights(context, hasPreviousLighting, effect, lightList.Value, directShadowLightDatas[lightList.Key], lightList.Key.Filter ==
ShadowMapFilterType.Variance))
557 || lightList.Key.LightType ==
LightType.Spot && RenderTileForSpotShadowLights(context, hasPreviousLighting, effect, lightList.Value, spotShadowLightDatas[lightList.Key], lightList.Key.Filter ==
ShadowMapFilterType.Variance))
559 effect.UnbindResources();
560 hasPreviousLighting =
true;
566 RenderTilesForPointLights(context, hasPreviousLighting);
569 GraphicsDevice.SetBlendState(null);
577 context.Parameters.Reset(MaterialKeys.SpecularIntensity);
582 LightingDeferredParameters[] deferredParameters = null;
583 if (lightingConfigurationsPerEffect.TryGetValue(effect, out deferredParameters))
585 foreach (var deferredParam
in deferredParameters)
587 if ((deferredParam.Semantic & LightingDeferredSemantic.DirectLightInfos) != 0)
588 context.
Parameters.Set(deferredParam.DirectLightInfosKey, data);
589 if ((deferredParam.Semantic & LightingDeferredSemantic.LightCount) != 0)
590 context.Parameters.Set(deferredParam.LightCountKey, lightCount);
595 private void SetSpotLightParameters(RenderContext context,
Effect effect, SpotLightData[] data,
int lightCount)
597 LightingDeferredParameters[] deferredParameters = null;
598 if (lightingConfigurationsPerEffect.TryGetValue(effect, out deferredParameters))
600 foreach (var deferredParam
in deferredParameters)
602 if ((deferredParam.Semantic & LightingDeferredSemantic.SpotLightInfos) != 0)
603 context.Parameters.Set(deferredParam.SpotLightInfosKey, data);
604 if ((deferredParam.Semantic & LightingDeferredSemantic.LightCount) != 0)
605 context.Parameters.Set(deferredParam.LightCountKey, lightCount);
610 private int SetCascadeInfo(List<EntityLightShadow> lights,
int startLightIndex,
int lightIndex,
int cascadeCount, ShadowUpdateInfo shadowUpdateInfo)
612 var shadowLight = lights[startLightIndex + lightIndex];
613 receiverInfos[lightIndex] = shadowLight.ShadowMap.ReceiverInfo;
614 receiverVsmInfos[lightIndex] = shadowLight.ShadowMap.ReceiverVsmInfo;
615 for (var cascade = 0; cascade < shadowUpdateInfo.CascadeCount; ++cascade)
616 cascadeInfos[cascadeCount + cascade] = shadowLight.ShadowMap.Cascades[cascade].ReceiverInfo;
618 return cascadeCount + shadowUpdateInfo.CascadeCount;
621 private void RenderTile(RenderContext context,
Effect effect,
bool hasPreviousDraw,
int currentDrawIndex)
624 effectParameterCollections[0] = context.CurrentPass.Parameters;
625 effectParameterCollections[1] = context.Parameters;
628 effect.Apply(effectParameterCollections);
632 if (!hasPreviousDraw && currentDrawIndex == 1)
633 GraphicsDevice.SetBlendState(accumulationBlendState);
636 GraphicsDevice.SetVertexArrayObject(vertexArrayObject);
640 private void RenderShadowLight(RenderContext context, List<EntityLightShadow> lights,
int startLightIndex,
int lightCount,
int cascadeCount,
bool varianceShadowMap,
bool hasPreviousDraw,
int currentDrawIndex, ShadowUpdateInfo shadowUpdateInfo,
Effect effect)
643 context.Parameters.Set((ParameterKey<ShadowMapReceiverInfo[]>)shadowUpdateInfo.ShadowMapReceiverInfoKey, receiverInfos, 0, lightCount);
644 context.Parameters.Set((ParameterKey<ShadowMapCascadeReceiverInfo[]>)shadowUpdateInfo.ShadowMapLevelReceiverInfoKey, cascadeInfos, 0, cascadeCount);
645 context.Parameters.Set(shadowUpdateInfo.ShadowMapLightCountKey, lightCount);
647 if (varianceShadowMap)
648 context.Parameters.Set(shadowUpdateInfo.ShadowMapTextureKey, lights[startLightIndex].ShadowMap.Texture.ShadowMapTargetTexture);
650 context.Parameters.Set(shadowUpdateInfo.ShadowMapTextureKey, lights[startLightIndex].ShadowMap.Texture.ShadowMapDepthTexture);
652 RenderTile(context, effect, hasPreviousDraw, currentDrawIndex);
655 private bool RenderTileForDirectLights(RenderContext context)
658 context.Parameters.Set(DeferredTiledShaderKeys.TileCountX, 1);
659 context.Parameters.Set(DeferredTiledShaderKeys.TileCountY, 1);
660 context.Parameters.Set(DeferredTiledShaderKeys.TileIndex, 0);
662 int directLightCount = directionalLightDatas.Count;
664 int drawCount = (directLightCount + MaxDirectLightsPerTileDrawCall - 1) / MaxDirectLightsPerTileDrawCall;
665 var startLightIndex = 0;
667 for (
int currentDrawIndex = 0; currentDrawIndex < drawCount; ++currentDrawIndex)
669 int lightCount = Math.Min(directLightCount - startLightIndex, MaxDirectLightsPerTileDrawCall);
672 for (
int lightIndex = 0; lightIndex < lightCount; ++lightIndex)
673 currentDirectLights[lightIndex] = directionalLightDatas[startLightIndex + lightIndex];
676 SetDirectLightParameters(context, directLightingPrepassEffect, currentDirectLights, lightCount);
678 RenderTile(context, directLightingPrepassEffect,
false, currentDrawIndex);
680 startLightIndex += MaxDirectLightsPerTileDrawCall;
685 directLightingPrepassEffect.UnbindResources();
692 private bool RenderTileForDirectShadowLights(RenderContext context,
bool hasPreviousDraw,
Effect effect, List<EntityLightShadow> lights, List<DirectLightData> lightDatas,
bool varianceShadowMap)
695 context.Parameters.Set(DeferredTiledShaderKeys.TileCountX, 1);
696 context.Parameters.Set(DeferredTiledShaderKeys.TileCountY, 1);
697 context.Parameters.Set(DeferredTiledShaderKeys.TileIndex, 0);
699 int directShadowLightCount = lightDatas.Count;
702 GraphicsDevice.SetBlendState(accumulationBlendState);
704 int drawCount = (directShadowLightCount + MaxDirectShadowLightsPerTileDrawCall - 1) / MaxDirectShadowLightsPerTileDrawCall;
705 var startLightIndex = 0;
708 var lightingGroupInfo = LightingGroupInfo.GetOrCreate(effect);
709 var shadowUpdateInfo = lightingGroupInfo.ShadowParameters[0];
711 for (
int i = 0; i < drawCount; ++i)
713 int lightCount = Math.Min(directShadowLightCount - startLightIndex, MaxDirectShadowLightsPerTileDrawCall);
714 var cascadeCount = 0;
716 for (
int lightIndex = 0; lightIndex < lightCount; ++lightIndex)
718 currentDirectShadowLights[lightIndex] = lightDatas[startLightIndex + lightIndex];
719 cascadeCount = SetCascadeInfo(lights, startLightIndex, lightIndex, cascadeCount, shadowUpdateInfo);
723 SetDirectLightParameters(context, effect, currentDirectShadowLights, lightCount);
725 RenderShadowLight(context, lights, startLightIndex, lightCount, cascadeCount, varianceShadowMap, hasPreviousDraw, i, shadowUpdateInfo, effect);
727 startLightIndex += MaxDirectShadowLightsPerTileDrawCall;
730 return (drawCount > 0);
733 private bool RenderTileForSpotShadowLights(RenderContext context,
bool hasPreviousDraw,
Effect effect, List<EntityLightShadow> lights, List<SpotLightData> lightDatas,
bool varianceShadowMap)
737 context.Parameters.Set(DeferredTiledShaderKeys.TileCountX, 1);
738 context.Parameters.Set(DeferredTiledShaderKeys.TileCountY, 1);
739 context.Parameters.Set(DeferredTiledShaderKeys.TileIndex, 0);
741 int spotShadowLightCount = lightDatas.Count;
744 GraphicsDevice.SetBlendState(accumulationBlendState);
746 int drawCount = (spotShadowLightCount + MaxSpotShadowLightsPerTileDrawCall - 1) / MaxSpotShadowLightsPerTileDrawCall;
747 var startLightIndex = 0;
750 var lightGroupInfo = LightingGroupInfo.GetOrCreate(effect);
751 var shadowUpdateInfo = lightGroupInfo.ShadowParameters[0];
753 for (
int i = 0; i < drawCount; ++i)
755 int lightCount = Math.Min(spotShadowLightCount - startLightIndex, MaxSpotShadowLightsPerTileDrawCall);
756 int cascadeCount = 0;
758 for (
int lightIndex = 0; lightIndex < lightCount; ++lightIndex)
760 currentSpotShadowLights[lightIndex] = lightDatas[startLightIndex + lightIndex];
761 cascadeCount = SetCascadeInfo(lights, startLightIndex, lightIndex, cascadeCount, shadowUpdateInfo);
765 SetSpotLightParameters(context, effect, currentSpotShadowLights, lightCount);
767 RenderShadowLight(context, lights, startLightIndex, lightCount, cascadeCount, varianceShadowMap, hasPreviousDraw, i, shadowUpdateInfo, effect);
769 startLightIndex += MaxSpotShadowLightsPerTileDrawCall;
774 effect.UnbindResources();
781 private bool RenderTileForSpotLights(RenderContext context,
bool hasPreviousDraw)
785 context.Parameters.Set(DeferredTiledShaderKeys.TileCountX, 1);
786 context.Parameters.Set(DeferredTiledShaderKeys.TileCountY, 1);
787 context.Parameters.Set(DeferredTiledShaderKeys.TileIndex, 0);
789 int spotLightCount = spotLightDatas.Count;
792 GraphicsDevice.SetBlendState(accumulationBlendState);
794 int drawCount = (spotLightCount + MaxSpotLightsPerTileDrawCall - 1) / MaxSpotLightsPerTileDrawCall;
795 var startLightIndex = 0;
797 for (
int currentDrawIndex = 0; currentDrawIndex < drawCount; ++currentDrawIndex)
799 int lightCount = Math.Min(spotLightCount - startLightIndex, MaxSpotLightsPerTileDrawCall);
802 for (
int lightIndex = 0; lightIndex < lightCount; ++lightIndex)
803 currentSpotLights[lightIndex] = spotLightDatas[startLightIndex + lightIndex];
806 SetSpotLightParameters(context, spotLightingPrepassEffect, currentSpotLights, lightCount);
808 RenderTile(context, spotLightingPrepassEffect, hasPreviousDraw, currentDrawIndex);
810 startLightIndex += MaxSpotLightsPerTileDrawCall;
815 spotLightingPrepassEffect.UnbindResources();
822 private void RenderTilesForPointLights(RenderContext context,
bool hasPreviousDraw)
824 context.Parameters.Set(DeferredTiledShaderKeys.TileCountX, TileCountX);
825 context.Parameters.Set(DeferredTiledShaderKeys.TileCountY, TileCountY);
827 var hasDrawn =
false;
829 for (var tileIndex = 0; tileIndex < TileCountX * TileCountY; ++tileIndex)
831 var tilesGroup = this.tilesGroups[tileIndex];
846 context.Parameters.Set(DeferredTiledShaderKeys.TileIndex, tileIndex);
848 int drawCount = (tilesGroup.Count + MaxPointLightsPerTileDrawCall - 1) / MaxPointLightsPerTileDrawCall;
851 GraphicsDevice.SetBlendState(accumulationBlendState);
853 GraphicsDevice.SetBlendState(null);
855 var startLightIndex = 0;
858 for (
int currentDrawIndex = 0; currentDrawIndex < drawCount; ++currentDrawIndex)
861 int lightCount = Math.Min(tilesGroup.Count - startLightIndex, MaxPointLightsPerTileDrawCall);
862 for (
int lightIndex = 0; lightIndex < lightCount; ++lightIndex)
863 currentPointLights[lightIndex] = tilesGroup[startLightIndex + lightIndex];
866 LightingDeferredParameters[] deferredParameters = null;
867 if (lightingConfigurationsPerEffect.TryGetValue(pointLightingPrepassEffect, out deferredParameters))
869 foreach (var deferredParam
in deferredParameters)
871 if ((deferredParam.Semantic & LightingDeferredSemantic.PointLightInfos) != 0)
873 context.Parameters.Set(deferredParam.PointLightInfosKey, currentPointLights);
875 if ((deferredParam.Semantic & LightingDeferredSemantic.LightCount) != 0)
877 context.Parameters.Set(deferredParam.LightCountKey, lightCount);
879 if ((deferredParam.Semantic & LightingDeferredSemantic.LightAttenuationCutoff) != 0)
881 context.Parameters.Set(deferredParam.LightAttenuationCutoffKey, 0.1f);
886 RenderTile(context, pointLightingPrepassEffect, hasPreviousDraw, currentDrawIndex);
888 startLightIndex += MaxPointLightsPerTileDrawCall;
891 hasDrawn |= (drawCount > 0);
895 pointLightingPrepassEffect.UnbindResources();
898 private void UpdateTiles(ParameterCollection viewParameters)
900 for (
int i = 0; i < tilesGroups.Length; ++i)
901 tilesGroups[i].
Clear();
903 var lightAttenuationCutoff = AttenuationCutoff;
906 viewParameters.Get(TransformationKeys.View, out viewMatrix);
908 viewParameters.Get(TransformationKeys.Projection, out projMatrix);
910 for (
int index = 0; index < pointLightDatas.Count; index++)
912 var lightData = pointLightDatas[index];
915 Vector3.TransformCoordinate(ref lightData.LightPosition, ref viewMatrix, out lightData.LightPosition);
924 float lightDistanceMax = CalculateMaxDistance(lightData.LightIntensity, lightData.LightRadius, lightAttenuationCutoff);
927 if (lightData.LightPosition.Z - lightDistanceMax > 0.0f)
930 var clipRegion = ComputeClipRegion(lightData.LightPosition, lightDistanceMax, ref projMatrix);
932 var tileStartX = (int)((clipRegion.X * 0.5f + 0.5f) * TileCountX);
933 var tileEndX = (int)((clipRegion.Z * 0.5f + 0.5f) * TileCountX);
934 var tileStartY = (int)((clipRegion.Y * 0.5f + 0.5f) * TileCountY);
935 var tileEndY = (int)((clipRegion.W * 0.5f + 0.5f) * TileCountY);
937 for (
int y = tileStartY;
y <= tileEndY; ++
y)
939 if (y < 0 || y >= TileCountY)
941 for (
int x = tileStartX; x <= tileEndX; ++x)
943 if (x < 0 || x >= TileCountX)
945 tilesGroups[
y * TileCountX + x].Add(lightData);
950 for (
int index = 0; index < spotLightDatas.Count; index++)
952 var lightData = spotLightDatas[index];
955 Vector3.TransformNormal(ref lightData.LightDirection, ref viewMatrix, out lightData.LightDirection);
957 Vector3.TransformCoordinate(ref lightData.LightPosition, ref viewMatrix, out lightData.LightPosition);
958 spotLightDatas[index] = lightData;
961 foreach (var lightDatas
in spotShadowLightDatas)
963 for (
int index = 0; index < lightDatas.Value.Count; index++)
965 var lightData = lightDatas.Value[index];
968 Vector3.TransformNormal(ref lightData.LightDirection, ref viewMatrix, out lightData.LightDirection);
970 Vector3.TransformCoordinate(ref lightData.LightPosition, ref viewMatrix, out lightData.LightPosition);
971 lightDatas.Value[index] = lightData;
975 for (
int index = 0; index < directionalLightDatas.Count; index++)
977 var lightData = directionalLightDatas[index];
980 Vector3.TransformNormal(ref lightData.LightDirection, ref viewMatrix, out lightData.LightDirection);
981 directionalLightDatas[index] = lightData;
984 foreach (var lightDatas
in directShadowLightDatas)
986 for (
int index = 0; index < lightDatas.Value.Count; index++)
988 var lightData = lightDatas.Value[index];
991 Vector3.TransformNormal(ref lightData.LightDirection, ref viewMatrix, out lightData.LightDirection);
992 lightDatas.Value[index] = lightData;
997 private static float CalculateMaxDistance(
float lightIntensity,
float lightRadius,
float cutoff)
1000 return (
float)(lightRadius * Math.Sqrt(lightIntensity / cutoff));
1003 private static void UpdateClipRegionRoot(
float nc,
1011 float nz = (lightRadius - nc * lc) / lz;
1012 float pz = (lc * lc + lz * lz - lightRadius * lightRadius) /
1013 (lz - (nz / nc) * lc);
1017 float c = -nz * cameraScale / nc;
1020 clipMin = Math.Max(clipMin, c);
1024 clipMax = Math.Min(clipMax, c);
1029 private static void UpdateClipRegion(
float lc,
1036 float rSq = lightRadius * lightRadius;
1037 float lcSqPluslzSq = lc * lc + lz * lz;
1038 float d = rSq * lc * lc - lcSqPluslzSq * (rSq - lz * lz);
1042 float a = lightRadius * lc;
1043 float b = (float)Math.Sqrt(d);
1044 float nx0 = (a +
b) / lcSqPluslzSq;
1045 float nx1 = (a -
b) / lcSqPluslzSq;
1047 UpdateClipRegionRoot(nx0, lc, lz, lightRadius, cameraScale, ref clipMin, ref clipMax);
1048 UpdateClipRegionRoot(nx1, lc, lz, lightRadius, cameraScale, ref clipMin, ref clipMax);
1052 private static Vector4 ComputeClipRegion(
Vector3 lightPosView,
float lightRadius, ref
Matrix projection)
1054 var clipRegion =
new Vector4(1.0f, 1.0f, 0.0f, 0.0f);
1055 var clipMin =
new Vector2(-1.0f, -1.0f);
1056 var clipMax =
new Vector2(1.0f, 1.0f);
1058 UpdateClipRegion(lightPosView.
X, -lightPosView.
Z, lightRadius, projection.M11, ref clipMin.X, ref clipMax.X);
1059 UpdateClipRegion(lightPosView.
Y, -lightPosView.
Z, lightRadius, projection.M22, ref clipMin.Y, ref clipMax.Y);
1061 clipRegion =
new Vector4(clipMin.X, clipMin.Y, clipMax.X, clipMax.Y);
1066 private LightingGroupInfo CreateLightingUpdateInfo(
Effect effect)
1068 var lightingGroupInfo = LightingGroupInfo.GetOrCreate(effect);
1070 if (!lightingGroupInfo.IsLightingSetup || !lightingConfigurationsPerEffect.ContainsKey(effect))
1072 var finalList =
new List<LightingDeferredParameters>();
1073 var continueSearch =
true;
1075 while (continueSearch)
1077 continueSearch = SearchLightingGroup(effect, index,
"lightingGroups", finalList);
1081 continueSearch =
true;
1083 while (continueSearch)
1085 continueSearch = SearchLightingGroup(effect, index,
"shadows", finalList);
1089 lightingConfigurationsPerEffect.Remove(effect);
1091 if (finalList.Count > 0)
1092 lightingConfigurationsPerEffect.Add(effect, finalList.ToArray());
1094 lightingGroupInfo.IsLightingSetup =
true;
1097 return lightingGroupInfo;
1100 private bool SearchLightingGroup(
Effect effect,
int index,
string groupName, List<LightingDeferredParameters> finalList)
1102 var constantBuffers = effect.ConstantBuffers;
1103 var info =
new LightingDeferredParameters();
1105 LightingDeferredSemantic foundParameterSemantic;
1106 var foundParam =
false;
1108 UpdateLightingParameterSemantics(index, groupName);
1110 foreach (var constantBuffer
in constantBuffers)
1112 foreach (var member
in constantBuffer.Members)
1114 if (lightingParameterSemantics.TryGetValue(member.Param.Key, out foundParameterSemantic))
1116 info.Semantic = info.Semantic | foundParameterSemantic;
1118 switch (foundParameterSemantic)
1120 case LightingDeferredSemantic.PointLightInfos:
1121 info.Count = member.Count;
1122 info.PointLightInfosKey = (ParameterKey<PointLightData[]>)member.Param.Key;
1124 case LightingDeferredSemantic.DirectLightInfos:
1125 info.Count = member.Count;
1126 info.DirectLightInfosKey = (ParameterKey<DirectLightData[]>)member.Param.Key;
1128 case LightingDeferredSemantic.SpotLightInfos:
1129 info.Count = member.Count;
1130 info.SpotLightInfosKey = (ParameterKey<SpotLightData[]>)member.Param.Key;
1132 case LightingDeferredSemantic.LightAttenuationCutoff:
1133 info.LightAttenuationCutoffKey = (ParameterKey<float>)member.Param.Key;
1135 case LightingDeferredSemantic.LightCount:
1136 info.LightCountKey = (ParameterKey<int>)member.Param.Key;
1139 throw new ArgumentOutOfRangeException();
1145 finalList.Add(info);
1149 private void UpdateLightingParameterSemantics(
int index,
string compositionName)
1151 lightingParameterSemantics.Clear();
1152 var lightGroupSubKey = string.Format(
"." + compositionName +
"[{0}]", index);
1153 foreach (var param
in LightParametersDict)
1155 lightingParameterSemantics.Add(param.Key.AppendKey(lightGroupSubKey), param.Value);
1161 #region Private static methods
1165 DirectLightData data;
1169 data.LightIntensity = light.Light.Intensity;
1170 var lightDir = light.Light.LightDirection;
1171 Vector3.TransformNormal(ref lightDir, ref light.Entity.Transformation.WorldMatrix, out lightDirection);
1172 data.LightDirection = lightDirection;
1185 var zero = Vector3.Zero;
1186 var lightDir = light.Light.LightDirection;
1187 Vector3.TransformNormal(ref lightDir, ref light.Entity.Transformation.WorldMatrix, out lightDirection);
1188 data.LightDirection = lightDirection;
1191 data.LightIntensity = light.Light.Intensity;
1193 data.LightPosition /= light.Entity.Transformation.WorldMatrix.M44;
1198 data.Range = light.Light.DecayStart;
1208 #region Helper structures
1210 private class LightingDeferredParameters
1212 public LightingDeferredSemantic Semantic;
1214 public ParameterKey<int> LightCountKey;
1215 public ParameterKey<PointLightData[]> PointLightInfosKey;
1216 public ParameterKey<DirectLightData[]> DirectLightInfosKey;
1217 public ParameterKey<SpotLightData[]> SpotLightInfosKey;
1218 public ParameterKey<float> LightAttenuationCutoffKey;
1220 public LightingDeferredParameters()
1222 Semantic = LightingDeferredSemantic.None;
1224 PointLightInfosKey = null;
1225 DirectLightInfosKey = null;
1226 SpotLightInfosKey = null;
1227 LightCountKey = null;
1228 LightAttenuationCutoffKey = null;
1233 internal enum LightingDeferredSemantic
1236 PointLightInfos = 0x1,
1237 DirectLightInfos = 0x2,
1238 SpotLightInfos = 0x4,
1239 LightAttenuationCutoff = 0x8,
1243 private struct ShadowEffectInfo
1246 public int CascadeCount;
float SpotBeamAngle
Gets or sets the beam angle of the spot light.
Key of an effect parameter.
SiliconStudio.Paradox.Games.Mathematics.Vector2 Vector2
The layout of a vertex buffer with a set of VertexElement.
float Y
The Y component of the vector.
Represents a two dimensional mathematical vector.
A renderable texture view.
_In_ size_t _In_ DXGI_FORMAT _In_ size_t _In_ float size_t y
Performs render pipeline transformations attached to a specific RenderPass.
override void Load()
Loads this instance. This method is called when a RenderPass is attached (directly or indirectly) to ...
LightingPrepassRenderer(IServiceRegistry services, string effectName, Texture2D depthStencilTexture, Texture2D gbufferTexture)
LightPrepassRenderer constructor.
Parameters used for compilation.
float X
The X component of the vector.
Represents a three dimensional mathematical vector.
float M42
Value at row 4 column 2 of the matrix.
TransformationComponent Transformation
Gets or sets the Transformation associated to this entity. Added for convenience over usual Get/Set m...
A service registry is a IServiceProvider that provides methods to register and unregister services...
Represents a color in the form of rgba.
All-in-One Buffer class linked SharpDX.Direct3D11.Buffer.
override void OnRendering(RenderContext context)
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.
ParameterCollection Parameters
Gets the parameters shared by this instance.
Flags
Enumeration of the new Assimp's flags.
static Buffer New(GraphicsDevice device, BufferDescription description, PixelFormat viewFormat=PixelFormat.None)
Creates a new Buffer instance.
float SpotFieldAngle
Gets or sets the spot field angle of the spot light.
Represents a four dimensional mathematical vector.
Thread-local storage context used during rendering.
SiliconStudio.Core.Mathematics.Color Color
Manage a collection of entities.
float M41
Value at row 4 column 1 of the matrix.
SiliconStudio.Paradox.Graphics.Buffer Buffer
override void Unload()
Unloads this instance. This method is called when a RenderPass is de-attached (directly or indirectly...
static VertexElement Position(PixelFormat format, int offsetInBytes=AppendAligned)
Declares a VertexElement with the semantic "POSITION".
A Texture 2D frontend to SharpDX.Direct3D11.Texture2D.
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.Core.Mathematics.Vector3 Vector3
float M43
Value at row 4 column 3 of the matrix.
float Z
The Z component of the vector.
A description of a single element for the input-assembler stage. This structure is related to Direct3...
A container to handle a hierarchical collection of effect variables.
Binding structure that specifies a vertex buffer and other per-vertex parameters (such as offset and ...
Represents a 4x4 mathematical matrix.