| 150 | } |
| 151 | |
| 152 | bool CascadedShadowMap::SetupForPlanarViewStable(const DirectionalLight& light, frustum projectionFrustum, affine3 inverseViewMatrix, float maxShadowDistance, float lightSpaceZUp, float lightSpaceZDown, float exponent, float3 preViewTranslation, int numberOfCascades) |
| 153 | { |
| 154 | assert(exponent > 1); |
| 155 | |
| 156 | assert(length(projectionFrustum.planes[frustum::NEAR_PLANE].normal) > 0); |
| 157 | |
| 158 | if (numberOfCascades < 0) |
| 159 | m_NumberOfCascades = static_cast<int>(m_Cascades.size()); |
| 160 | else |
| 161 | m_NumberOfCascades = std::min(numberOfCascades, static_cast<int>(m_Cascades.size())); |
| 162 | |
| 163 | if (maxShadowDistance > 0.f) |
| 164 | { |
| 165 | plane& nearPlane = projectionFrustum.nearPlane(); |
| 166 | plane& farPlane = projectionFrustum.farPlane(); |
| 167 | farPlane.normal = -nearPlane.normal; |
| 168 | farPlane.distance = -nearPlane.distance + maxShadowDistance; |
| 169 | } |
| 170 | else |
| 171 | { |
| 172 | assert(length(projectionFrustum.planes[frustum::FAR_PLANE].normal) > 0); |
| 173 | } |
| 174 | |
| 175 | std::array<float3, frustum::numCorners> corners; |
| 176 | for (uint32_t i = 0; i < frustum::numCorners; i++) |
| 177 | { |
| 178 | corners[i] = projectionFrustum.getCorner(i); |
| 179 | } |
| 180 | |
| 181 | float far = 1.f; |
| 182 | float near = far / exponent; |
| 183 | |
| 184 | bool viewModified = false; |
| 185 | |
| 186 | for (int cascade = m_NumberOfCascades - 1; cascade >= 0; cascade--) |
| 187 | { |
| 188 | if (cascade == 0) |
| 189 | near = 0.f; |
| 190 | |
| 191 | std::array<float3, frustum::numCorners> cascadeCorners; |
| 192 | for (uint32_t i = 0; i < frustum::numCorners; i++) |
| 193 | { |
| 194 | cascadeCorners[i] = lerp(corners[i & 3], corners[(i & 3) + 4], (i & 4) ? far : near); |
| 195 | } |
| 196 | |
| 197 | float3 nearDiagonalCenter = (cascadeCorners[frustum::C_BOTTOM | frustum::C_LEFT | frustum::C_NEAR] + cascadeCorners[frustum::C_TOP | frustum::C_RIGHT | frustum::C_NEAR]) * 0.5f; |
| 198 | float3 farDiagonalCenter = (cascadeCorners[frustum::C_BOTTOM | frustum::C_LEFT | frustum::C_FAR] + cascadeCorners[frustum::C_TOP | frustum::C_RIGHT | frustum::C_FAR]) * 0.5f; |
| 199 | float nearCenterToFarCenter = length(farDiagonalCenter - nearDiagonalCenter); |
| 200 | float nearDiagonalHalfLength = length(cascadeCorners[frustum::C_BOTTOM | frustum::C_LEFT | frustum::C_NEAR] - cascadeCorners[frustum::C_TOP | frustum::C_RIGHT | frustum::C_NEAR]) * 0.5f; |
| 201 | float farDiagonalHalfLength = length(cascadeCorners[frustum::C_BOTTOM | frustum::C_LEFT | frustum::C_FAR] - cascadeCorners[frustum::C_TOP | frustum::C_RIGHT | frustum::C_FAR]) * 0.5f; |
| 202 | |
| 203 | float nearCenterToSphereCenter = (square(nearCenterToFarCenter) + square(farDiagonalHalfLength) - square(nearDiagonalHalfLength)) / (2.f * nearCenterToFarCenter); |
| 204 | nearCenterToSphereCenter = clamp(nearCenterToSphereCenter, 0.f, nearCenterToFarCenter); |
| 205 | float3 sphereCenter = nearDiagonalCenter + normalize(farDiagonalCenter - nearDiagonalCenter) * nearCenterToSphereCenter; |
| 206 | float sphereRadius = sqrtf(square(farDiagonalHalfLength) + square(nearCenterToFarCenter - nearCenterToSphereCenter)); |
| 207 | |
| 208 | float3 cascadeCenter = inverseViewMatrix.transformPoint(sphereCenter); |
| 209 |
nothing calls this directly
no test coverage detected