| 22 | } |
| 23 | |
| 24 | void stable_cascaded_shadows::update_cascades(const float4x4 & view, const float near, const float far, const float aspectRatio, const float vfov, const float3 & lightDir) |
| 25 | { |
| 26 | nearPlanes.clear(); |
| 27 | farPlanes.clear(); |
| 28 | splitPlanes.clear(); |
| 29 | viewMatrices.clear(); |
| 30 | projMatrices.clear(); |
| 31 | shadowMatrices.clear(); |
| 32 | |
| 33 | for (size_t C = 0; C < uniforms::NUM_CASCADES; ++C) |
| 34 | { |
| 35 | const float splitIdx = uniforms::NUM_CASCADES; |
| 36 | |
| 37 | // Find the split planes using GPU Gem 3. Chap 10 "Practical Split Scheme". |
| 38 | // http://http.developer.nvidia.com/GPUGems3/gpugems3_ch10.html |
| 39 | const float splitNear = C > 0 ? mix(near + (static_cast<float>(C) / splitIdx) * (far - near), |
| 40 | near * pow(far / near, static_cast<float>(C) / splitIdx), splitLambda) : near; |
| 41 | |
| 42 | const float splitFar = C < splitIdx - 1 ? mix(near + (static_cast<float>(C + 1) / splitIdx) * (far - near), |
| 43 | near * pow(far / near, static_cast<float>(C + 1) / splitIdx), splitLambda) : far; |
| 44 | |
| 45 | const float4x4 splitProjectionMatrix = make_projection_matrix(vfov, aspectRatio, splitNear, splitFar); |
| 46 | |
| 47 | // Extract the frustum points |
| 48 | float4 splitFrustumVerts[8] = { |
| 49 | { -1.f, -1.f, -1.f, 1.f }, // Near plane |
| 50 | { -1.f, 1.f, -1.f, 1.f }, |
| 51 | { +1.f, 1.f, -1.f, 1.f }, |
| 52 | { +1.f, -1.f, -1.f, 1.f }, |
| 53 | { -1.f, -1.f, 1.f, 1.f }, // Far plane |
| 54 | { -1.f, 1.f, 1.f, 1.f }, |
| 55 | { +1.f, 1.f, 1.f, 1.f }, |
| 56 | { +1.f, -1.f, 1.f, 1.f } |
| 57 | }; |
| 58 | |
| 59 | for (unsigned int j = 0; j < 8; ++j) |
| 60 | { |
| 61 | splitFrustumVerts[j] = float4(transform_coord(inverse((splitProjectionMatrix * view)), splitFrustumVerts[j].xyz), 1); |
| 62 | } |
| 63 | |
| 64 | float3 frustumCentroid = float3(0, 0, 0); |
| 65 | for (size_t i = 0; i < 8; ++i) frustumCentroid += splitFrustumVerts[i].xyz; |
| 66 | frustumCentroid /= 8.0f; |
| 67 | |
| 68 | // Calculate the radius of a bounding sphere surrounding the frustum corners in worldspace |
| 69 | // This can be precomputed if the camera frustum does not change |
| 70 | float sphereRadius = 0.0f; |
| 71 | for (int i = 0; i < 8; ++i) |
| 72 | { |
| 73 | const float dist = length(splitFrustumVerts[i].xyz - frustumCentroid) * 1.0f; |
| 74 | sphereRadius = std::max(sphereRadius, dist); |
| 75 | } |
| 76 | |
| 77 | sphereRadius = (std::ceil(sphereRadius * 16.0f) / 16.0f); |
| 78 | |
| 79 | const float3 maxExtents = float3(sphereRadius, sphereRadius, sphereRadius); |
| 80 | const float3 minExtents = -maxExtents; |
| 81 |
no test coverage detected