| 296 | } |
| 297 | |
| 298 | OrthoFit SnapToTexelGrid(const OrthoFit& fit, int resolution) |
| 299 | { |
| 300 | OrthoFit out = fit; |
| 301 | if (resolution <= 0) |
| 302 | { |
| 303 | return out; |
| 304 | } |
| 305 | float res = static_cast<float>(resolution); |
| 306 | float texelX = (fit.maxB.x - fit.minB.x) / res; |
| 307 | float texelY = (fit.maxB.y - fit.minB.y) / res; |
| 308 | |
| 309 | auto snap = [](float v, float texel) |
| 310 | { |
| 311 | if (texel <= 0.0f) |
| 312 | { |
| 313 | return v; |
| 314 | } |
| 315 | return std::floor(v / texel) * texel; |
| 316 | }; |
| 317 | |
| 318 | // Snap the min corner to the texel grid and hold the extent fixed, so the |
| 319 | // matrix scale never changes and a sub-texel shift leaves it identical. |
| 320 | float minX = snap(fit.minB.x, texelX); |
| 321 | float minY = snap(fit.minB.y, texelY); |
| 322 | out.minB.x = minX; |
| 323 | out.minB.y = minY; |
| 324 | out.maxB.x = minX + texelX * res; |
| 325 | out.maxB.y = minY + texelY * res; |
| 326 | |
| 327 | float n = -out.maxB.z; |
| 328 | float f = -out.minB.z; |
| 329 | out.proj = Ortho(out.minB.x, out.maxB.x, out.minB.y, out.maxB.y, n, f); |
| 330 | return out; |
| 331 | } |
| 332 | |
| 333 | Bias ShadowBias(const Vec3& normal, const Vec3& lightDir, float texelWorldSize) |
| 334 | { |