Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- protected OrthographicCamera CalculateFrustum(DirectionalLight light, Camera mainCamera, float minZ, float maxZ)
- {
- // Shorten the view frustum according to the shadow view distance
- Matrix cameraMatrix;
- mainCamera.GetWorldMatrix(out cameraMatrix);
- for (int i = 0; i < 4; i++)
- splitFrustumCornersVS[i] = frustumCornersVS[i + 4] * (minZ / mainCamera.FarClip);
- for (int i = 4; i < 8; i++)
- splitFrustumCornersVS[i] = frustumCornersVS[i] * (maxZ / mainCamera.FarClip);
- 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
- Matrix viewMatrix = Matrix.CreateLookAt(Vector3.Zero - (light.Direction * 100), Vector3.Zero, 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++)
- {
- if (frustumCornersLS[i].X > maxes.X)
- maxes.X = frustumCornersLS[i].X;
- else if (frustumCornersLS[i].X < mins.X)
- mins.X = frustumCornersLS[i].X;
- if (frustumCornersLS[i].Y > maxes.Y)
- maxes.Y = frustumCornersLS[i].Y;
- else if (frustumCornersLS[i].Y < mins.Y)
- mins.Y = frustumCornersLS[i].Y;
- if (frustumCornersLS[i].Z > maxes.Z)
- maxes.Z = frustumCornersLS[i].Z;
- else if (frustumCornersLS[i].Z < mins.Z)
- mins.Z = frustumCornersLS[i].Z;
- }
- // 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 = (frustumCornersWS[0] - frustumCornersWS[6]).Length();
- diagonalLength += 2; //Without this, the shadow map isn't big enough in the world.
- float worldsUnitsPerTexel = diagonalLength / (float)ShadowMapSize;
- 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;
- // Create an orthographic camera for use as a shadow caster
- const float nearClipOffset = 100.0f;
- OrthographicCamera lightCamera = new OrthographicCamera(mins.X, maxes.X, mins.Y, maxes.Y, -maxes.Z - nearClipOffset, -mins.Z);
- lightCamera.SetViewMatrix(ref viewMatrix);
- return lightCamera;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement