Ejemplo n.º 1
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;

            // This used to be fixed to .6f, but is now configureable.
            splitData.shadowCascadeBlendCullingFactor = .6f;

            // get lightDir
            lightDir = visibleLight.GetForward();
            // 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);
            projection       = GL.GetGPUProjectionMatrix(projection, true);
            InvertOrthographic(ref deviceProjection, ref view, out invViewProjection);
        }
Ejemplo n.º 2
0
        static Matrix4x4 ExtractSpotLightMatrix(VisibleLight vl, float forwardOffset, float spotAngle, float nearPlane, float guardAngle, float aspectRatio, out Matrix4x4 view, out Matrix4x4 proj, out Matrix4x4 deviceProj, out Matrix4x4 deviceProjYFlip, 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;
            lightDir = vl.GetForward();

            // calculate view
            Matrix4x4 localToWorldOffset = vl.localToWorldMatrix;

            CoreMatrixUtils.MatrixTimesTranslation(ref localToWorldOffset, Vector3.forward * forwardOffset);
            view      = localToWorldOffset.inverse;
            view.m20 *= -1;
            view.m21 *= -1;
            view.m22 *= -1;
            view.m23 *= -1;

            // calculate projection
            proj = ExtractSpotLightProjectionMatrix(vl.range - forwardOffset, spotAngle, nearPlane - forwardOffset, aspectRatio, guardAngle);

            // and the compound (deviceProj will potentially inverse-Z)
            deviceProj      = GL.GetGPUProjectionMatrix(proj, false);
            deviceProjYFlip = GL.GetGPUProjectionMatrix(proj, true);
            InvertPerspective(ref deviceProj, ref view, out vpinverse);
            return(CoreMatrixUtils.MultiplyPerspectiveMatrix(deviceProj, view));
        }
Ejemplo n.º 3
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);

            // get lightDir
            lightDir = vl.GetForward();
            // calculate the view matrices
            Vector3 lpos = vl.GetPosition();

            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));

            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);
            proj       = GL.GetGPUProjectionMatrix(proj, true);
            InvertPerspective(ref deviceProj, ref view, out vpinverse);

            Matrix4x4 devProjView = CoreMatrixUtils.MultiplyPerspectiveMatrix(deviceProj, view);

            // We can avoid computing proj * view for frustum planes, if device has reversed Z we flip the culling planes as we should have computed them with proj
            GeometryUtility.CalculateFrustumPlanes(devProjView, s_CachedPlanes);
            if (SystemInfo.usesReversedZBuffer)
            {
                var tmpPlane = s_CachedPlanes[2];
                s_CachedPlanes[2] = s_CachedPlanes[3];
                s_CachedPlanes[3] = tmpPlane;
            }
            splitData.cullingPlaneCount = 6;
            for (int i = 0; i < 6; i++)
            {
                splitData.SetCullingPlane(i, s_CachedPlanes[i]);
            }

            return(devProjView);
        }
Ejemplo n.º 4
0
        static Matrix4x4 ExtractSpotLightMatrix(VisibleLight vl, float spotAngle, 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.GetForward();
            // calculate view
            Matrix4x4 scaleMatrix = Matrix4x4.identity;

            scaleMatrix.m22 = -1.0f;
            view            = scaleMatrix * vl.localToWorldMatrix.inverse;
            // calculate projection
            proj = ExtractSpotLightProjectionMatrix(vl.range, spotAngle, nearPlane, aspectRatio, guardAngle);
            // and the compound (deviceProj will potentially inverse-Z)
            deviceProj = GL.GetGPUProjectionMatrix(proj, false);
            proj       = GL.GetGPUProjectionMatrix(proj, true);
            InvertPerspective(ref deviceProj, ref view, out vpinverse);
            return(deviceProj * view);
        }
Ejemplo n.º 5
0
        // Must return the first executed shadow request
        public int UpdateShadowRequest(HDCamera hdCamera, HDShadowManager manager, VisibleLight visibleLight, CullingResults cullResults, int lightIndex, out int shadowRequestCount)
        {
            int     firstShadowRequestIndex = -1;
            Vector3 cameraPos = hdCamera.camera.transform.position;

            shadowRequestCount = 0;

            int count = GetShadowRequestCount();

            for (int index = 0; index < count; index++)
            {
                var       shadowRequest      = shadowRequests[index];
                Matrix4x4 invViewProjection  = Matrix4x4.identity;
                int       shadowRequestIndex = m_ShadowRequestIndices[index];
                Vector2   viewportSize       = manager.GetReservedResolution(shadowRequestIndex);

                if (shadowRequestIndex == -1)
                {
                    continue;
                }

                if (lightTypeExtent == LightTypeExtent.Rectangle)
                {
                    Vector2 shapeSize    = new Vector2(shapeWidth, shapeHeight);
                    float   offset       = GetAreaLightOffsetForShadows(shapeSize, areaLightShadowCone);
                    Vector3 shadowOffset = offset * visibleLight.GetForward();
                    HDShadowUtils.ExtractAreaLightData(hdCamera, visibleLight, lightTypeExtent, visibleLight.GetPosition() + shadowOffset, areaLightShadowCone, shadowNearPlane, shapeSize, viewportSize, m_ShadowData.normalBiasMax, out shadowRequest.view, out invViewProjection, out shadowRequest.deviceProjectionYFlip, out shadowRequest.deviceProjection, out shadowRequest.splitData);
                }
                else
                {
                    // Write per light type matrices, splitDatas and culling parameters
                    switch (legacyLight.type)
                    {
                    case LightType.Point:
                        HDShadowUtils.ExtractPointLightData(
                            hdCamera, legacyLight.type, visibleLight, viewportSize, shadowNearPlane,
                            m_ShadowData.normalBiasMax, (uint)index, out shadowRequest.view,
                            out invViewProjection, out shadowRequest.deviceProjectionYFlip,
                            out shadowRequest.deviceProjection, out shadowRequest.splitData
                            );
                        break;

                    case LightType.Spot:
                        HDShadowUtils.ExtractSpotLightData(
                            hdCamera, legacyLight.type, spotLightShape, shadowNearPlane, aspectRatio, shapeWidth,
                            shapeHeight, visibleLight, viewportSize, m_ShadowData.normalBiasMax,
                            out shadowRequest.view, out invViewProjection, out shadowRequest.deviceProjectionYFlip,
                            out shadowRequest.deviceProjection, out shadowRequest.splitData
                            );
                        break;

                    case LightType.Directional:
                        Vector4 cullingSphere;
                        float   nearPlaneOffset = QualitySettings.shadowNearPlaneOffset;

                        HDShadowUtils.ExtractDirectionalLightData(
                            visibleLight, viewportSize, (uint)index, m_ShadowSettings.cascadeShadowSplitCount.value,
                            m_ShadowSettings.cascadeShadowSplits, nearPlaneOffset, cullResults, lightIndex,
                            out shadowRequest.view, out invViewProjection, out shadowRequest.deviceProjectionYFlip,
                            out shadowRequest.deviceProjection, out shadowRequest.splitData
                            );

                        cullingSphere = shadowRequest.splitData.cullingSphere;

                        // Camera relative for directional light culling sphere
                        if (ShaderConfig.s_CameraRelativeRendering != 0)
                        {
                            cullingSphere.x -= cameraPos.x;
                            cullingSphere.y -= cameraPos.y;
                            cullingSphere.z -= cameraPos.z;
                        }
                        manager.UpdateCascade(index, cullingSphere, m_ShadowSettings.cascadeShadowBorders[index]);
                        break;
                    }
                }

                // Assign all setting common to every lights
                SetCommonShadowRequestSettings(shadowRequest, cameraPos, invViewProjection, shadowRequest.deviceProjectionYFlip * shadowRequest.view, viewportSize, lightIndex);

                manager.UpdateShadowRequest(shadowRequestIndex, shadowRequest);

                // Store the first shadow request id to return it
                if (firstShadowRequestIndex == -1)
                {
                    firstShadowRequestIndex = shadowRequestIndex;
                }

                shadowRequestCount++;
            }

            return(firstShadowRequestIndex);
        }