Exemplo n.º 1
0
        public MyShadowRenderer(int shadowMapSize, MyRenderTargets renderTarget, MyRenderTargets depthTarget, bool multiThreaded)
        {
            ShadowMapCascadeSize = shadowMapSize;
            m_shadowRenderTarget = renderTarget;
            m_shadowDepthTarget  = depthTarget;

            for (int i = 0; i < NumSplits; i++)
            {
                m_lightCameras[i] = new MyOrthographicCamera(1, 1, 1, 10);
                // Occ queries for shadows are disabled, so save memory by commenting this
                //m_occlusionQueriesLists[i] = new List<MyOcclusionQueryIssue>(1024);
                m_cascadeQueries[i] = new MyOcclusionQueryIssue(null);
                m_visibility[i]     = true;
            }

            MultiThreaded = multiThreaded;
        }
Exemplo n.º 2
0
        /// <summary>
        /// Creates the renderer
        /// </summary>
        /// <param name="graphicsDevice">The GraphicsDevice to use for rendering</param>
        /// <param name="contentManager">The MyCustomContentManager to use for loading content</param>
        public MyShadowRenderer(int shadowMapSize, MyRenderTargets renderTarget, MyRenderTargets depthTarget, bool multiThreaded)
        {
            ShadowMapCascadeSize = shadowMapSize;
            m_shadowRenderTarget = renderTarget;
            m_shadowDepthTarget = depthTarget;

            for (int i = 0; i < NumSplits; i++)
            {
                m_lightCameras[i] = new MyOrthographicCamera(1, 1, 1, 10);
                // Occ queries for shadows are disabled, so save memory by commenting this
                //m_occlusionQueriesLists[i] = new List<MyOcclusionQueryIssue>(1024);
                m_cascadeQueries[i] = new MyOcclusionQueryIssue(null);
                m_visibility[i] = true;
            }

            MultiThreaded = multiThreaded;
        }
Exemplo 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)
        {
            MatrixD cameraMatrix;
            mainCamera.GetWorldMatrix(out cameraMatrix);

            MatrixD cameraMatrixAtZero = cameraMatrix;
            cameraMatrixAtZero.Translation = Vector3D.Zero;

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

            Vector3D.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
            MatrixD viewMatrix = MatrixD.CreateLookAt(MyRenderCamera.Position - (MyRender.Sun.Direction * (float)mainCamera.FarClip), MyRenderCamera.Position, Vector3D.Up);

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

            // Calculate an orthographic projection by sizing a bounding box
            // to the frustum coordinates in light space
            Vector3D mins = m_frustumCornersLS[0];
            Vector3D 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
            var diagonalLength = (m_frustumCornersWS[0] - m_frustumCornersWS[6]).Length();
                                                                                     
            //Make bigger box - ensure rotation and movement stabilization
            diagonalLength = MathHelper.GetNearestBiggerPowerOfTwo(diagonalLength);

            var worldsUnitsPerTexel = diagonalLength / (float)ShadowMapCascadeSize;

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

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

            maxes /= worldsUnitsPerTexel;
            maxes.X = Math.Floor(maxes.X);
            maxes.Y = Math.Floor(maxes.Y);
            maxes.Z = 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;
        }
Exemplo n.º 4
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)
        {
            MatrixD cameraMatrix;

            mainCamera.GetWorldMatrix(out cameraMatrix);

            MatrixD cameraMatrixAtZero = cameraMatrix;

            cameraMatrixAtZero.Translation = Vector3D.Zero;


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

            Vector3D.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
            Vector3 viewUp     = Math.Abs(Vector3.UnitY.Dot(MyRender.Sun.Direction)) < 0.99f ? Vector3.UnitY : Vector3.UnitX;
            MatrixD viewMatrix = MatrixD.CreateLookAt(MyRenderCamera.Position - (MyRender.Sun.Direction * (float)mainCamera.FarClip), MyRenderCamera.Position, viewUp);

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

            // Calculate an orthographic projection by sizing a bounding box
            // to the frustum coordinates in light space
            Vector3D mins  = m_frustumCornersLS[0];
            Vector3D 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
            var diagonalLength = (m_frustumCornersWS[0] - m_frustumCornersWS[6]).Length();

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

            var worldsUnitsPerTexel = diagonalLength / (float)ShadowMapCascadeSize;

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

            maxes += vBorderOffset;
            mins  -= vBorderOffset;

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

            maxes  /= worldsUnitsPerTexel;
            maxes.X = Math.Floor(maxes.X);
            maxes.Y = Math.Floor(maxes.Y);
            maxes.Z = 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);
        }