Pastebin launched a little side project called VERYVIRAL.com, check it out ;-) Want more features on Pastebin? Sign Up, it's FREE!
Guest

Stable Cascade Shadow Maps

By: a guest on Aug 21st, 2010  |  syntax: C#  |  size: 3.52 KB  |  views: 968  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
This paste has a previous version, view the difference. Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1.         protected OrthographicCamera CalculateFrustum(DirectionalLight light, Camera mainCamera, float minZ, float maxZ)
  2.         {
  3.             // Shorten the view frustum according to the shadow view distance
  4.             Matrix cameraMatrix;
  5.             mainCamera.GetWorldMatrix(out cameraMatrix);
  6.  
  7.             for (int i = 0; i < 4; i++)
  8.                 splitFrustumCornersVS[i] = frustumCornersVS[i + 4] * (minZ / mainCamera.FarClip);
  9.  
  10.             for (int i = 4; i < 8; i++)
  11.                 splitFrustumCornersVS[i] = frustumCornersVS[i] * (maxZ / mainCamera.FarClip);
  12.  
  13.             Vector3.Transform(splitFrustumCornersVS, ref cameraMatrix, frustumCornersWS);
  14.  
  15.             // Position the shadow-caster camera so that it's looking at the centroid,
  16.             // and backed up in the direction of the sunlight
  17.             Matrix viewMatrix = Matrix.CreateLookAt(Vector3.Zero - (light.Direction * 100), Vector3.Zero, new Vector3(0, 1, 0));
  18.  
  19.             // Determine the position of the frustum corners in light space
  20.             Vector3.Transform(frustumCornersWS, ref viewMatrix, frustumCornersLS);
  21.  
  22.             // Calculate an orthographic projection by sizing a bounding box
  23.             // to the frustum coordinates in light space
  24.             Vector3 mins = frustumCornersLS[0];
  25.             Vector3 maxes = frustumCornersLS[0];
  26.             for (int i = 0; i < 8; i++)
  27.             {
  28.                 if (frustumCornersLS[i].X > maxes.X)
  29.                     maxes.X = frustumCornersLS[i].X;
  30.                 else if (frustumCornersLS[i].X < mins.X)
  31.                     mins.X = frustumCornersLS[i].X;
  32.                 if (frustumCornersLS[i].Y > maxes.Y)
  33.                     maxes.Y = frustumCornersLS[i].Y;
  34.                 else if (frustumCornersLS[i].Y < mins.Y)
  35.                     mins.Y = frustumCornersLS[i].Y;
  36.                 if (frustumCornersLS[i].Z > maxes.Z)
  37.                     maxes.Z = frustumCornersLS[i].Z;
  38.                 else if (frustumCornersLS[i].Z < mins.Z)
  39.                     mins.Z = frustumCornersLS[i].Z;
  40.             }
  41.  
  42.             // We snap the camera to 1 pixel increments so that moving the camera does not cause the shadows to jitter.
  43.             // This is a matter of integer dividing by the world space size of a texel
  44.             float diagonalLength = (frustumCornersWS[0] - frustumCornersWS[6]).Length();
  45.             diagonalLength += 2;    //Without this, the shadow map isn't big enough in the world.
  46.             float worldsUnitsPerTexel = diagonalLength / (float)ShadowMapSize;
  47.  
  48.             Vector3 vBorderOffset = (new Vector3(diagonalLength, diagonalLength, diagonalLength) - (maxes - mins)) * 0.5f;
  49.             maxes += vBorderOffset;
  50.             mins -= vBorderOffset;
  51.  
  52.             mins /= worldsUnitsPerTexel;
  53.             mins.X = (float)Math.Floor(mins.X);
  54.             mins.Y = (float)Math.Floor(mins.Y);
  55.             mins.Z = (float)Math.Floor(mins.Z);
  56.             mins *= worldsUnitsPerTexel;
  57.  
  58.             maxes /= worldsUnitsPerTexel;
  59.             maxes.X = (float)Math.Floor(maxes.X);
  60.             maxes.Y = (float)Math.Floor(maxes.Y);
  61.             maxes.Z = (float)Math.Floor(maxes.Z);
  62.             maxes *= worldsUnitsPerTexel;
  63.  
  64.             // Create an orthographic camera for use as a shadow caster
  65.             const float nearClipOffset = 100.0f;
  66.             OrthographicCamera lightCamera = new OrthographicCamera(mins.X, maxes.X, mins.Y, maxes.Y, -maxes.Z - nearClipOffset, -mins.Z);
  67.             lightCamera.SetViewMatrix(ref viewMatrix);
  68.  
  69.             return lightCamera;
  70.         }