Ejemplo n.º 1
0
        public void UpdateFrustumCorners()
        {
            //Set camera data
            m_camera.FarClip     = 1000.0f;
            m_camera.NearClip    = 1.0f;
            m_camera.AspectRatio = MyCamera.AspectRatio;
            m_camera.FieldOfView = MyCamera.FovWithZoom;

            //camera.WorldMatrix = Matrix.CreateWorld(MyCamera.Position, MyCamera.ForwardVector, MyCamera.UpVector);
            m_camera.ViewMatrix       = MyCamera.ViewMatrix;
            m_camera.ProjectionMatrix = MyCamera.ProjectionMatrix;

            // Get corners of the main camera's bounding frustum
            Matrix cameraTransform, viewMatrix;

            m_camera.GetWorldMatrix(out cameraTransform);
            m_camera.GetViewMatrix(out viewMatrix);
            m_camera.BoundingFrustum.GetCorners(m_frustumCornersWS);
            Vector3.Transform(m_frustumCornersWS, ref viewMatrix, m_frustumCornersVS);
            for (int i = 0; i < 4; i++)
            {
                m_farFrustumCornersVS[i] = m_frustumCornersVS[i + 4];
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Determines the size of the frustum needed to cover the viewable area,
        /// then creates an appropriate orthographic projection.
        /// </summary>
        /// <param name="light">The directional light to use</param>
        /// <param name="mainCamera">The camera viewing the scene</param>
        protected MyOrthographicCamera CalculateFrustum(MyOrthographicCamera lightCamera, MyPerspectiveCamera mainCamera, float minZ, float maxZ)
        {
            // Shorten the view frustum according to the shadow view distance
            Matrix cameraMatrix;
            mainCamera.GetWorldMatrix(out cameraMatrix);

            Matrix.CreatePerspectiveFieldOfView(mainCamera.FieldOfView, mainCamera.AspectRatio, minZ, maxZ, out lightCamera.CameraSubfrustum);
            Matrix wma;
            mainCamera.GetViewMatrix(out wma);
            lightCamera.CameraSubfrustum = MyCamera.ViewMatrix * lightCamera.CameraSubfrustum;

            for (int i = 0; i < 4; i++)
                m_splitFrustumCornersVS[i] = m_frustumCornersVS[i + 4] * (minZ / mainCamera.FarClip);

            for (int i = 4; i < 8; i++)
                m_splitFrustumCornersVS[i] = m_frustumCornersVS[i] * (maxZ / mainCamera.FarClip);

            Vector3.Transform(m_splitFrustumCornersVS, ref cameraMatrix, m_frustumCornersWS);

            // Position the shadow-caster camera so that it's looking at the centroid,
            // and backed up in the direction of the sunlight

            //Toto se nemeni per frame!
            Matrix viewMatrix = Matrix.CreateLookAt(Vector3.Zero - (m_sunLightDirection * mainCamera.FarClip), Vector3.Zero, new Vector3(0, 1, 0));

            // Determine the position of the frustum corners in light space
            Vector3.Transform(m_frustumCornersWS, ref viewMatrix, m_frustumCornersLS);

            // Calculate an orthographic projection by sizing a bounding box
            // to the frustum coordinates in light space
            Vector3 mins = m_frustumCornersLS[0];
            Vector3 maxes = m_frustumCornersLS[0];
            for (int i = 0; i < 8; i++)
            {
                if (m_frustumCornersLS[i].X > maxes.X)
                    maxes.X = m_frustumCornersLS[i].X;
                else if (m_frustumCornersLS[i].X < mins.X)
                    mins.X = m_frustumCornersLS[i].X;
                if (m_frustumCornersLS[i].Y > maxes.Y)
                    maxes.Y = m_frustumCornersLS[i].Y;
                else if (m_frustumCornersLS[i].Y < mins.Y)
                    mins.Y = m_frustumCornersLS[i].Y;
                if (m_frustumCornersLS[i].Z > maxes.Z)
                    maxes.Z = m_frustumCornersLS[i].Z;
                else if (m_frustumCornersLS[i].Z < mins.Z)
                    mins.Z = m_frustumCornersLS[i].Z;
            }

            // Update an orthographic camera for collision detection
            lightCamera.UpdateUnscaled(mins.X, maxes.X, mins.Y, maxes.Y, -maxes.Z - SHADOW_MAX_OFFSET, -mins.Z);
            lightCamera.SetViewMatrixUnscaled(ref viewMatrix);

            // We snap the camera to 1 pixel increments so that moving the camera does not cause the shadows to jitter.
            // This is a matter of integer dividing by the world space size of a texel
            float diagonalLength = (m_frustumCornersWS[0] - m_frustumCornersWS[6]).Length();

            //Make bigger box - ensure rotation and movement stabilization
            diagonalLength = MyMath.GetNearestBiggerPowerOfTwo(diagonalLength);

            float worldsUnitsPerTexel = diagonalLength / (float)ShadowMapCascadeSize;

            Vector3 vBorderOffset = (new Vector3(diagonalLength, diagonalLength, diagonalLength) - (maxes - mins)) * 0.5f;
            maxes += vBorderOffset;
            mins -= vBorderOffset;

            mins /= worldsUnitsPerTexel;
            mins.X = (float)Math.Floor(mins.X);
            mins.Y = (float)Math.Floor(mins.Y);
            mins.Z = (float)Math.Floor(mins.Z);
            mins *= worldsUnitsPerTexel;

            maxes /= worldsUnitsPerTexel;
            maxes.X = (float)Math.Floor(maxes.X);
            maxes.Y = (float)Math.Floor(maxes.Y);
            maxes.Z = (float)Math.Floor(maxes.Z);
            maxes *= worldsUnitsPerTexel;


            /*
            Matrix proj;
            Matrix.CreateOrthographicOffCenter(mins.X, maxes.X, mins.Y, maxes.Y, -maxes.Z - SHADOW_MAX_OFFSET, -mins.Z, out proj);
            
            if (MyUtils.IsEqual(lightCamera.ProjectionMatrix, proj))
            {   //cache
                return null;
            } */


            // Update an orthographic camera for use as a shadow caster
            lightCamera.Update(mins.X, maxes.X, mins.Y, maxes.Y, -maxes.Z - SHADOW_MAX_OFFSET, -mins.Z);


            lightCamera.SetViewMatrix(ref viewMatrix);

            return lightCamera;
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Determines the size of the frustum needed to cover the viewable area,
        /// then creates an appropriate orthographic projection.
        /// </summary>
        /// <param name="light">The directional light to use</param>
        /// <param name="mainCamera">The camera viewing the scene</param>
        protected MyOrthographicCamera CalculateFrustum(MyOrthographicCamera lightCamera, MyPerspectiveCamera mainCamera, float minZ, float maxZ)
        {
            // Shorten the view frustum according to the shadow view distance
            Matrix cameraMatrix;

            mainCamera.GetWorldMatrix(out cameraMatrix);

            Matrix.CreatePerspectiveFieldOfView(mainCamera.FieldOfView, mainCamera.AspectRatio, minZ, maxZ, out lightCamera.CameraSubfrustum);
            Matrix wma;

            mainCamera.GetViewMatrix(out wma);
            lightCamera.CameraSubfrustum = MyCamera.ViewMatrix * lightCamera.CameraSubfrustum;

            for (int i = 0; i < 4; i++)
            {
                m_splitFrustumCornersVS[i] = m_frustumCornersVS[i + 4] * (minZ / mainCamera.FarClip);
            }

            for (int i = 4; i < 8; i++)
            {
                m_splitFrustumCornersVS[i] = m_frustumCornersVS[i] * (maxZ / mainCamera.FarClip);
            }

            Vector3.Transform(m_splitFrustumCornersVS, ref cameraMatrix, m_frustumCornersWS);

            // Position the shadow-caster camera so that it's looking at the centroid,
            // and backed up in the direction of the sunlight

            //Toto se nemeni per frame!
            Matrix viewMatrix = Matrix.CreateLookAt(Vector3.Zero - (m_sunLightDirection * mainCamera.FarClip), Vector3.Zero, new Vector3(0, 1, 0));

            // Determine the position of the frustum corners in light space
            Vector3.Transform(m_frustumCornersWS, ref viewMatrix, m_frustumCornersLS);

            // Calculate an orthographic projection by sizing a bounding box
            // to the frustum coordinates in light space
            Vector3 mins  = m_frustumCornersLS[0];
            Vector3 maxes = m_frustumCornersLS[0];

            for (int i = 0; i < 8; i++)
            {
                if (m_frustumCornersLS[i].X > maxes.X)
                {
                    maxes.X = m_frustumCornersLS[i].X;
                }
                else if (m_frustumCornersLS[i].X < mins.X)
                {
                    mins.X = m_frustumCornersLS[i].X;
                }
                if (m_frustumCornersLS[i].Y > maxes.Y)
                {
                    maxes.Y = m_frustumCornersLS[i].Y;
                }
                else if (m_frustumCornersLS[i].Y < mins.Y)
                {
                    mins.Y = m_frustumCornersLS[i].Y;
                }
                if (m_frustumCornersLS[i].Z > maxes.Z)
                {
                    maxes.Z = m_frustumCornersLS[i].Z;
                }
                else if (m_frustumCornersLS[i].Z < mins.Z)
                {
                    mins.Z = m_frustumCornersLS[i].Z;
                }
            }

            // Update an orthographic camera for collision detection
            lightCamera.UpdateUnscaled(mins.X, maxes.X, mins.Y, maxes.Y, -maxes.Z - SHADOW_MAX_OFFSET, -mins.Z);
            lightCamera.SetViewMatrixUnscaled(ref viewMatrix);

            // We snap the camera to 1 pixel increments so that moving the camera does not cause the shadows to jitter.
            // This is a matter of integer dividing by the world space size of a texel
            float diagonalLength = (m_frustumCornersWS[0] - m_frustumCornersWS[6]).Length();

            //Make bigger box - ensure rotation and movement stabilization
            diagonalLength = MyMath.GetNearestBiggerPowerOfTwo(diagonalLength);

            float worldsUnitsPerTexel = diagonalLength / (float)ShadowMapCascadeSize;

            Vector3 vBorderOffset = (new Vector3(diagonalLength, diagonalLength, diagonalLength) - (maxes - mins)) * 0.5f;

            maxes += vBorderOffset;
            mins  -= vBorderOffset;

            mins  /= worldsUnitsPerTexel;
            mins.X = (float)Math.Floor(mins.X);
            mins.Y = (float)Math.Floor(mins.Y);
            mins.Z = (float)Math.Floor(mins.Z);
            mins  *= worldsUnitsPerTexel;

            maxes  /= worldsUnitsPerTexel;
            maxes.X = (float)Math.Floor(maxes.X);
            maxes.Y = (float)Math.Floor(maxes.Y);
            maxes.Z = (float)Math.Floor(maxes.Z);
            maxes  *= worldsUnitsPerTexel;


            /*
             * Matrix proj;
             * Matrix.CreateOrthographicOffCenter(mins.X, maxes.X, mins.Y, maxes.Y, -maxes.Z - SHADOW_MAX_OFFSET, -mins.Z, out proj);
             *
             * if (MyUtils.IsEqual(lightCamera.ProjectionMatrix, proj))
             * {   //cache
             *  return null;
             * } */


            // Update an orthographic camera for use as a shadow caster
            lightCamera.Update(mins.X, maxes.X, mins.Y, maxes.Y, -maxes.Z - SHADOW_MAX_OFFSET, -mins.Z);


            lightCamera.SetViewMatrix(ref viewMatrix);

            return(lightCamera);
        }