View difference between Paste ID: Yn5SVPUP and
SHOW:
|
|
- or go back to the newest paste.
1 | - | |
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 | } |