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
        }