Exemple #1
0
        public static void RenderLightVolumes(this IRenderPass2D pass, RenderingData renderingData, CommandBuffer cmd, int layerToRender, int endLayerValue,
                                              RenderTargetIdentifier renderTexture, RenderTargetIdentifier depthTexture, RenderBufferStoreAction intermediateStoreAction,
                                              RenderBufferStoreAction finalStoreAction, bool requiresRTInit, List <Light2D> lights)
        {
            var maxShadowLightCount = ShadowRendering.maxTextureCount * 4;  // Now encodes shadows into RGBA as well as seperate textures

            NativeArray <bool> doesLightAtIndexHaveShadows = new NativeArray <bool>(lights.Count, Allocator.Temp);

            // This case should never happen, but if it does it may cause an infinite loop later.
            if (maxShadowLightCount < 1)
            {
                Debug.LogError("maxShadowLightCount cannot be less than 1");
                return;
            }

            // Determine last light with volumetric shadows to be rendered if we want to use a different store action after using rendering its volumetric shadows
            int useFinalStoreActionAfter = lights.Count;

            if (intermediateStoreAction != finalStoreAction)
            {
                for (int i = lights.Count - 1; i >= 0; i--)
                {
                    if (lights[i].renderVolumetricShadows)
                    {
                        useFinalStoreActionAfter = i;
                        break;
                    }
                }
            }

            // Break up light rendering into batches for the purpose of shadow casting
            var lightIndex = 0;

            while (lightIndex < lights.Count)
            {
                var remainingLights = (uint)lights.Count - lightIndex;
                var batchedLights   = 0;

                // Add lights to our batch until the number of shadow textures reach the maxShadowTextureCount
                var shadowLightCount = 0;
                while (batchedLights < remainingLights && shadowLightCount < maxShadowLightCount)
                {
                    int curLightIndex = lightIndex + batchedLights;
                    var light         = lights[curLightIndex];

                    if (CanCastVolumetricShadows(light, endLayerValue))
                    {
                        doesLightAtIndexHaveShadows[curLightIndex] = false;
                        if (ShadowRendering.PrerenderShadows(pass, renderingData, cmd, layerToRender, light, shadowLightCount, light.shadowVolumeIntensity))
                        {
                            doesLightAtIndexHaveShadows[curLightIndex] = true;
                            shadowLightCount++;
                        }
                    }
                    batchedLights++;
                }

                // Set the current RT to the light RT
                if (shadowLightCount > 0 || requiresRTInit)
                {
                    var storeAction = lightIndex + batchedLights >= useFinalStoreActionAfter ? finalStoreAction : intermediateStoreAction;
                    cmd.SetRenderTarget(renderTexture, RenderBufferLoadAction.Load, storeAction, depthTexture, RenderBufferLoadAction.Load, storeAction);
                    requiresRTInit = false;
                }

                // Render all the lights.
                shadowLightCount = 0;
                for (var lightIndexOffset = 0; lightIndexOffset < batchedLights; lightIndexOffset++)
                {
                    var light = lights[(int)(lightIndex + lightIndexOffset)];

                    if (light.lightType == Light2D.LightType.Global)
                    {
                        continue;
                    }

                    if (light.volumeIntensity <= 0.0f || !light.volumeIntensityEnabled)
                    {
                        continue;
                    }

                    var topMostLayerValue = light.GetTopMostLitLayer();
                    if (endLayerValue == topMostLayerValue) // this implies the layer is correct
                    {
                        var lightVolumeMaterial = pass.rendererData.GetLightMaterial(light, true);
                        var lightMesh           = light.lightMesh;

                        // Set the shadow texture to read from.
                        if (doesLightAtIndexHaveShadows[lightIndex + lightIndexOffset])
                        {
                            ShadowRendering.SetGlobalShadowTexture(cmd, light, shadowLightCount++);
                        }
                        else
                        {
                            ShadowRendering.DisableGlobalShadowTexture(cmd);
                        }

                        if (light.lightType == Light2D.LightType.Sprite && light.lightCookieSprite != null && light.lightCookieSprite.texture != null)
                        {
                            cmd.SetGlobalTexture(k_CookieTexID, light.lightCookieSprite.texture);
                        }

                        SetGeneralLightShaderGlobals(pass, cmd, light);

                        // Is this needed
                        if (light.normalMapQuality != Light2D.NormalMapQuality.Disabled || light.lightType == Light2D.LightType.Point)
                        {
                            SetPointLightShaderGlobals(pass, cmd, light);
                        }

                        // Could be combined...
                        if (light.lightType == Light2D.LightType.Parametric || light.lightType == Light2D.LightType.Freeform || light.lightType == Light2D.LightType.Sprite)
                        {
                            cmd.DrawMesh(lightMesh, light.transform.localToWorldMatrix, lightVolumeMaterial);
                        }
                        else if (light.lightType == Light2D.LightType.Point)
                        {
                            DrawPointLight(cmd, light, lightMesh, lightVolumeMaterial);
                        }
                    }
                }


                // Release all of the temporary shadow textures
                for (var releaseIndex = shadowLightCount - 1; releaseIndex >= 0; releaseIndex--)
                {
                    ShadowRendering.ReleaseShadowRenderTexture(cmd, releaseIndex);
                }

                lightIndex += batchedLights;
            }

            doesLightAtIndexHaveShadows.Dispose();
        }
Exemple #2
0
        private static void RenderLightSet(IRenderPass2D pass, RenderingData renderingData, int blendStyleIndex, CommandBuffer cmd, int layerToRender, RenderTargetIdentifier renderTexture, List <Light2D> lights)
        {
            var maxShadowLightCount = ShadowRendering.maxTextureCount * 4;
            var requiresRTInit      = true;

            // This case should never happen, but if it does it may cause an infinite loop later.
            if (maxShadowLightCount < 1)
            {
                Debug.LogError("maxShadowTextureCount cannot be less than 1");
                return;
            }


            NativeArray <bool> doesLightAtIndexHaveShadows = new NativeArray <bool>(lights.Count, Allocator.Temp);

            // Break up light rendering into batches for the purpose of shadow casting
            var lightIndex = 0;

            while (lightIndex < lights.Count)
            {
                var remainingLights = (uint)lights.Count - lightIndex;
                var batchedLights   = 0;

                // Add lights to our batch until the number of shadow textures reach the maxShadowTextureCount
                int shadowLightCount = 0;
                while (batchedLights < remainingLights && shadowLightCount < maxShadowLightCount)
                {
                    int curLightIndex = lightIndex + batchedLights;
                    var light         = lights[curLightIndex];
                    if (CanCastShadows(light, layerToRender))
                    {
                        doesLightAtIndexHaveShadows[curLightIndex] = false;
                        if (ShadowRendering.PrerenderShadows(pass, renderingData, cmd, layerToRender, light, shadowLightCount, light.shadowIntensity))
                        {
                            doesLightAtIndexHaveShadows[curLightIndex] = true;
                            shadowLightCount++;
                        }
                    }
                    batchedLights++;
                }


                // Set the current RT to the light RT
                if (shadowLightCount > 0 || requiresRTInit)
                {
                    cmd.SetRenderTarget(renderTexture, RenderBufferLoadAction.Load, RenderBufferStoreAction.Store, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.DontCare);
                    requiresRTInit = false;
                }

                // Render all the lights.
                shadowLightCount = 0;
                for (var lightIndexOffset = 0; lightIndexOffset < batchedLights; lightIndexOffset++)
                {
                    var light = lights[(int)(lightIndex + lightIndexOffset)];

                    if (light != null &&
                        light.lightType != Light2D.LightType.Global &&
                        light.blendStyleIndex == blendStyleIndex &&
                        light.IsLitLayer(layerToRender))
                    {
                        // Render light
                        var lightMaterial = pass.rendererData.GetLightMaterial(light, false);
                        if (lightMaterial == null)
                        {
                            continue;
                        }

                        var lightMesh = light.lightMesh;
                        if (lightMesh == null)
                        {
                            continue;
                        }

                        // Set the shadow texture to read from
                        if (doesLightAtIndexHaveShadows[lightIndex + lightIndexOffset])
                        {
                            ShadowRendering.SetGlobalShadowTexture(cmd, light, shadowLightCount++);
                        }
                        else
                        {
                            ShadowRendering.DisableGlobalShadowTexture(cmd);
                        }


                        if (light.lightType == Light2D.LightType.Sprite && light.lightCookieSprite != null && light.lightCookieSprite.texture != null)
                        {
                            cmd.SetGlobalTexture(k_CookieTexID, light.lightCookieSprite.texture);
                        }

                        SetGeneralLightShaderGlobals(pass, cmd, light);

                        if (light.normalMapQuality != Light2D.NormalMapQuality.Disabled || light.lightType == Light2D.LightType.Point)
                        {
                            SetPointLightShaderGlobals(pass, cmd, light);
                        }

                        // Light code could be combined...
                        if (light.lightType == (Light2D.LightType)Light2D.DeprecatedLightType.Parametric || light.lightType == Light2D.LightType.Freeform || light.lightType == Light2D.LightType.Sprite)
                        {
                            cmd.DrawMesh(lightMesh, light.transform.localToWorldMatrix, lightMaterial);
                        }
                        else if (light.lightType == Light2D.LightType.Point)
                        {
                            DrawPointLight(cmd, light, lightMesh, lightMaterial);
                        }
                    }
                }

                // Release all of the temporary shadow textures
                for (var releaseIndex = shadowLightCount - 1; releaseIndex >= 0; releaseIndex--)
                {
                    ShadowRendering.ReleaseShadowRenderTexture(cmd, releaseIndex);
                }

                lightIndex += batchedLights;
            }

            doesLightAtIndexHaveShadows.Dispose();
        }
Exemple #3
0
 public static void CreateShadowRenderTexture(IRenderPass2D pass, RenderingData renderingData, CommandBuffer cmdBuffer, int shadowIndex)
 {
     CreateShadowRenderTexture(pass, m_RenderTargets[shadowIndex], renderingData, cmdBuffer);
 }
Exemple #4
0
        public static void RenderShadows(IRenderPass2D pass, RenderingData renderingData, CommandBuffer cmdBuffer, int layerToRender, Light2D light, float shadowIntensity, RenderTargetIdentifier renderTexture, int colorBit)
        {
            using (new ProfilingScope(cmdBuffer, m_ProfilingSamplerShadows))
            {
                bool hasShadow          = false;
                var  shadowCasterGroups = ShadowCasterGroup2DManager.shadowCasterGroups;
                if (shadowCasterGroups != null && shadowCasterGroups.Count > 0)
                {
                    // Before doing anything check to see if any of the shadow casters are visible to this light
                    for (var group = 0; group < shadowCasterGroups.Count; group++)
                    {
                        var shadowCasterGroup = shadowCasterGroups[group];
                        var shadowCasters     = shadowCasterGroup.GetShadowCasters();

                        if (shadowCasters != null)
                        {
                            // Draw the projected shadows for the shadow caster group. Writing into the group stencil buffer bit
                            for (var i = 0; i < shadowCasters.Count; i++)
                            {
                                var shadowCaster = shadowCasters[i];
                                if (shadowCaster.IsLit(light))
                                {
                                    hasShadow = true;
                                    break;
                                }
                            }
                        }
                    }

                    if (hasShadow)
                    {
                        cmdBuffer.SetRenderTarget(renderTexture, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.DontCare);

                        if (colorBit == 0)
                        {
                            cmdBuffer.ClearRenderTarget(true, true, Color.clear);  // clear stencil
                        }
                        using (new ProfilingScope(cmdBuffer, m_ProfilingSamplerShadowColorsLookup[colorBit]))
                        {
                            var shadowRadius = light.boundingSphere.radius;

                            cmdBuffer.SetGlobalVector(k_LightPosID, light.transform.position);
                            cmdBuffer.SetGlobalFloat(k_ShadowRadiusID, shadowRadius);


                            cmdBuffer.SetGlobalColor(k_ShadowColorMaskID, k_ColorLookup[colorBit]);
                            var projectedShadowsMaterial = pass.rendererData.GetProjectedShadowMaterial(colorBit);
                            var selfShadowMaterial       = pass.rendererData.GetSpriteSelfShadowMaterial(colorBit);
                            var unshadowMaterial         = pass.rendererData.GetSpriteUnshadowMaterial(colorBit);
                            var setGlobalStencilMaterial = pass.rendererData.GetStencilOnlyShadowMaterial(colorBit);

                            for (var group = 0; group < shadowCasterGroups.Count; group++)
                            {
                                var shadowCasterGroup = shadowCasterGroups[group];
                                var shadowCasters     = shadowCasterGroup.GetShadowCasters();

                                if (shadowCasters != null)
                                {
                                    // Draw the projected shadows for the shadow caster group. Writing into the group stencil buffer bit
                                    for (var i = 0; i < shadowCasters.Count; i++)
                                    {
                                        var shadowCaster = shadowCasters[i];

                                        if (shadowCaster.IsLit(light))
                                        {
                                            if (shadowCaster != null && projectedShadowsMaterial != null && shadowCaster.IsShadowedLayer(layerToRender))
                                            {
                                                if (shadowCaster.castsShadows)
                                                {
                                                    SetShadowProjectionGlobals(cmdBuffer, shadowCaster);
                                                    cmdBuffer.DrawMesh(shadowCaster.mesh, shadowCaster.transform.localToWorldMatrix, projectedShadowsMaterial, 0, 0);
                                                }
                                            }
                                        }
                                    }

                                    // Draw the sprites, either as self shadowing or unshadowing
                                    for (var i = 0; i < shadowCasters.Count; i++)
                                    {
                                        var shadowCaster = shadowCasters[i];

                                        if (shadowCaster.IsLit(light))
                                        {
                                            if (shadowCaster != null && shadowCaster.IsShadowedLayer(layerToRender))
                                            {
                                                if (shadowCaster.useRendererSilhouette)
                                                {
                                                    // Draw using the sprite renderer
                                                    var renderer = (Renderer)null;
                                                    shadowCaster.TryGetComponent <Renderer>(out renderer);

                                                    if (renderer != null)
                                                    {
                                                        var material = shadowCaster.selfShadows ? selfShadowMaterial : unshadowMaterial;
                                                        if (material != null)
                                                        {
                                                            cmdBuffer.DrawRenderer(renderer, material);
                                                        }
                                                    }
                                                }
                                                else
                                                {
                                                    var meshMat  = shadowCaster.transform.localToWorldMatrix;
                                                    var material = shadowCaster.selfShadows ? selfShadowMaterial : unshadowMaterial;

                                                    // Draw using the shadow mesh
                                                    if (material != null)
                                                    {
                                                        cmdBuffer.DrawMesh(shadowCaster.mesh, meshMat, material);
                                                    }
                                                }
                                            }
                                        }
                                    }

                                    // Draw the projected shadows for the shadow caster group. Writing clearing the group stencil bit, and setting the global bit
                                    for (var i = 0; i < shadowCasters.Count; i++)
                                    {
                                        var shadowCaster = shadowCasters[i];

                                        if (shadowCaster.IsLit(light))
                                        {
                                            if (shadowCaster != null && projectedShadowsMaterial != null && shadowCaster.IsShadowedLayer(layerToRender))
                                            {
                                                if (shadowCaster.castsShadows)
                                                {
                                                    SetShadowProjectionGlobals(cmdBuffer, shadowCaster);
                                                    cmdBuffer.DrawMesh(shadowCaster.mesh, shadowCaster.transform.localToWorldMatrix, projectedShadowsMaterial, 0, 1);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
Exemple #5
0
        public static void RenderLightVolumes(this IRenderPass2D pass, RenderingData renderingData, CommandBuffer cmd, int layerToRender, int endLayerValue, RenderTargetIdentifier renderTexture, RenderTargetIdentifier depthTexture, List <Light2D> lights)
        {
            var maxShadowTextureCount = ShadowRendering.maxTextureCount;
            var requiresRTInit        = true;

            // This case should never happen, but if it does it may cause an infinite loop later.
            if (maxShadowTextureCount < 1)
            {
                Debug.LogError("maxShadowTextureCount cannot be less than 1");
                return;
            }

            // Break up light rendering into batches for the purpose of shadow casting
            var lightIndex = 0;

            while (lightIndex < lights.Count)
            {
                var remainingLights = (uint)lights.Count - lightIndex;
                var batchedLights   = 0;

                // Add lights to our batch until the number of shadow textures reach the maxShadowTextureCount
                var shadowLightCount = 0;
                while (batchedLights < remainingLights && shadowLightCount < maxShadowTextureCount)
                {
                    var light = lights[lightIndex + batchedLights];
                    if (light.volumetricShadowsEnabled && light.shadowVolumeIntensity > 0)
                    {
                        ShadowRendering.CreateShadowRenderTexture(pass, renderingData, cmd, shadowLightCount);
                        ShadowRendering.PrerenderShadows(pass, renderingData, cmd, layerToRender, light, shadowLightCount, light.shadowVolumeIntensity);
                        shadowLightCount++;
                    }
                    batchedLights++;
                }

                // Set the current RT to the light RT
                if (shadowLightCount > 0 || requiresRTInit)
                {
                    cmd.SetRenderTarget(renderTexture, depthTexture);
                    requiresRTInit = false;
                }

                // Render all the lights.
                shadowLightCount = 0;
                for (var lightIndexOffset = 0; lightIndexOffset < batchedLights; lightIndexOffset++)
                {
                    var light = lights[(int)(lightIndex + lightIndexOffset)];

                    if (light.lightType == Light2D.LightType.Global)
                    {
                        continue;
                    }

                    if (light.volumeIntensity <= 0.0f || !light.volumeIntensityEnabled)
                    {
                        continue;
                    }

                    var topMostLayerValue = light.GetTopMostLitLayer();
                    if (endLayerValue == topMostLayerValue) // this implies the layer is correct
                    {
                        var lightVolumeMaterial = pass.rendererData.GetLightMaterial(light, true);
                        var lightMesh           = light.lightMesh;

                        // Set the shadow texture to read from
                        if (light.volumetricShadowsEnabled && light.shadowVolumeIntensity > 0)
                        {
                            ShadowRendering.SetGlobalShadowTexture(cmd, light, shadowLightCount++);
                        }
                        else
                        {
                            ShadowRendering.DisableGlobalShadowTexture(cmd);
                        }

                        if (light.lightType == Light2D.LightType.Sprite && light.lightCookieSprite != null && light.lightCookieSprite.texture != null)
                        {
                            cmd.SetGlobalTexture(k_CookieTexID, light.lightCookieSprite.texture);
                        }

                        SetGeneralLightShaderGlobals(pass, cmd, light);

                        // Is this needed
                        if (light.normalMapQuality != Light2D.NormalMapQuality.Disabled || light.lightType == Light2D.LightType.Point)
                        {
                            SetPointLightShaderGlobals(pass, cmd, light);
                        }

                        // Could be combined...
                        if (light.lightType == Light2D.LightType.Parametric || light.lightType == Light2D.LightType.Freeform || light.lightType == Light2D.LightType.Sprite)
                        {
                            cmd.DrawMesh(lightMesh, light.transform.localToWorldMatrix, lightVolumeMaterial);
                        }
                        else if (light.lightType == Light2D.LightType.Point)
                        {
                            DrawPointLight(cmd, light, lightMesh, lightVolumeMaterial);
                        }
                    }
                }


                // Release all of the temporary shadow textures
                for (var releaseIndex = shadowLightCount - 1; releaseIndex >= 0; releaseIndex--)
                {
                    ShadowRendering.ReleaseShadowRenderTexture(cmd, releaseIndex);
                }

                lightIndex += batchedLights;
            }
        }