Beispiel #1
0
        static Matrix4x4 ExtractSpotLightMatrix(VisibleLight vl, float nearPlane, float guardAngle, float aspectRatio, out Matrix4x4 view, out Matrix4x4 proj, out Matrix4x4 deviceProj, out Matrix4x4 vpinverse, out Vector4 lightDir, out ShadowSplitData splitData)
        {
            splitData = new ShadowSplitData();
            splitData.cullingSphere.Set(0.0f, 0.0f, 0.0f, float.NegativeInfinity);
            splitData.cullingPlaneCount = 0;
            // get lightDir
            lightDir = vl.light.transform.forward;
            // calculate view
            Matrix4x4 scaleMatrix = Matrix4x4.identity;

            scaleMatrix.m22 = -1.0f;
            view            = scaleMatrix * vl.localToWorld.inverse;
            // calculate projection
            float fov   = vl.spotAngle + guardAngle;
            float nearZ = Mathf.Max(nearPlane, k_MinShadowNearPlane);

            proj = Matrix4x4.Perspective(fov, aspectRatio, nearZ, vl.range);
            // and the compound (deviceProj will potentially inverse-Z)
            deviceProj = GL.GetGPUProjectionMatrix(proj, false);
            InvertPerspective(ref deviceProj, ref view, out vpinverse);
            return(deviceProj * view);
        }
        public static Matrix4x4 ExtractDirectionalLightMatrix(VisibleLight vl, uint cascadeIdx, int cascadeCount, float[] splitRatio, float nearPlaneOffset, uint width, uint height, out Matrix4x4 view, out Matrix4x4 proj, out Matrix4x4 deviceProj, out Matrix4x4 vpinverse, out Vector4 lightDir, out ShadowSplitData splitData, CullResults cullResults, int lightIndex)
        {
            Debug.Assert(width == height, "Currently the cascaded shadow mapping code requires square cascades.");
            splitData = new ShadowSplitData();
            splitData.cullingSphere.Set(0.0f, 0.0f, 0.0f, float.NegativeInfinity);
            splitData.cullingPlaneCount = 0;
            // get lightDir
            lightDir = vl.light.transform.forward;
            // TODO: At some point this logic should be moved to C#, then the parameters cullResults and lightIndex can be removed as well
            //       For directional lights shadow data is extracted from the cullResults, so that needs to be somehow provided here.
            //       Check ScriptableShadowsUtility.cpp ComputeDirectionalShadowMatricesAndCullingPrimitives(...) for details.
            Vector3 ratios = new Vector3();

            for (int i = 0, cnt = splitRatio.Length < 3 ? splitRatio.Length : 3; i < cnt; i++)
            {
                ratios[i] = splitRatio[i];
            }
            cullResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(lightIndex, (int)cascadeIdx, cascadeCount, ratios, (int)width, nearPlaneOffset, out view, out proj, out splitData);
            // and the compound (deviceProj will potentially inverse-Z)
            deviceProj = GL.GetGPUProjectionMatrix(proj, false);
            InvertOrthographic(ref deviceProj, ref view, out vpinverse);
            return(deviceProj * view);
        }
Beispiel #3
0
 // Currently area light shadows are not supported
 public static void ExtractAreaLightData(VisibleLight visibleLight, LightTypeExtent lightTypeExtent, out Matrix4x4 view, out Matrix4x4 invViewProjection, out Matrix4x4 projection, out Matrix4x4 deviceProjection, out ShadowSplitData splitData)
 {
     view = Matrix4x4.identity;
     invViewProjection = Matrix4x4.identity;
     deviceProjection  = Matrix4x4.identity;
     projection        = Matrix4x4.identity;
     splitData         = default(ShadowSplitData);
 }
        public static Matrix4x4 ExtractSpotLightMatrix(VisibleLight vl, float guardAngle, out Matrix4x4 view, out Matrix4x4 proj, out Matrix4x4 deviceProj, out Matrix4x4 vpinverse, out Vector4 lightDir, out ShadowSplitData splitData)
        {
            splitData = new ShadowSplitData();
            splitData.cullingSphere.Set(0.0f, 0.0f, 0.0f, float.NegativeInfinity);
            splitData.cullingPlaneCount = 0;
            // get lightDir
            lightDir = vl.light.transform.forward;
            // calculate view
            Matrix4x4 scaleMatrix = Matrix4x4.identity;

            scaleMatrix.m22 = -1.0f;
            view            = scaleMatrix * vl.localToWorld.inverse;
            // following code is from SharedLightData::GetNearPlaneMinBound
            float percentageBound = 0.01f * vl.light.range;
            float fixedBound      = 0.1f;
            float nearmin         = fixedBound <= percentageBound ? fixedBound : percentageBound;
            // calculate projection
            float zfar  = vl.range;
            float znear = vl.light.shadowNearPlane >= nearmin ? vl.light.shadowNearPlane : nearmin;
            float fov   = vl.spotAngle + guardAngle;

            proj = Matrix4x4.Perspective(fov, 1.0f, znear, zfar);
            // and the compound (deviceProj will potentially inverse-Z)
            deviceProj = GL.GetGPUProjectionMatrix(proj, false);
            InvertPerspective(ref deviceProj, ref view, out vpinverse);
            return(deviceProj * view);
        }
        public static Matrix4x4 ExtractPointLightMatrix(VisibleLight vl, uint faceIdx, float guardAngle, out Matrix4x4 view, out Matrix4x4 proj, out Matrix4x4 deviceProj, out Matrix4x4 vpinverse, out Vector4 lightDir, out ShadowSplitData splitData)
        {
            if (faceIdx > (uint)CubemapFace.NegativeZ)
            {
                Debug.LogError("Tried to extract cubemap face " + faceIdx + ".");
            }

            splitData = new ShadowSplitData();
            splitData.cullingSphere.Set(0.0f, 0.0f, 0.0f, float.NegativeInfinity);
            splitData.cullingPlaneCount = 4;
            // get lightDir
            lightDir = vl.light.transform.forward;
            // calculate the view matrices
            Vector3 lpos = vl.light.transform.position;

            view = ShadowUtilsConstants.kCubemapFaces[faceIdx];
            Vector3 inverted_viewpos = ShadowUtilsConstants.kCubemapFaces[faceIdx].MultiplyPoint(-lpos);

            view.SetColumn(3, new Vector4(inverted_viewpos.x, inverted_viewpos.y, inverted_viewpos.z, 1.0f));

            for (int i = 0; i < 4; ++i)
            {
                ShadowUtilsConstants.CubemapEdge cubemapEdge = ShadowUtilsConstants.kCubemapEdgesPerFace[faceIdx, i];
                Vector3 cullingPlaneDirection = ShadowUtilsConstants.kCubemapEdgeDirections[(int)cubemapEdge];
                splitData.SetCullingPlane(i, new Plane(cullingPlaneDirection, lpos));
            }
            // following code is from SharedLightData::GetNearPlaneMinBound
            float percentageBound = 0.01f * vl.light.range;
            float fixedBound      = 0.1f;
            float nearmin         = fixedBound <= percentageBound ? fixedBound : percentageBound;
            // calculate projection
            float farPlane  = vl.range;
            float nearPlane = vl.light.shadowNearPlane >= nearmin ? vl.light.shadowNearPlane : nearmin;

            proj = Matrix4x4.Perspective(90.0f + guardAngle, 1.0f, nearPlane, farPlane);
            // and the compound (deviceProj will potentially inverse-Z)
            deviceProj = GL.GetGPUProjectionMatrix(proj, false);
            InvertPerspective(ref deviceProj, ref view, out vpinverse);
            return(deviceProj * view);
        }
Beispiel #6
0
        // TODO: box spot and pyramid spots with non 1 aspect ratios shadow are incorrectly culled, see when scriptable culling will be here
        public static void ExtractSpotLightData(HDCamera camera, LightType lightType, SpotLightShape shape, float nearPlane, float aspectRatio, float shapeWidth, float shapeHeight, VisibleLight visibleLight, Vector2 viewportSize, float normalBiasMax, out Matrix4x4 view, out Matrix4x4 invViewProjection, out Matrix4x4 projection, out Matrix4x4 deviceProjection, out ShadowSplitData splitData)
        {
            Vector4 lightDir;

            // There is no aspect ratio for non pyramid spot lights
            if (shape != SpotLightShape.Pyramid)
            {
                aspectRatio = 1.0f;
            }

            float guardAngle = CalcGuardAnglePerspective(visibleLight.light.spotAngle, viewportSize.x, GetPunctualFilterWidthInTexels(camera, lightType), normalBiasMax, 180.0f - visibleLight.light.spotAngle);

            ExtractSpotLightMatrix(visibleLight, nearPlane, guardAngle, aspectRatio, out view, out projection, out deviceProjection, out invViewProjection, out lightDir, out splitData);

            if (shape == SpotLightShape.Box)
            {
                float nearZ = Mathf.Max(nearPlane, k_MinShadowNearPlane);
                projection       = Matrix4x4.Ortho(-shapeWidth / 2, shapeWidth / 2, -shapeHeight / 2, shapeHeight / 2, nearZ, visibleLight.range);
                deviceProjection = GL.GetGPUProjectionMatrix(projection, false);
                InvertOrthographic(ref projection, ref view, out invViewProjection);
            }
        }
Beispiel #7
0
        public static void ExtractDirectionalLightData(VisibleLight visibleLight, Vector2 viewportSize, uint cascadeIndex, int cascadeCount, float[] cascadeRatios, float nearPlaneOffset, CullingResults cullResults, int lightIndex, out Matrix4x4 view, out Matrix4x4 invViewProjection, out Matrix4x4 projection, out Matrix4x4 deviceProjection, out ShadowSplitData splitData)
        {
            Vector4 lightDir;

            Debug.Assert((uint)viewportSize.x == (uint)viewportSize.y, "Currently the cascaded shadow mapping code requires square cascades.");
            splitData = new ShadowSplitData();
            splitData.cullingSphere.Set(0.0f, 0.0f, 0.0f, float.NegativeInfinity);
            splitData.cullingPlaneCount = 0;
            // get lightDir
            lightDir = visibleLight.light.transform.forward;
            // TODO: At some point this logic should be moved to C#, then the parameters cullResults and lightIndex can be removed as well
            //       For directional lights shadow data is extracted from the cullResults, so that needs to be somehow provided here.
            //       Check ScriptableShadowsUtility.cpp ComputeDirectionalShadowMatricesAndCullingPrimitives(...) for details.
            Vector3 ratios = new Vector3();

            for (int i = 0, cnt = cascadeRatios.Length < 3 ? cascadeRatios.Length : 3; i < cnt; i++)
            {
                ratios[i] = cascadeRatios[i];
            }
            cullResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(lightIndex, (int)cascadeIndex, cascadeCount, ratios, (int)viewportSize.x, nearPlaneOffset, out view, out projection, out splitData);
            // and the compound (deviceProjection will potentially inverse-Z)
            deviceProjection = GL.GetGPUProjectionMatrix(projection, false);
            InvertOrthographic(ref deviceProjection, ref view, out invViewProjection);
        }
Beispiel #8
0
        static Matrix4x4 ExtractPointLightMatrix(VisibleLight vl, uint faceIdx, float nearPlane, float guardAngle, out Matrix4x4 view, out Matrix4x4 proj, out Matrix4x4 deviceProj, out Matrix4x4 vpinverse, out Vector4 lightDir, out ShadowSplitData splitData)
        {
            if (faceIdx > (uint)CubemapFace.NegativeZ)
            {
                Debug.LogError("Tried to extract cubemap face " + faceIdx + ".");
            }

            splitData = new ShadowSplitData();
            splitData.cullingSphere.Set(0.0f, 0.0f, 0.0f, float.NegativeInfinity);
            splitData.cullingPlaneCount = 4;
            // get lightDir
            lightDir = vl.light.transform.forward;
            // calculate the view matrices
            Vector3 lpos = vl.light.transform.position;

            view = kCubemapFaces[faceIdx];
            Vector3 inverted_viewpos = kCubemapFaces[faceIdx].MultiplyPoint(-lpos);

            view.SetColumn(3, new Vector4(inverted_viewpos.x, inverted_viewpos.y, inverted_viewpos.z, 1.0f));

            for (int i = 0; i < 4; ++i)
            {
                CubemapEdge cubemapEdge           = kCubemapEdgesPerFace[faceIdx, i];
                Vector3     cullingPlaneDirection = kCubemapEdgeDirections[(int)cubemapEdge];
                splitData.SetCullingPlane(i, new Plane(cullingPlaneDirection, lpos));
            }

            float nearZ = Mathf.Max(nearPlane, k_MinShadowNearPlane);

            proj = Matrix4x4.Perspective(90.0f + guardAngle, 1.0f, nearZ, vl.range);
            // and the compound (deviceProj will potentially inverse-Z)
            deviceProj = GL.GetGPUProjectionMatrix(proj, false);
            InvertPerspective(ref deviceProj, ref view, out vpinverse);
            return(deviceProj * view);
        }
Beispiel #9
0
        public static void ExtractPointLightData(HDCamera camera, LightType lightType, VisibleLight visibleLight, Vector2 viewportSize, float nearPlane, float normalBiasMax, uint faceIndex, out Matrix4x4 view, out Matrix4x4 invViewProjection, out Matrix4x4 projection, out Matrix4x4 deviceProjection, out ShadowSplitData splitData)
        {
            Vector4 lightDir;

            float guardAngle = CalcGuardAnglePerspective(90.0f, viewportSize.x, GetPunctualFilterWidthInTexels(camera, lightType), normalBiasMax, 79.0f);

            ExtractPointLightMatrix(visibleLight, faceIndex, nearPlane, guardAngle, out view, out projection, out deviceProjection, out invViewProjection, out lightDir, out splitData);
        }
        // Currently area light shadows are not supported
        public static void ExtractAreaLightData(HDCamera camera, VisibleLight visibleLight, LightTypeExtent lightTypeExtent, Vector3 shadowPosition, float areaLightShadowCone, float shadowNearPlane, Vector2 shapeSize, Vector2 viewportSize, float normalBiasMax, out Matrix4x4 view, out Matrix4x4 invViewProjection, out Matrix4x4 projection, out Matrix4x4 deviceProjection, out ShadowSplitData splitData)
        {
            if (lightTypeExtent != LightTypeExtent.Rectangle)
            {
                view = Matrix4x4.identity;
                invViewProjection = Matrix4x4.identity;
                deviceProjection  = Matrix4x4.identity;
                projection        = Matrix4x4.identity;
                splitData         = default(ShadowSplitData);
            }
            else
            {
                Vector4 lightDir;
                float   aspectRatio = shapeSize.x / shapeSize.y;
                float   spotAngle   = areaLightShadowCone;
                visibleLight.spotAngle = spotAngle;
                float guardAngle = CalcGuardAnglePerspective(visibleLight.spotAngle, viewportSize.x, GetPunctualFilterWidthInTexels(camera, LightType.Rectangle), normalBiasMax, 180.0f - visibleLight.spotAngle);

                ExtractSpotLightMatrix(visibleLight, shadowNearPlane, guardAngle, aspectRatio, out view, out projection, out deviceProjection, out invViewProjection, out lightDir, out splitData);
            }
        }
Beispiel #11
0
 public static Matrix4x4 ExtractDirectionalLightMatrix(VisibleLight vl, uint cascadeIdx, int cascadeCount, Vector3 splitRatio, float nearPlaneOffset, uint width, uint height, out Matrix4x4 view, out Matrix4x4 proj, out Vector4 lightDir, out ShadowSplitData splitData, CullResults cullResults, int lightIndex)
 {
     Debug.Assert(width == height, "Currently the cascaded shadow mapping code requires square cascades.");
     splitData = new ShadowSplitData();
     splitData.cullingSphere.Set(0.0f, 0.0f, 0.0f, float.NegativeInfinity);
     splitData.cullingPlaneCount = 0;
     // get lightDir
     lightDir = vl.light.transform.forward;
     // TODO: At some point this logic should be moved to C#, then the parameters cullResults and lightIndex can be removed as well
     //       For directional lights shadow data is extracted from the cullResults, so that needs to be somehow provided here.
     //       Check ScriptableShadowsUtility.cpp ComputeDirectionalShadowMatricesAndCullingPrimitives(...) for details.
     cullResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(lightIndex, (int)cascadeIdx, cascadeCount, splitRatio, (int)width, nearPlaneOffset, out view, out proj, out splitData);
     // and the compound
     return(proj * view);
 }
Beispiel #12
0
        public static Matrix4x4 ExtractPointLightMatrix(VisibleLight vl, uint faceIdx, float fovBias, out Matrix4x4 view, out Matrix4x4 proj, out Vector4 lightDir, out ShadowSplitData splitData, CullResults cullResults, int lightIndex)
        {
            Debug.Assert(faceIdx <= (uint)CubemapFace.NegativeZ, "Tried to extract cubemap face " + faceIdx + ".");

            splitData = new ShadowSplitData();
            splitData.cullingSphere.Set(0.0f, 0.0f, 0.0f, float.NegativeInfinity);
            splitData.cullingPlaneCount = 0;
            // get lightDir
            lightDir = vl.light.transform.forward;
            // TODO: At some point this logic should be moved to C#, then the parameters cullResults and lightIndex can be removed as well
            cullResults.ComputePointShadowMatricesAndCullingPrimitives(lightIndex, (CubemapFace)faceIdx, fovBias, out view, out proj, out splitData);
            // and the compound
            return(proj * view);
        }
Beispiel #13
0
        public static bool ExtractPointLightMatrix(ref CullingResults cullResults, ref ShadowData shadowData, int shadowLightIndex, CubemapFace cubemapFace, float fovBias, out Matrix4x4 shadowMatrix, out Matrix4x4 viewMatrix, out Matrix4x4 projMatrix, out ShadowSplitData splitData)
        {
            bool success = cullResults.ComputePointShadowMatricesAndCullingPrimitives(shadowLightIndex, cubemapFace, fovBias, out viewMatrix, out projMatrix, out splitData); // returns false if input parameters are incorrect (rare)

            // In native API CullingResults.ComputeSpotShadowMatricesAndCullingPrimitives there is code that inverts the 3rd component of shadow-casting spot light's "world-to-local" matrix (it was so since its original addition to the code base):
            // https://github.cds.internal.unity3d.com/unity/unity/commit/34813e063526c4be0ef0448dfaae3a911dd8be58#diff-cf0b417fc6bd8ee2356770797e628cd4R331
            // (the same transformation has also always been used in the Built-In Render Pipeline)
            //
            // However native API CullingResults.ComputePointShadowMatricesAndCullingPrimitives does not contain this transformation.
            // As a result, the view matrices returned for a point light shadow face, and for a spot light with same direction as that face, have opposite 3rd component.
            //
            // This causes normalBias to be incorrectly applied to shadow caster vertices during the point light shadow pass.
            // To counter this effect, we invert the point light shadow view matrix component here:
            {
                viewMatrix.m10 = -viewMatrix.m10;
                viewMatrix.m11 = -viewMatrix.m11;
                viewMatrix.m12 = -viewMatrix.m12;
                viewMatrix.m13 = -viewMatrix.m13;
            }

            shadowMatrix = GetShadowTransform(projMatrix, viewMatrix);
            return(success);
        }
Beispiel #14
0
        public static bool ExtractSpotLightMatrix(ref CullingResults cullResults, ref ShadowData shadowData, int shadowLightIndex, out Matrix4x4 shadowMatrix, out Matrix4x4 viewMatrix, out Matrix4x4 projMatrix, out ShadowSplitData splitData)
        {
            bool success = cullResults.ComputeSpotShadowMatricesAndCullingPrimitives(shadowLightIndex, out viewMatrix, out projMatrix, out splitData); // returns false if input parameters are incorrect (rare)

            shadowMatrix = GetShadowTransform(projMatrix, viewMatrix);
            return(success);
        }