Example #1
0
        void ComputeFrustum(float minZ, float maxZ, RenderView cameraRenderView, int split)
        {
            // Shorten the view frustum according to the shadow view distance
            Matrix cameraMatrix = cameraRenderView.GetWorldMatrix();

            Vector4 camPos = cameraRenderView.GetEyePosShader();

            for (int i = 0; i < 4; i++)
                splitFrustumCornersVS[i] = frustumCornersVS[i + 4] * (minZ / camPos.W);

            for (int i = 4; i < 8; i++)
                splitFrustumCornersVS[i] = frustumCornersVS[i] * (maxZ / camPos.W);

            Vector3.Transform(splitFrustumCornersVS, ref cameraMatrix, frustumCornersWS);

            // Position the shadow-caster camera so that it's looking at the centroid,
            // and backed up in the direction of the sunlight
            BoundingBox sceneBounds = scene.GetSceneDimensions();
            Vector3 sceneCenter = (sceneBounds.Min + sceneBounds.Max) * 0.5f;
            Vector3 sceneExtents = (sceneBounds.Max - sceneBounds.Min) * 0.5f;
            Vector3 lightDir = -this.Transformation.GetPosition();
            lightDir.Normalize();
            Matrix viewMatrix = Matrix.CreateLookAt(sceneCenter - (lightDir * sceneExtents.Length()), sceneCenter, new Vector3(0, 1, 0));

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

            // Calculate an orthographic projection by sizing a bounding box
            // to the frustum coordinates in light space
            Vector3 mins = frustumCornersLS[0];
            Vector3 maxes = frustumCornersLS[0];
            for (int i = 0; i < 8; i++)
            {
                maxes = Vector3.Max(frustumCornersLS[i], maxes);
                mins = Vector3.Min(frustumCornersLS[i], mins);
            }

            // Create an orthographic camera for use as a shadow caster
            //const float nearClipOffset = 380.0f;

            float nearPlane = -maxes.Z-sceneExtents.Length();
            float farPlane = -mins.Z;

            renderViews[split].SetPosition(viewMatrix.Translation);
            renderViews[split].SetView(viewMatrix);
            renderViews[split].SetNearPlane(nearPlane);
            renderViews[split].SetFarPlane(farPlane);
            renderViews[split].SetProjection(Matrix.CreateOrthographicOffCenter(mins.X, maxes.X, mins.Y, maxes.Y, nearPlane, farPlane));
            lightViewProjectionMatrices[split] = renderViews[split].GetViewProjection();
            lightClipPositions[split] = renderViews[split].GetEyePosShader();
        }