/// <summary> /// Initializes a new instance of the <see cref="LightSpotShadowMapGroupShaderData" /> class. /// </summary> /// <param name="compositionKey">The composition key.</param> /// <param name="shadowType">Type of the shadow.</param> /// <param name="lightCountMax">The light count maximum.</param> public LightSpotShadowMapGroupShaderData(string compositionKey, LightShadowType shadowType, int lightCountMax) { this.shadowType = shadowType; worldToShadowCascadeUV = new Matrix[lightCountMax]; depthBiases = new float[lightCountMax]; offsetScales = new float[lightCountMax]; var mixin = new ShaderMixinSource(); mixin.Mixins.Add(new ShaderClassSource(ShaderName,lightCountMax, (this.shadowType & LightShadowType.Debug) != 0)); // TODO: Temporary passing filter here switch (shadowType & LightShadowType.FilterMask) { case LightShadowType.PCF3x3: mixin.Mixins.Add(new ShaderClassSource("ShadowMapFilterPcf", 3)); break; case LightShadowType.PCF5x5: mixin.Mixins.Add(new ShaderClassSource("ShadowMapFilterPcf", 5)); break; case LightShadowType.PCF7x7: mixin.Mixins.Add(new ShaderClassSource("ShadowMapFilterPcf", 7)); break; default: mixin.Mixins.Add(new ShaderClassSource("ShadowMapFilterDefault")); break; } shadowShader = mixin; shadowMapTextureKey = ShadowMapKeys.Texture.ComposeWith(compositionKey); shadowMapTextureSizeKey = ShadowMapKeys.TextureSize.ComposeWith(compositionKey); shadowMapTextureTexelSizeKey = ShadowMapKeys.TextureTexelSize.ComposeWith(compositionKey); worldToShadowCascadeUVsKey = ShadowMapReceiverBaseKeys.WorldToShadowCascadeUV.ComposeWith(compositionKey); depthBiasesKey = ShadowMapReceiverBaseKeys.DepthBiases.ComposeWith(compositionKey); offsetScalesKey = ShadowMapReceiverBaseKeys.OffsetScales.ComposeWith(compositionKey); }
public LightGroupKey(ILightShadowMapRenderer shadowRenderer, LightShadowType shadowType, ITextureProjectionRenderer textureProjectionRenderer) { ShadowRenderer = shadowRenderer; ShadowType = shadowType; TextureProjectionRenderer = textureProjectionRenderer; }
public int Compare(int a, int b) { LightShadowType shadowTypeA = GetShadowType(Lights[a]); LightShadowType shadowTypeB = GetShadowType(Lights[b]); // Decreasing order so that non shadowed lights are last return(((int)shadowTypeB).CompareTo((int)shadowTypeA)); }
/// <summary> /// Initializes a new instance of the <see cref="LightDirectionalShadowMapGroupShaderData" /> class. /// </summary> /// <param name="compositionKey">The composition key.</param> /// <param name="shadowType">Type of the shadow.</param> /// <param name="lightCountMax">The light count maximum.</param> public LightDirectionalShadowMapGroupShaderData(string compositionKey, LightShadowType shadowType, int lightCountMax) { this.shadowType = shadowType; this.cascadeCount = 1 << ((int)(shadowType & LightShadowType.CascadeMask) - 1); cascadeSplits = new float[cascadeCount * lightCountMax]; worldToShadowCascadeUV = new Matrix[cascadeCount * lightCountMax]; depthBiases = new float[lightCountMax]; offsetScales = new float[lightCountMax]; var mixin = new ShaderMixinSource(); var isDepthRangeAuto = (this.shadowType & LightShadowType.DepthRangeAuto) != 0; mixin.Mixins.Add(new ShaderClassSource(ShaderName, cascadeCount, lightCountMax, (this.shadowType & LightShadowType.BlendCascade) != 0 && !isDepthRangeAuto, isDepthRangeAuto, (this.shadowType & LightShadowType.Debug) != 0)); // TODO: Temporary passing filter here switch (shadowType & LightShadowType.FilterMask) { case LightShadowType.PCF3x3: mixin.Mixins.Add(new ShaderClassSource("ShadowMapFilterPcf", 3)); break; case LightShadowType.PCF5x5: mixin.Mixins.Add(new ShaderClassSource("ShadowMapFilterPcf", 5)); break; case LightShadowType.PCF7x7: mixin.Mixins.Add(new ShaderClassSource("ShadowMapFilterPcf", 7)); break; default: mixin.Mixins.Add(new ShaderClassSource("ShadowMapFilterDefault")); break; } shadowShader = mixin; shadowMapTextureKey = ShadowMapKeys.Texture.ComposeWith(compositionKey); shadowMapTextureSizeKey = ShadowMapKeys.TextureSize.ComposeWith(compositionKey); shadowMapTextureTexelSizeKey = ShadowMapKeys.TextureTexelSize.ComposeWith(compositionKey); cascadeSplitsKey = ShadowMapReceiverDirectionalKeys.CascadeDepthSplits.ComposeWith(compositionKey); worldToShadowCascadeUVsKey = ShadowMapReceiverBaseKeys.WorldToShadowCascadeUV.ComposeWith(compositionKey); depthBiasesKey = ShadowMapReceiverBaseKeys.DepthBiases.ComposeWith(compositionKey); offsetScalesKey = ShadowMapReceiverBaseKeys.OffsetScales.ComposeWith(compositionKey); }
public override ILightShadowMapShaderGroupData CreateShaderGroupData(string compositionKey, LightShadowType shadowType, int maxLightCount) { return(new LightDirectionalShadowMapGroupShaderData(compositionKey, shadowType, maxLightCount)); }
/// <summary> /// Initializes a new instance of the <see cref="LightSpotShadowMapGroupShaderData" /> class. /// </summary> /// <param name="shadowType">Type of the shadow.</param> /// <param name="lightCountMax">The light count maximum.</param> public LightSpotShadowMapGroupShaderData(LightShadowType shadowType) { this.shadowType = shadowType; }
public override ILightShadowMapShaderGroupData CreateShaderGroupData(LightShadowType shadowType) { return(new LightDirectionalShadowMapGroupShaderData(shadowType)); }
public ShaderGroupData(LightShadowType shadowType) : base(shadowType) { }
public override void ProcessLights(ProcessLightsParameters parameters) { if (parameters.LightCollection.Count == 0) { return; } // Check if we have a fallback renderer next in the chain, in case we don't need shadows bool hasNextRenderer = parameters.RendererIndex < (parameters.Renderers.Length - 1); ILightShadowMapRenderer currentShadowRenderer = null; LightShadowType currentShadowType = 0; // Start by filtering/sorting what can be processed shadowComparer.ShadowMapTexturesPerLight = parameters.ShadowMapTexturesPerLight; shadowComparer.Lights = parameters.LightCollection; parameters.LightIndices.Sort(0, parameters.LightIndices.Count, shadowComparer); // Loop over the number of lights + 1 where the last iteration will always flush the last batch of lights for (int j = 0; j < parameters.LightIndices.Count + 1;) { LightShadowType nextShadowType = 0; ILightShadowMapRenderer nextShadowRenderer = null; LightShadowMapTexture nextShadowTexture = null; LightComponent nextLight = null; if (j < parameters.LightIndices.Count) { nextLight = parameters.LightCollection[parameters.LightIndices[j]]; if (parameters.ShadowMapRenderer != null && parameters.ShadowMapTexturesPerLight.TryGetValue(nextLight, out nextShadowTexture) && nextShadowTexture.Atlas != null) // atlas could not be allocated? treat it as a non-shadowed texture { nextShadowType = nextShadowTexture.ShadowType; nextShadowRenderer = nextShadowTexture.Renderer; } } // Flush current group if (j == parameters.LightIndices.Count || currentShadowType != nextShadowType || currentShadowRenderer != nextShadowRenderer) { if (processedLights.Count > 0) { var lightGroupKey = new LightGroupKey(currentShadowRenderer, currentShadowType); LightShaderGroupDynamic lightShaderGroup; if (!lightShaderGroupPool.TryGetValue(lightGroupKey, out lightShaderGroup)) { ILightShadowMapShaderGroupData shadowGroupData = null; if (currentShadowRenderer != null) { shadowGroupData = currentShadowRenderer.CreateShaderGroupData(currentShadowType); } lightShaderGroup = CreateLightShaderGroup(parameters.Context, shadowGroupData); lightShaderGroup.SetViews(parameters.Views); lightShaderGroupPool.Add(lightGroupKey, lightShaderGroup); } // Add view and lights var allowedLightCount = lightShaderGroup.AddView(parameters.ViewIndex, parameters.View, processedLights.Count); for (int i = 0; i < allowedLightCount; ++i) { var light = processedLights[i]; lightShaderGroup.AddLight(light.Light, light.ShadowMapTexture); } // TODO: assign extra lights to non-shadow rendering if possible //for (int i = lightCount; i < processedLights.Count; ++i) // XXX.AddLight(processedLights[i], null); var lightShaderGroupEntry = new LightShaderGroupEntry(lightGroupKey, lightShaderGroup); if (!lightShaderGroups.Contains(lightShaderGroupEntry)) { lightShaderGroups.Add(lightShaderGroupEntry); } processedLights.Clear(); } // Start next group currentShadowType = nextShadowType; currentShadowRenderer = nextShadowRenderer; } if (j < parameters.LightIndices.Count) { // Do we need to process non shadowing lights or defer it to something else? if (nextShadowTexture == null && hasNextRenderer) { // Break out so the remaining lights can be handled by the next renderer break; } parameters.LightIndices.RemoveAt(j); processedLights.Add(new LightDynamicEntry(nextLight, nextShadowTexture)); } else { j++; } } processedLights.Clear(); }
public override ILightShadowMapShaderGroupData CreateShaderGroupData(string compositionKey, LightShadowType shadowType, int maxLightCount) { return new LightDirectionalShadowMapGroupShaderData(compositionKey, shadowType, maxLightCount); }
private ILightShadowMapShaderGroupData CreateShadowMapShaderGroupData(ILightShadowMapRenderer shadowRenderer, LightShadowType shadowType) { ILightShadowMapShaderGroupData shadowGroupData = shadowRenderer?.CreateShaderGroupData(shadowType); return(shadowGroupData); }
public override void ProcessLights(ProcessLightsParameters parameters) { if (parameters.LightCollection.Count == 0) { return; } // Check if we have a fallback renderer next in the chain, in case we don't need shadows bool hasNextRenderer = parameters.RendererIndex < (parameters.Renderers.Length - 1); ILightShadowMapRenderer currentShadowRenderer = null; LightShadowType currentShadowType = 0; // Start by filtering/sorting what can be processed shadowComparer.ShadowMapTexturesPerLight = parameters.ShadowMapTexturesPerLight; shadowComparer.Lights = parameters.LightCollection; parameters.LightIndices.Sort(0, parameters.LightIndices.Count, shadowComparer); // Loop over the number of lights + 1 where the last iteration will always flush the last batch of lights for (int j = 0; j < parameters.LightIndices.Count + 1;) { // TODO: Eventually move this loop to a separate function that returns a structure. // These variables will contain the relevant parameters of the next usable light: LightShadowType nextShadowType = 0; ILightShadowMapRenderer nextShadowRenderer = null; LightShadowMapTexture nextShadowTexture = null; RenderLight nextLight = null; // Find the next light whose attributes aren't null: if (j < parameters.LightIndices.Count) { nextLight = parameters.LightCollection[parameters.LightIndices[j]]; if (parameters.ShadowMapRenderer != null && parameters.ShadowMapTexturesPerLight.TryGetValue(nextLight, out nextShadowTexture) && nextShadowTexture.Atlas != null) // atlas could not be allocated? treat it as a non-shadowed texture { nextShadowType = nextShadowTexture.ShadowType; nextShadowRenderer = nextShadowTexture.Renderer; } } // Flush current group // If we detect that the previous light's attributes don't match the next one's, create a new group (or add to an existing one that has the same attributes): if (j == parameters.LightIndices.Count || currentShadowType != nextShadowType || currentShadowRenderer != nextShadowRenderer) // TODO: Refactor this into a little structure instead. { if (processedLights.Count > 0) { var lightGroupKey = new LightGroupKey(currentShadowRenderer, currentShadowType); LightShaderGroupDynamic lightShaderGroup = FindOrCreateLightShaderGroup(lightGroupKey, parameters); // Add view and lights to the current group: var allowedLightCount = lightShaderGroup.AddView(parameters.ViewIndex, parameters.View, processedLights.Count); for (int i = 0; i < allowedLightCount; ++i) { LightDynamicEntry light = processedLights[i]; lightShaderGroup.AddLight(light.Light, light.ShadowMapTexture); } // TODO: assign extra lights to non-shadow rendering if possible //for (int i = lightCount; i < processedLights.Count; ++i) // XXX.AddLight(processedLights[i], null); // Add the current light shader group to the collection if it hasn't already been added: var lightShaderGroupEntry = new LightShaderGroupEntry <LightGroupKey>(lightGroupKey, lightShaderGroup); if (!lightShaderGroups.Contains(lightShaderGroupEntry)) { lightShaderGroups.Add(lightShaderGroupEntry); } processedLights.Clear(); } // Start next group currentShadowType = nextShadowType; currentShadowRenderer = nextShadowRenderer; } if (j < parameters.LightIndices.Count) { // Do we need to process non shadowing lights or defer it to something else? if (nextShadowTexture == null && hasNextRenderer) { // Break out so the remaining lights can be handled by the next renderer break; } parameters.LightIndices.RemoveAt(j); processedLights.Add(new LightDynamicEntry(nextLight, nextShadowTexture)); } else { j++; } } processedLights.Clear(); }
private bool PrepareRenderModelForRendering(RenderContext context, RenderModel model) { var shaderKeyIdBuilder = new ObjectIdSimpleBuilder(); var parametersKeyIdBuilder = new ObjectIdSimpleBuilder(); //var idBuilder = new ObjectIdBuilder(); var modelComponent = model.ModelComponent; var group = modelComponent.Entity.Group; var modelBoundingBox = modelComponent.BoundingBox; directLightsPerModel.Clear(); directLightShaderGroupEntryKeys.Clear(); directLightShaderGroupEntryKeysNoShadows.Clear(); environmentLightsPerModel.Clear(); environmentLightShaderGroupEntryKeys.Clear(); // This loop is looking for visible lights per render model and calculate a ShaderId and ParametersId // TODO: Part of this loop could be processed outisde of the PrepareRenderModelForRendering // For example: Environment lights or directional lights are always active, so we could pregenerate part of the // id and groups outside this loop. Also considering that each light renderer has a maximum of lights // we could pre foreach (var activeRenderer in activeRenderers) { var lightRenderer = activeRenderer.LightRenderer; var lightCollection = activeRenderer.LightGroup.FindLightCollectionByGroup(group); var lightCount = lightCollection == null ? 0 : lightCollection.Count; int lightMaxCount = Math.Min(lightCount, lightRenderer.LightMaxCount); var lightRendererId = lightRenderer.LightRendererId; var allocCountForNewLightType = lightRenderer.AllocateLightMaxCount ? (byte)lightRenderer.LightMaxCount : (byte)1; var currentShaderKey = new LightForwardShaderEntryKey(); // Path for environment lights if (lightRenderer.IsEnvironmentLight) { // The loop is simpler for environment lights (single group per light, no shadow maps, no bounding box...etc) for (int i = 0; i < lightMaxCount; i++) { var light = lightCollection[i]; currentShaderKey = new LightForwardShaderEntryKey(lightRendererId, 0, allocCountForNewLightType); unsafe { shaderKeyIdBuilder.Write(*(uint *)¤tShaderKey); } parametersKeyIdBuilder.Write(light.Id); environmentLightsPerModel.Add(new LightEntry(environmentLightShaderGroupEntryKeys.Count, 0, light, null)); environmentLightShaderGroupEntryKeys.Add(new LightForwardShaderFullEntryKey(currentShaderKey, lightRenderer, null)); } } else { ILightShadowMapRenderer currentShadowRenderer = null; for (int i = 0; i < lightMaxCount; i++) { var light = lightCollection[i]; var directLight = (IDirectLight)light.Type; // If the light does not intersects the model, we can skip it if (directLight.HasBoundingBox && !light.BoundingBox.Intersects(ref modelBoundingBox)) { continue; } LightShadowMapTexture shadowTexture = null; LightShadowType shadowType = 0; ILightShadowMapRenderer newShadowRenderer = null; if (shadowMapRenderer != null && shadowMapRenderer.LightComponentsWithShadows.TryGetValue(light, out shadowTexture)) { shadowType = shadowTexture.ShadowType; newShadowRenderer = shadowTexture.Renderer; } if (i == 0) { currentShaderKey = new LightForwardShaderEntryKey(lightRendererId, shadowType, allocCountForNewLightType); currentShadowRenderer = newShadowRenderer; } else { if (currentShaderKey.LightRendererId == lightRendererId && currentShaderKey.ShadowType == shadowType) { if (!lightRenderer.AllocateLightMaxCount) { currentShaderKey.LightCount++; } } else { unsafe { shaderKeyIdBuilder.Write(*(uint *)¤tShaderKey); } directLightShaderGroupEntryKeys.Add(new LightForwardShaderFullEntryKey(currentShaderKey, lightRenderer, currentShadowRenderer)); currentShaderKey = new LightForwardShaderEntryKey(lightRendererId, shadowType, allocCountForNewLightType); currentShadowRenderer = newShadowRenderer; } } parametersKeyIdBuilder.Write(light.Id); directLightsPerModel.Add(new LightEntry(directLightShaderGroupEntryKeys.Count, directLightShaderGroupEntryKeysNoShadows.Count, light, shadowTexture)); } if (directLightsPerModel.Count > 0) { directLightShaderGroupEntryKeysNoShadows.Add(new LightForwardShaderFullEntryKey(new LightForwardShaderEntryKey(lightRendererId, 0, (byte)directLightsPerModel.Count), lightRenderer, null)); unsafe { shaderKeyIdBuilder.Write(*(uint *)¤tShaderKey); } directLightShaderGroupEntryKeys.Add(new LightForwardShaderFullEntryKey(currentShaderKey, lightRenderer, currentShadowRenderer)); } } } // Find or create an existing shaders/parameters permutation // Build the keys for Shaders and Parameters permutations ObjectId shaderKeyId; ObjectId parametersKeyId; shaderKeyIdBuilder.ComputeHash(out shaderKeyId); parametersKeyIdBuilder.ComputeHash(out parametersKeyId); // Calculate the shader parameters just once // If we don't have already this permutation, use it LightShaderPermutationEntry newLightShaderPermutationEntry; if (!shaderEntries.TryGetValue(shaderKeyId, out newLightShaderPermutationEntry)) { newLightShaderPermutationEntry = CreateShaderPermutationEntry(); shaderEntries.Add(shaderKeyId, newLightShaderPermutationEntry); } LightParametersPermutationEntry newShaderEntryParameters; // Calculate the shader parameters just once per light combination and for this rendering pass if (!lightParameterEntries.TryGetValue(parametersKeyId, out newShaderEntryParameters)) { newShaderEntryParameters = CreateParametersPermutationEntry(newLightShaderPermutationEntry); lightParameterEntries.Add(parametersKeyId, newShaderEntryParameters); } modelToLights.Add(model, new RenderModelLights(newLightShaderPermutationEntry, newShaderEntryParameters)); return(true); }
private LightParametersPermutationEntry PreparePermutationEntryForRendering(RenderViewLightData renderViewData, bool isShadowReceiver, ref BoundingBox boundingBox, EntityGroup group, int effectSlot) { var shaderKeyIdBuilder = new ObjectIdSimpleBuilder(); var parametersKeyIdBuilder = new ObjectIdSimpleBuilder(); directLightsPerMesh.Clear(); directLightShaderGroupEntryKeys.Clear(); environmentLightsPerMesh.Clear(); environmentLightShaderGroupEntryKeys.Clear(); // Create different parameter collections depending on shadows // TODO GRAPHICS REFACTOR can we use the same parameter collection for shadowed/non-shadowed? parametersKeyIdBuilder.Write(isShadowReceiver ? 1U : 0U); shaderKeyIdBuilder.Write(isShadowReceiver ? 1U : 0U); shaderKeyIdBuilder.Write((uint)effectSlot); // This loop is looking for visible lights per render model and calculate a ShaderId and ParametersId // TODO: Part of this loop could be processed outisde of the PrepareRenderMeshForRendering // For example: Environment lights or directional lights are always active, so we could pregenerate part of the // id and groups outside this loop. Also considering that each light renderer has a maximum of lights // we could pre foreach (var activeRenderer in renderViewData.ActiveRenderers) { var lightRenderer = activeRenderer.LightRenderer; var lightCollection = activeRenderer.LightGroup.FindLightCollectionByGroup(group); var lightCount = lightCollection == null ? 0 : lightCollection.Count; int lightMaxCount = Math.Min(lightCount, lightRenderer.LightMaxCount); var lightRendererId = lightRenderer.LightRendererId; var allocCountForNewLightType = lightRenderer.AllocateLightMaxCount ? (byte)lightRenderer.LightMaxCount : (byte)1; var currentShaderKey = new LightForwardShaderEntryKey(); // Path for environment lights if (lightRenderer.IsEnvironmentLight) { // The loop is simpler for environment lights (single group per light, no shadow maps, no bounding box...etc) for (int i = 0; i < lightMaxCount; i++) { var light = lightCollection[i]; currentShaderKey = new LightForwardShaderEntryKey(lightRendererId, 0, allocCountForNewLightType); unsafe { shaderKeyIdBuilder.Write(*(uint *)¤tShaderKey); } parametersKeyIdBuilder.Write(light.Id); environmentLightsPerMesh.Add(new LightEntry(environmentLightShaderGroupEntryKeys.Count, light, null)); environmentLightShaderGroupEntryKeys.Add(new LightForwardShaderFullEntryKey(currentShaderKey, lightRenderer, null)); } } else { ILightShadowMapRenderer currentShadowRenderer = null; bool hasDirectLight = false; for (int i = 0; i < lightMaxCount; i++) { var light = lightCollection[i]; var directLight = (IDirectLight)light.Type; // If the light does not intersects the model, we can skip it if (directLight.HasBoundingBox && !light.BoundingBox.Intersects(ref boundingBox)) { continue; } LightShadowMapTexture shadowTexture = null; LightShadowType shadowType = 0; ILightShadowMapRenderer newShadowRenderer = null; if (ShadowMapRenderer != null && renderViewData.LightComponentsWithShadows.TryGetValue(light, out shadowTexture)) { shadowType = shadowTexture.ShadowType; newShadowRenderer = (ILightShadowMapRenderer)shadowTexture.Renderer; } if (!hasDirectLight) { hasDirectLight = true; currentShaderKey = new LightForwardShaderEntryKey(lightRendererId, shadowType, allocCountForNewLightType); currentShadowRenderer = newShadowRenderer; } else { if (currentShaderKey.LightRendererId == lightRendererId && currentShaderKey.ShadowType == shadowType) { if (!lightRenderer.AllocateLightMaxCount) { currentShaderKey.LightCount++; } } else { unsafe { shaderKeyIdBuilder.Write(*(uint *)¤tShaderKey); } directLightShaderGroupEntryKeys.Add(new LightForwardShaderFullEntryKey(currentShaderKey, lightRenderer, isShadowReceiver ? currentShadowRenderer : null)); currentShaderKey = new LightForwardShaderEntryKey(lightRendererId, shadowType, allocCountForNewLightType); currentShadowRenderer = newShadowRenderer; } } parametersKeyIdBuilder.Write(light.Id); directLightsPerMesh.Add(new LightEntry(directLightShaderGroupEntryKeys.Count, light, shadowTexture)); } if (hasDirectLight) { unsafe { shaderKeyIdBuilder.Write(*(uint *)¤tShaderKey); } directLightShaderGroupEntryKeys.Add(new LightForwardShaderFullEntryKey(currentShaderKey, lightRenderer, isShadowReceiver ? currentShadowRenderer : null)); } } } // Find or create an existing shaders/parameters permutation // Build the keys for Shaders and Parameters permutations ObjectId shaderKeyId; ObjectId parametersKeyId; shaderKeyIdBuilder.ComputeHash(out shaderKeyId); parametersKeyIdBuilder.ComputeHash(out parametersKeyId); // Calculate the shader parameters just once // If we don't have already this permutation, use it LightShaderPermutationEntry newLightShaderPermutationEntry; if (!shaderEntries.TryGetValue(shaderKeyId, out newLightShaderPermutationEntry)) { newLightShaderPermutationEntry = CreateShaderPermutationEntry(); shaderEntries.Add(shaderKeyId, newLightShaderPermutationEntry); } // Calculate the shader parameters just once per light combination and for this rendering pass LightParametersPermutationEntry newShaderEntryParameters; if (!lightParameterEntries.TryGetValue(parametersKeyId, out newShaderEntryParameters)) { newShaderEntryParameters = CreateParametersPermutationEntry(newLightShaderPermutationEntry); lightParameterEntries.Add(parametersKeyId, newShaderEntryParameters); } return(newShaderEntryParameters); }
public abstract ILightShadowMapShaderGroupData CreateShaderGroupData(string compositionKey, LightShadowType shadowType, int maxLightCount);
public override void ProcessLights(ProcessLightsParameters parameters) { if (parameters.LightCollection.Count == 0) { return; } ILightShadowMapRenderer currentShadowRenderer = null; LightShadowType currentShadowType = 0; // Start by filtering/sorting what can be processed shadowComparer.ShadowMapTexturesPerLight = parameters.ShadowMapTexturesPerLight; parameters.LightCollection.Sort(parameters.LightStart, parameters.LightEnd - parameters.LightStart, shadowComparer); for (int index = parameters.LightStart; index <= parameters.LightEnd; index++) { LightShadowType nextShadowType = 0; ILightShadowMapRenderer nextShadowRenderer = null; LightShadowMapTexture nextShadowTexture = null; LightComponent nextLight = null; if (index < parameters.LightEnd) { nextLight = parameters.LightCollection[index]; if (parameters.ShadowMapRenderer != null && parameters.ShadowMapTexturesPerLight.TryGetValue(nextLight, out nextShadowTexture) && nextShadowTexture.Atlas != null) // atlas could not be allocated? treat it as a non-shadowed texture { nextShadowType = nextShadowTexture.ShadowType; nextShadowRenderer = nextShadowTexture.Renderer; } } // Flush current group if (index == parameters.LightEnd || currentShadowType != nextShadowType || currentShadowRenderer != nextShadowRenderer) { if (processedLights.Count > 0) { var lightGroupKey = new LightGroupKey(currentShadowRenderer, currentShadowType); LightShaderGroupDynamic lightShaderGroup; if (!lightShaderGroupPool.TryGetValue(lightGroupKey, out lightShaderGroup)) { ILightShadowMapShaderGroupData shadowGroupData = null; if (currentShadowRenderer != null) { shadowGroupData = currentShadowRenderer.CreateShaderGroupData(currentShadowType); } lightShaderGroup = CreateLightShaderGroup(parameters.Context, shadowGroupData); lightShaderGroup.SetViews(parameters.Views); lightShaderGroupPool.Add(lightGroupKey, lightShaderGroup); } // Add view and lights var allowedLightCount = lightShaderGroup.AddView(parameters.ViewIndex, parameters.View, processedLights.Count); for (int i = 0; i < allowedLightCount; ++i) { var light = processedLights[i]; lightShaderGroup.AddLight(light.Light, light.ShadowMapTexture); } // TODO: assign extra lights to non-shadow rendering if possible //for (int i = lightCount; i < processedLights.Count; ++i) // XXX.AddLight(processedLights[i], null); var lightShaderGroupEntry = new LightShaderGroupEntry(lightGroupKey, lightShaderGroup); if (!lightShaderGroups.Contains(lightShaderGroupEntry)) { lightShaderGroups.Add(lightShaderGroupEntry); } processedLights.Clear(); } // Start next group currentShadowType = nextShadowType; currentShadowRenderer = nextShadowRenderer; } if (index < parameters.LightEnd) { // Do we need to process non shadowing lights or defer it to something else? if (nextShadowTexture == null && NonShadowRenderer != null) { parameters.LightStart = index; NonShadowRenderer.ProcessLights(parameters); break; } processedLights.Add(new LightDynamicEntry(nextLight, nextShadowTexture)); } } processedLights.Clear(); }
/// <summary> /// Initializes a new instance of the <see cref="LightDirectionalShadowMapGroupShaderData" /> class. /// </summary> /// <param name="shadowType">Type of the shadow.</param> /// <param name="lightCountMax">The light count maximum.</param> public LightDirectionalShadowMapGroupShaderData(LightShadowType shadowType) { this.shadowType = shadowType; this.cascadeCount = 1 << ((int)(shadowType & LightShadowType.CascadeMask) - 1); }
public LightForwardShaderEntryKey(byte lightRendererId, LightShadowType shadowType, byte lightCount) { LightRendererId = lightRendererId; ShadowType = shadowType; LightCount = lightCount; }
public LightGroupKey(ILightShadowMapRenderer shadowRenderer, LightShadowType shadowType) { ShadowRenderer = shadowRenderer; ShadowType = shadowType; }
private ILightShadowMapShaderGroupData CreateShadowMapShaderGroupData(ILightShadowMapRenderer shadowRenderer, LightShadowType shadowType) { ILightShadowMapShaderGroupData shadowGroupData = null; if (shadowRenderer != null) { shadowGroupData = shadowRenderer.CreateShaderGroupData(shadowType); } return(shadowGroupData); }
public override ILightShadowMapShaderGroupData CreateShaderGroupData(LightShadowType shadowType) { return new LightSpotShadowMapGroupShaderData(shadowType); }
/// <summary> /// Initializes a new instance of the <see cref="LightSpotShadowMapGroupShaderData" /> class. /// </summary> /// <param name="shadowType">Type of the shadow.</param> /// <param name="lightCountMax">The light count maximum.</param> public LightSpotShadowMapGroupShaderData(LightShadowType shadowType) : base(shadowType) { }
/// <summary> /// Initializes a new instance of the <see cref="ShaderGroupData" /> class. /// </summary> /// <param name="shadowType">Type of the shadow.</param> /// <param name="lightCountMax">The light count maximum.</param> public ShaderGroupData(LightShadowType shadowType) : base(shadowType) { cascadeCount = 1 << ((int)(shadowType & LightShadowType.CascadeMask) - 1); }
public LightShadowMapShaderGroupDataBase(LightShadowType shadowType) { ShadowType = shadowType; }
public abstract ILightShadowMapShaderGroupData CreateShaderGroupData(LightShadowType shadowType);
public override ILightShadowMapShaderGroupData CreateShaderGroupData(LightShadowType shadowType) { return(new ShaderGroupData(shadowType)); }