Ejemplo n.º 1
0
        private Matrix4x4 UpdateDirectionalLightMatrices(
            GraphicsDevice gd,
            SceneContext sc,
            float near,
            float far,
            uint shadowMapWidth,
            out BoundingFrustum lightFrustum)
        {
            Vector3        lightDir = sc.DirectionalLight.Direction;
            Vector3        viewDir  = sc.Camera.LookDirection;
            Vector3        viewPos  = sc.Camera.Position;
            Vector3        unitY    = Vector3.UnitY;
            FrustumCorners cameraCorners;

            if (gd.IsDepthRangeZeroToOne)
            {
                FrustumHelpers.ComputePerspectiveFrustumCorners(
                    ref viewPos,
                    ref viewDir,
                    ref unitY,
                    sc.Camera.FieldOfView,
                    far,
                    near,
                    sc.Camera.AspectRatio,
                    out cameraCorners);
            }
            else
            {
                FrustumHelpers.ComputePerspectiveFrustumCorners(
                    ref viewPos,
                    ref viewDir,
                    ref unitY,
                    sc.Camera.FieldOfView,
                    near,
                    far,
                    sc.Camera.AspectRatio,
                    out cameraCorners);
            }

            // Approach used: http://alextardif.com/ShadowMapping.html

            Vector3 frustumCenter = Vector3.Zero;

            frustumCenter += cameraCorners.NearTopLeft;
            frustumCenter += cameraCorners.NearTopRight;
            frustumCenter += cameraCorners.NearBottomLeft;
            frustumCenter += cameraCorners.NearBottomRight;
            frustumCenter += cameraCorners.FarTopLeft;
            frustumCenter += cameraCorners.FarTopRight;
            frustumCenter += cameraCorners.FarBottomLeft;
            frustumCenter += cameraCorners.FarBottomRight;
            frustumCenter /= 8f;

            float radius        = (cameraCorners.NearTopLeft - cameraCorners.FarBottomRight).Length() / 2.0f;
            float texelsPerUnit = shadowMapWidth / (radius * 2.0f);

            Matrix4x4 scalar = Matrix4x4.CreateScale(texelsPerUnit, texelsPerUnit, texelsPerUnit);

            Vector3 baseLookAt = -lightDir;

            Matrix4x4 lookat = Matrix4x4.CreateLookAt(Vector3.Zero, baseLookAt, Vector3.UnitY);

            lookat = scalar * lookat;
            Matrix4x4.Invert(lookat, out Matrix4x4 lookatInv);

            frustumCenter   = Vector3.Transform(frustumCenter, lookat);
            frustumCenter.X = (int)frustumCenter.X;
            frustumCenter.Y = (int)frustumCenter.Y;
            frustumCenter   = Vector3.Transform(frustumCenter, lookatInv);

            Vector3 lightPos = frustumCenter - (lightDir * radius * 2f);

            Matrix4x4 lightView = Matrix4x4.CreateLookAt(lightPos, frustumCenter, Vector3.UnitY);

            Matrix4x4 lightProjection = Util.CreateOrtho(
                gd,
                gd.IsDepthRangeZeroToOne,
                -radius * _lScale,
                radius * _rScale,
                -radius * _bScale,
                radius * _tScale,
                -radius * _nScale,
                radius * _fScale);

            Matrix4x4 viewProjectionMatrix = lightView * lightProjection;

            lightFrustum = new BoundingFrustum(viewProjectionMatrix);
            return(viewProjectionMatrix);
        }
Ejemplo n.º 2
0
        private void UpdateLightProjection()
        {
            if (MainCamera == null)
            {
                return;
            }
            if (Light == null)
            {
                _lightProjectionProvider.Data = Matrix4x4.Identity;
                _lightViewProvider.Data       = Matrix4x4.Identity;
                return;
            }

            Vector3        cameraDir      = MainCamera.Transform.Forward;
            Vector3        unitY          = Vector3.UnitY;
            Vector3        cameraPosition = MainCamera.Transform.Position;
            FrustumCorners corners;

            FrustumHelpers.ComputePerspectiveFrustumCorners(
                ref cameraPosition,
                ref cameraDir,
                ref unitY,
                MainCamera.FieldOfViewRadians,
                MainCamera.NearPlaneDistance,
                MainCamera.FarPlaneDistance,
                (float)RenderContext.Window.Width / (float)RenderContext.Window.Height,
                out corners);

            // Approach used: http://alextardif.com/ShadowMapping.html

            Vector3 frustumCenter = Vector3.Zero;

            frustumCenter += corners.NearTopLeft;
            frustumCenter += corners.NearTopRight;
            frustumCenter += corners.NearBottomLeft;
            frustumCenter += corners.NearBottomRight;
            frustumCenter += corners.FarTopLeft;
            frustumCenter += corners.FarTopRight;
            frustumCenter += corners.FarBottomLeft;
            frustumCenter += corners.FarBottomRight;
            frustumCenter /= 8f;

            float radius        = (corners.NearTopLeft - corners.FarBottomRight).Length() / 2.0f;
            float texelsPerUnit = (float)DepthMapWidth / (radius * 2.0f);

            Matrix4x4 scalar = Matrix4x4.CreateScale(texelsPerUnit, texelsPerUnit, texelsPerUnit);

            var     _lightDirection = Light.Direction;
            Vector3 baseLookAt      = -_lightDirection;

            Matrix4x4 lookat = Matrix4x4.CreateLookAt(Vector3.Zero, baseLookAt, Vector3.UnitY);

            lookat = scalar * lookat;
            Matrix4x4 lookatInv;

            Matrix4x4.Invert(lookat, out lookatInv);

            frustumCenter   = Vector3.Transform(frustumCenter, lookat);
            frustumCenter.X = (int)frustumCenter.X;
            frustumCenter.Y = (int)frustumCenter.Y;
            frustumCenter   = Vector3.Transform(frustumCenter, lookatInv);

            Vector3 lightPos = frustumCenter - (_lightDirection * radius * 2f);

            Matrix4x4 lightView = Matrix4x4.CreateLookAt(lightPos, frustumCenter, Vector3.UnitY);

            _lightProjectionProvider.Data = Matrix4x4.CreateOrthographicOffCenter(
                -radius, radius, -radius, radius, -radius * 4f, radius * 4f);
            _lightViewProvider.Data = lightView;
        }