Example #1
0
 public static void BuiltinBlit(this CommandBuffer cmd, Rendering.RenderTargetIdentifier source, Rendering.RenderTargetIdentifier dest, Material mat, int pass = 0)
 {
     #if UNITY_2018_2_OR_NEWER
     cmd.SetRenderTarget(dest, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store);
     dest = BuiltinRenderTextureType.CurrentActive;
     #endif
     cmd.Blit(source, dest, mat, pass);
 }
        public void SetRenderTarget(RenderTargetIdentifier[] colors, Rendering.RenderTargetIdentifier depth)
        {
            if (colors.Length < 1)
            {
                throw new ArgumentException(string.Format("colors.Length must be at least 1, but was", colors.Length));
            }
            if (colors.Length > SystemInfo.supportedRenderTargetCount)
            {
                throw new ArgumentException(string.Format("colors.Length is {0} and exceeds the maximum number of supported render targets ({1})", colors.Length, SystemInfo.supportedRenderTargetCount));
            }

            SetRenderTargetMulti_Internal(colors, depth, null, null, RenderBufferLoadAction.Load, RenderBufferStoreAction.Store);
        }
Example #3
0
 public void SetRenderTarget(RenderTargetIdentifier[] colors, Rendering.RenderTargetIdentifier depth, int mipLevel, CubemapFace cubemapFace, int depthSlice)
 {
     ValidateAgainstExecutionFlags(CommandBufferExecutionFlags.None, CommandBufferExecutionFlags.AsyncCompute);
     if (colors.Length < 1)
     {
         throw new ArgumentException(string.Format("colors.Length must be at least 1, but was {0}", colors.Length));
     }
     if (colors.Length > SystemInfo.supportedRenderTargetCount)
     {
         throw new ArgumentException(string.Format("colors.Length is {0} and exceeds the maximum number of supported render targets ({1})", colors.Length, SystemInfo.supportedRenderTargetCount));
     }
     SetRenderTargetMultiSubtarget(colors, depth, null, null, RenderBufferLoadAction.Load, RenderBufferStoreAction.Store, mipLevel, cubemapFace, depthSlice);
 }
        /// <summary>
        /// Effective Job of drawing the set of Lens Flare registered
        /// </summary>
        /// <param name="lensFlareShader">Lens Flare material (HDRP or URP shader)</param>
        /// <param name="lensFlares">Set of Lens Flare</param>
        /// <param name="cam">Camera</param>
        /// <param name="actualWidth">Width actually used for rendering after dynamic resolution and XR is applied.</param>
        /// <param name="actualHeight">Height actually used for rendering after dynamic resolution and XR is applied.</param>
        /// <param name="usePanini">Set if use Panani Projection</param>
        /// <param name="paniniDistance">Distance used for Panini projection</param>
        /// <param name="paniniCropToFit">CropToFit parameter used for Panini projection</param>
        /// <param name="cmd">Command Buffer</param>
        /// <param name="colorBuffer">Source Render Target which contains the Color Buffer</param>
        /// <param name="GetLensFlareLightAttenuation">Delegate to which return return the Attenuation of the light based on their shape which uses the functions ShapeAttenuation...(...), must reimplemented per SRP</param>
        /// <param name="_FlareTex">ShaderID for the FlareTex</param>
        /// <param name="_FlareColorValue">ShaderID for the FlareColor</param>
        /// <param name="_FlareData0">ShaderID for the FlareData0</param>
        /// <param name="_FlareData1">ShaderID for the FlareData1</param>
        /// <param name="_FlareData2">ShaderID for the FlareData2</param>
        /// <param name="_FlareData3">ShaderID for the FlareData3</param>
        /// <param name="_FlareData4">ShaderID for the FlareData4</param>
        /// <param name="_FlareData5">ShaderID for the FlareData5</param>
        /// <param name="debugView">Debug View which setup black background to see only Lens Flare</param>
        static public void DoLensFlareDataDrivenCommon(Material lensFlareShader, LensFlareCommonSRP lensFlares, Camera cam, float actualWidth, float actualHeight,
                                                       bool usePanini, float paniniDistance, float paniniCropToFit,
                                                       Rendering.CommandBuffer cmd,
                                                       Rendering.RenderTargetIdentifier colorBuffer,
                                                       System.Func <Light, Camera, Vector3, float> GetLensFlareLightAttenuation,
                                                       int _FlareTex, int _FlareColorValue, int _FlareData0, int _FlareData1, int _FlareData2, int _FlareData3, int _FlareData4, int _FlareData5, bool debugView)
        {
            Vector2 vScreenRatio;

            if (lensFlares.IsEmpty())
            {
                return;
            }

            Vector2 screenSize  = new Vector2(actualWidth, actualHeight);
            float   screenRatio = screenSize.x / screenSize.y;

            vScreenRatio = new Vector2(screenRatio, 1.0f);

            Rendering.CoreUtils.SetRenderTarget(cmd, colorBuffer);
            if (debugView)
            {
                // Background pitch black to see only the Flares
                cmd.ClearRenderTarget(false, true, Color.black);
            }

            foreach (LensFlareComponentSRP comp in lensFlares.GetData())
            {
                if (comp == null)
                {
                    continue;
                }

                LensFlareDataSRP data = comp.lensFlareData;

                if (!comp.enabled ||
                    !comp.gameObject.activeSelf ||
                    !comp.gameObject.activeInHierarchy ||
                    data == null ||
                    data.elements == null ||
                    data.elements.Length == 0)
                {
                    continue;
                }

                Light light = comp.GetComponent <Light>();

                Vector3 positionWS;
                Vector3 viewportPos;

                bool isDirLight = false;
                if (light != null && light.type == LightType.Directional)
                {
                    positionWS = -light.transform.forward * cam.farClipPlane;
                    isDirLight = true;
                }
                else
                {
                    positionWS = comp.transform.position;
                }
                viewportPos = cam.WorldToViewportPoint(positionWS);
                if (usePanini && cam == Camera.main)
                {
                    viewportPos = DoPaniniProjection(viewportPos, actualWidth, actualHeight, cam.fieldOfView, paniniCropToFit, paniniDistance);
                }

                if (viewportPos.z < 0.0f)
                {
                    continue;
                }

                if (!comp.allowOffScreen)
                {
                    if (viewportPos.x < 0.0f || viewportPos.x > 1.0f ||
                        viewportPos.y < 0.0f || viewportPos.y > 1.0f)
                    {
                        continue;
                    }
                }

                Vector4 modulationByColor     = Vector4.one;
                Vector4 modulationAttenuation = Vector4.one;
                Vector3 diffToObject          = positionWS - cam.transform.position;
                float   distToObject          = diffToObject.magnitude;
                float   coefDistSample        = distToObject / comp.maxAttenuationDistance;
                float   coefScaleSample       = distToObject / comp.maxAttenuationScale;
                float   distanceAttenuation   = !isDirLight && comp.distanceAttenuationCurve.length > 0 ? comp.distanceAttenuationCurve.Evaluate(coefDistSample) : 1.0f;
                float   scaleByDistance       = !isDirLight && comp.scaleByDistanceCurve.length >= 1 ? comp.scaleByDistanceCurve.Evaluate(coefScaleSample) : 1.0f;

                Color globalColorModulation = Color.white;

                if (light != null)
                {
                    if (comp.attenuationByLightShape)
                    {
                        globalColorModulation *= GetLensFlareLightAttenuation(light, cam, -diffToObject.normalized);
                    }
                }

                globalColorModulation *= distanceAttenuation;

                Vector3 dir        = (cam.transform.position - comp.transform.position).normalized;
                Vector3 screenPosZ = cam.WorldToViewportPoint(positionWS + dir * comp.occlusionOffset);
                Vector2 occlusionRadiusEdgeScreenPos0 = (Vector2)cam.WorldToViewportPoint(positionWS);
                Vector2 occlusionRadiusEdgeScreenPos1 = (Vector2)cam.WorldToViewportPoint(positionWS + cam.transform.up * comp.occlusionRadius);
                float   occlusionRadius = (occlusionRadiusEdgeScreenPos1 - occlusionRadiusEdgeScreenPos0).magnitude;
                cmd.SetGlobalVector(_FlareData1, new Vector4(occlusionRadius, comp.sampleCount, screenPosZ.z, actualHeight / actualWidth));

                if (comp.useOcclusion)
                {
                    cmd.EnableShaderKeyword("FLARE_OCCLUSION");
                }
                else
                {
                    cmd.DisableShaderKeyword("FLARE_OCCLUSION");
                }

                foreach (LensFlareDataElementSRP element in data.elements)
                {
                    if (element == null ||
                        (element.lensFlareTexture == null && element.flareType == SRPLensFlareType.Image) ||
                        element.localIntensity <= 0.0f ||
                        element.count <= 0)
                    {
                        continue;
                    }

                    Color colorModulation = globalColorModulation;
                    if (light != null && element.modulateByLightColor)
                    {
                        if (light.useColorTemperature)
                        {
                            colorModulation *= light.color * Mathf.CorrelatedColorTemperatureToRGB(light.colorTemperature);
                        }
                        else
                        {
                            colorModulation *= light.color;
                        }
                    }

                    Color   curColor         = colorModulation;
                    Vector2 screenPos        = new Vector2(2.0f * viewportPos.x - 1.0f, 1.0f - 2.0f * viewportPos.y);
                    Vector2 translationScale = new Vector2(element.translationScale.x, element.translationScale.y);
                    Texture texture          = element.lensFlareTexture;
                    float   elemAspectRatio  = element.sizeXY.x / element.sizeXY.y;
                    float   usedAspectRatio;
                    if (element.flareType == SRPLensFlareType.Image)
                    {
                        usedAspectRatio = element.preserveAspectRatio ? ((((float)texture.height) / (float)texture.width)) : 1.0f;
                    }
                    else
                    {
                        usedAspectRatio = 1.0f;
                    }

                    float   rotation           = element.rotation;
                    Vector4 tint               = Vector4.Scale(element.tint, curColor);
                    Vector2 radPos             = new Vector2(Mathf.Abs(screenPos.x), Mathf.Abs(screenPos.y));
                    float   radius             = Mathf.Max(radPos.x, radPos.y); // l1 norm (instead of l2 norm)
                    float   radialsScaleRadius = comp.radialScreenAttenuationCurve.length > 0 ? comp.radialScreenAttenuationCurve.Evaluate(radius) : 1.0f;

                    Vector2 elemSizeXY;
                    if (element.preserveAspectRatio)
                    {
                        if (usedAspectRatio >= 1.0f)
                        {
                            elemSizeXY = new Vector2(element.sizeXY.x / usedAspectRatio, element.sizeXY.y);
                        }
                        else
                        {
                            elemSizeXY = new Vector2(element.sizeXY.x, element.sizeXY.y * usedAspectRatio);
                        }
                    }
                    else
                    {
                        elemSizeXY = new Vector2(element.sizeXY.x, element.sizeXY.y);
                    }
                    float   scaleSize     = 0.1f; // Arbitrary value
                    Vector2 size          = new Vector2(elemSizeXY.x, elemSizeXY.y);
                    float   combinedScale = scaleByDistance * scaleSize * element.uniformScale * comp.scale;
                    size *= combinedScale;

                    Vector4 gradientModulation = new Vector4(1.0f, 1.0f, 1.0f, 1.0f);

                    float currentIntensity = comp.intensity * element.localIntensity * radialsScaleRadius * distanceAttenuation;

                    if (currentIntensity <= 0.0f)
                    {
                        continue;
                    }

                    curColor *= element.tint;
                    curColor *= currentIntensity;

                    float globalCos0 = Mathf.Cos(-element.angularOffset * Mathf.Deg2Rad);
                    float globalSin0 = Mathf.Sin(-element.angularOffset * Mathf.Deg2Rad);

                    float position = 2.0f * element.position;

                    SRPLensFlareBlendMode blendMode = element.blendMode;
                    int materialPass;
                    if (blendMode == SRPLensFlareBlendMode.Additive)
                    {
                        materialPass = 0;
                    }
                    else if (blendMode == SRPLensFlareBlendMode.Screen)
                    {
                        materialPass = 1;
                    }
                    else if (blendMode == SRPLensFlareBlendMode.Premultiply)
                    {
                        materialPass = 2;
                    }
                    else if (blendMode == SRPLensFlareBlendMode.Lerp)
                    {
                        materialPass = 3;
                    }
                    else
                    {
                        materialPass = 0;
                    }

                    if (element.flareType == SRPLensFlareType.Image)
                    {
                        cmd.DisableShaderKeyword("FLARE_CIRCLE");
                        cmd.DisableShaderKeyword("FLARE_POLYGON");
                    }
                    else if (element.flareType == SRPLensFlareType.Circle)
                    {
                        cmd.EnableShaderKeyword("FLARE_CIRCLE");
                        cmd.DisableShaderKeyword("FLARE_POLYGON");
                    }
                    else if (element.flareType == SRPLensFlareType.Polygon)
                    {
                        cmd.DisableShaderKeyword("FLARE_CIRCLE");
                        cmd.EnableShaderKeyword("FLARE_POLYGON");
                    }

                    if (element.flareType == SRPLensFlareType.Circle ||
                        element.flareType == SRPLensFlareType.Polygon)
                    {
                        if (element.inverseSDF)
                        {
                            cmd.EnableShaderKeyword("FLARE_INVERSE_SDF");
                        }
                        else
                        {
                            cmd.DisableShaderKeyword("FLARE_INVERSE_SDF");
                        }
                    }
                    else
                    {
                        cmd.DisableShaderKeyword("FLARE_INVERSE_SDF");
                    }

                    if (element.lensFlareTexture != null)
                    {
                        cmd.SetGlobalTexture(_FlareTex, element.lensFlareTexture);
                    }

                    float usedGradientPosition = Mathf.Clamp01((1.0f - element.edgeOffset) - 1e-6f);
                    if (element.flareType == SRPLensFlareType.Polygon)
                    {
                        usedGradientPosition = Mathf.Pow(usedGradientPosition + 1.0f, 5);
                    }

                    Vector2 ComputeLocalSize(Vector2 rayOff, Vector2 rayOff0, Vector2 curSize, AnimationCurve distortionCurve)
                    {
                        Vector2 rayOffZ = GetLensFlareRayOffset(screenPos, position, globalCos0, globalSin0);
                        Vector2 localRadPos;
                        float   localRadius;

                        if (!element.distortionRelativeToCenter)
                        {
                            localRadPos = (rayOff - rayOff0) * 0.5f;
                            localRadius = Mathf.Clamp01(Mathf.Max(Mathf.Abs(localRadPos.x), Mathf.Abs(localRadPos.y))); // l1 norm (instead of l2 norm)
                        }
                        else
                        {
                            localRadPos = screenPos + (rayOff + new Vector2(element.positionOffset.x, -element.positionOffset.y)) * element.translationScale;
                            localRadius = Mathf.Clamp01(localRadPos.magnitude); // l2 norm (instead of l1 norm)
                        }

                        float localLerpValue = Mathf.Clamp01(distortionCurve.Evaluate(localRadius));

                        return(new Vector2(Mathf.Lerp(curSize.x, element.targetSizeDistortion.x * combinedScale / usedAspectRatio, localLerpValue),
                                           Mathf.Lerp(curSize.y, element.targetSizeDistortion.y * combinedScale, localLerpValue)));
                    }

                    float usedSDFRoundness = element.sdfRoundness;

                    cmd.SetGlobalVector(_FlareData5, new Vector4(comp.allowOffScreen ? 1.0f : -1.0f, usedGradientPosition, Mathf.Exp(Mathf.Lerp(0.0f, 4.0f, Mathf.Clamp01(1.0f - element.fallOff))), 0.0f));
                    if (element.flareType == SRPLensFlareType.Polygon)
                    {
                        float invSide    = 1.0f / (float)element.sideCount;
                        float rCos       = Mathf.Cos(Mathf.PI * invSide);
                        float roundValue = rCos * usedSDFRoundness;
                        float r          = rCos - roundValue;
                        float an         = 2.0f * Mathf.PI * invSide;
                        float he         = r * Mathf.Tan(0.5f * an);
                        cmd.SetGlobalVector(_FlareData4, new Vector4(usedSDFRoundness, r, an, he));
                    }
                    else
                    {
                        cmd.SetGlobalVector(_FlareData4, new Vector4(usedSDFRoundness, 0.0f, 0.0f, 0.0f));
                    }

                    if (!element.allowMultipleElement || element.count == 1)
                    {
                        Vector4 flareData0 = GetFlareData0(screenPos, element.translationScale, vScreenRatio, element.rotation, position, element.angularOffset, element.positionOffset, element.autoRotate);

                        Vector2 rayOff    = GetLensFlareRayOffset(screenPos, position, globalCos0, globalSin0);
                        Vector2 localSize = size;

                        if (element.enableRadialDistortion)
                        {
                            Vector2 rayOff0 = GetLensFlareRayOffset(screenPos, 0.0f, globalCos0, globalSin0);
                            localSize = ComputeLocalSize(rayOff, rayOff0, localSize, element.distortionCurve);
                        }

                        cmd.SetGlobalVector(_FlareData0, flareData0);
                        cmd.SetGlobalVector(_FlareData2, new Vector4(screenPos.x, screenPos.y, localSize.x, localSize.y));
                        cmd.SetGlobalVector(_FlareData3, new Vector4(rayOff.x * element.translationScale.x, rayOff.y * element.translationScale.y, 1.0f / (float)element.sideCount, 0.0f));
                        cmd.SetGlobalVector(_FlareColorValue, curColor);

                        UnityEngine.Rendering.Blitter.DrawQuad(cmd, lensFlareShader, materialPass);
                    }
                    else
                    {
                        float dLength = 2.0f * element.lengthSpread / ((float)(element.count - 1));

                        if (element.distribution == SRPLensFlareDistribution.Uniform)
                        {
                            for (int elemIdx = 0; elemIdx < element.count; ++elemIdx)
                            {
                                Vector2 rayOff = GetLensFlareRayOffset(screenPos, position, globalCos0, globalSin0);

                                Vector2 localSize = size;
                                if (element.enableRadialDistortion)
                                {
                                    Vector2 rayOff0 = GetLensFlareRayOffset(screenPos, 0.0f, globalCos0, globalSin0);
                                    localSize = ComputeLocalSize(rayOff, rayOff0, localSize, element.distortionCurve);
                                }

                                float timeScale = element.count >= 2 ? ((float)elemIdx) / ((float)(element.count - 1)) : 0.5f;

                                Color col = element.colorGradient.Evaluate(timeScale);

                                Vector4 flareData0 = GetFlareData0(screenPos, element.translationScale, vScreenRatio, element.rotation, position, element.angularOffset, element.positionOffset, element.autoRotate);
                                cmd.SetGlobalVector(_FlareData0, flareData0);
                                cmd.SetGlobalVector(_FlareData2, new Vector4(screenPos.x, screenPos.y, localSize.x, localSize.y));
                                cmd.SetGlobalVector(_FlareData3, new Vector4(rayOff.x * element.translationScale.x, rayOff.y * element.translationScale.y, 1.0f / (float)element.sideCount, 0.0f));
                                cmd.SetGlobalVector(_FlareColorValue, curColor * col);

                                UnityEngine.Rendering.Blitter.DrawQuad(cmd, lensFlareShader, materialPass);
                                position += dLength;
                            }
                        }
                        else if (element.distribution == SRPLensFlareDistribution.Random)
                        {
                            Random.State backupRandState = UnityEngine.Random.state;
                            Random.InitState(element.seed);
                            Vector2 side = new Vector2(Mathf.Sin(-element.angularOffset * Mathf.Deg2Rad), Mathf.Cos(-element.angularOffset * Mathf.Deg2Rad));
                            side *= element.positionVariation.y;
                            float RandomRange(float min, float max)
                            {
                                return(Random.Range(min, max));
                            }

                            for (int elemIdx = 0; elemIdx < element.count; ++elemIdx)
                            {
                                float localIntensity = RandomRange(-1.0f, 1.0f) * element.intensityVariation + 1.0f;

                                Vector2 rayOff    = GetLensFlareRayOffset(screenPos, position, globalCos0, globalSin0);
                                Vector2 localSize = size;
                                if (element.enableRadialDistortion)
                                {
                                    Vector2 rayOff0 = GetLensFlareRayOffset(screenPos, 0.0f, globalCos0, globalSin0);
                                    localSize = ComputeLocalSize(rayOff, rayOff0, localSize, element.distortionCurve);
                                }

                                localSize += localSize * (element.scaleVariation * RandomRange(-1.0f, 1.0f));

                                Color randCol = element.colorGradient.Evaluate(RandomRange(0.0f, 1.0f));

                                Vector2 localPositionOffset = element.positionOffset + RandomRange(-1.0f, 1.0f) * side;

                                float localRotation = element.rotation + RandomRange(-Mathf.PI, Mathf.PI) * element.rotationVariation;

                                if (localIntensity > 0.0f)
                                {
                                    Vector4 flareData0 = GetFlareData0(screenPos, element.translationScale, vScreenRatio, localRotation, position, element.angularOffset, localPositionOffset, element.autoRotate);
                                    cmd.SetGlobalVector(_FlareData0, flareData0);
                                    cmd.SetGlobalVector(_FlareData2, new Vector4(screenPos.x, screenPos.y, localSize.x, localSize.y));
                                    cmd.SetGlobalVector(_FlareData3, new Vector4(rayOff.x * element.translationScale.x, rayOff.y * element.translationScale.y, 1.0f / (float)element.sideCount, 0.0f));
                                    cmd.SetGlobalVector(_FlareColorValue, curColor * randCol * localIntensity);

                                    UnityEngine.Rendering.Blitter.DrawQuad(cmd, lensFlareShader, materialPass);
                                }

                                position += dLength;
                                position += 0.5f * dLength * RandomRange(-1.0f, 1.0f) * element.positionVariation.x;
                            }
                            Random.state = backupRandState;
                        }
                        else if (element.distribution == SRPLensFlareDistribution.Curve)
                        {
                            for (int elemIdx = 0; elemIdx < element.count; ++elemIdx)
                            {
                                float timeScale = element.count >= 2 ? ((float)elemIdx) / ((float)(element.count - 1)) : 0.5f;

                                Color col = element.colorGradient.Evaluate(timeScale);

                                float positionSpacing = element.positionCurve.length > 0 ? element.positionCurve.Evaluate(timeScale) : 1.0f;

                                float   localPos  = position + 2.0f * element.lengthSpread * positionSpacing;
                                Vector2 rayOff    = GetLensFlareRayOffset(screenPos, localPos, globalCos0, globalSin0);
                                Vector2 localSize = size;
                                if (element.enableRadialDistortion)
                                {
                                    Vector2 rayOff0 = GetLensFlareRayOffset(screenPos, 0.0f, globalCos0, globalSin0);
                                    localSize = ComputeLocalSize(rayOff, rayOff0, localSize, element.distortionCurve);
                                }
                                float sizeCurveValue = element.scaleCurve.length > 0 ? element.scaleCurve.Evaluate(timeScale) : 1.0f;
                                localSize *= sizeCurveValue;

                                Vector4 flareData0 = GetFlareData0(screenPos, element.translationScale, vScreenRatio, element.rotation, localPos, element.angularOffset, element.positionOffset, element.autoRotate);
                                cmd.SetGlobalVector(_FlareData0, flareData0);
                                cmd.SetGlobalVector(_FlareData2, new Vector4(screenPos.x, screenPos.y, localSize.x, localSize.y));
                                cmd.SetGlobalVector(_FlareData3, new Vector4(rayOff.x * element.translationScale.x, rayOff.y * element.translationScale.y, 1.0f / (float)element.sideCount, 0.0f));
                                cmd.SetGlobalVector(_FlareColorValue, curColor * col);

                                UnityEngine.Rendering.Blitter.DrawQuad(cmd, lensFlareShader, materialPass);
                            }
                        }
                    }
                }
            }
        }
 extern private void SetRenderTargetMulti_Internal(RenderTargetIdentifier[] colors, Rendering.RenderTargetIdentifier depth,
                                                   RenderBufferLoadAction[] colorLoadActions, RenderBufferStoreAction[] colorStoreActions,
                                                   RenderBufferLoadAction depthLoadAction, RenderBufferStoreAction depthStoreAction);
Example #6
0
 extern private void SetRenderTargetMultiSubtarget(RenderTargetIdentifier[] colors, Rendering.RenderTargetIdentifier depth,
                                                   RenderBufferLoadAction[] colorLoadActions, RenderBufferStoreAction[] colorStoreActions,
                                                   RenderBufferLoadAction depthLoadAction, RenderBufferStoreAction depthStoreAction,
                                                   int mipLevel, CubemapFace cubemapFace, int depthSlice);