Bakes lookup textures for computing environment specular from radiance encoded as spherical harmonics.
| 273 | |
| 274 | // Bakes lookup textures for computing environment specular from radiance encoded as spherical harmonics. |
| 275 | static void GenerateSHSpecularLookupTextures(ID3D11Device* device) |
| 276 | { |
| 277 | static const uint32 ViewResolution = 32; |
| 278 | static const uint32 RoughnessResolution = 32; |
| 279 | static const uint32 FresnelResolution = 32; |
| 280 | #if Debug_ |
| 281 | static const uint64 SqrtNumSamples = 10; |
| 282 | #else |
| 283 | static const uint64 SqrtNumSamples = 25; |
| 284 | #endif |
| 285 | static const uint64 NumSamples = SqrtNumSamples * SqrtNumSamples; |
| 286 | std::vector<Half4> texData0(ViewResolution * RoughnessResolution * FresnelResolution); |
| 287 | std::vector<Half2> texData1(ViewResolution * RoughnessResolution * FresnelResolution); |
| 288 | |
| 289 | int32 pattern = 0; |
| 290 | const Float3 n = Float3(0.0f, 0.0f, 1.0f); |
| 291 | |
| 292 | // Integrate the specular BRDF for a fixed value of Phi (camera lined up with the X-axis) |
| 293 | // for a set of viewing angles and roughness values |
| 294 | for(uint32 fIdx = 0; fIdx < FresnelResolution; ++fIdx) |
| 295 | { |
| 296 | const float specAlbedo = (fIdx + 0.5f) / FresnelResolution; |
| 297 | for(uint32 mIdx = 0; mIdx < RoughnessResolution; ++mIdx) |
| 298 | { |
| 299 | const float SqrtRoughness = (mIdx + 0.5f) / RoughnessResolution; |
| 300 | const float Roughness = SqrtRoughness * SqrtRoughness; |
| 301 | for(uint32 vIdx = 0; vIdx < ViewResolution; ++vIdx) |
| 302 | { |
| 303 | Float3 v = 0.0f; |
| 304 | v.z = (vIdx + 0.5f) / ViewResolution; |
| 305 | v.x = std::sqrt(1.0f - Saturate(v.z * v.z)); |
| 306 | |
| 307 | SH9 sh; |
| 308 | |
| 309 | SH9 accumulatedSH; |
| 310 | uint32 accumulatedSamples = 0; |
| 311 | for(uint64 sampleIdx = 0; sampleIdx < NumSamples; ++sampleIdx) |
| 312 | { |
| 313 | ++accumulatedSamples; |
| 314 | |
| 315 | Float2 sampleCoord = SampleCMJ2D(int32(sampleIdx), int32(SqrtNumSamples), int32(SqrtNumSamples), pattern++); |
| 316 | Float3 l = SampleDirectionGGX(v, n, Roughness, Float3x3(), sampleCoord.x, sampleCoord.y); |
| 317 | Float3 h = Float3::Normalize(v + l); |
| 318 | float nDotL = Saturate(l.z); |
| 319 | |
| 320 | float pdf = GGX_PDF(n, h, v, Roughness); |
| 321 | float brdf = GGX_Specular(Roughness, n, h, v, l) * Fresnel(specAlbedo, h, l).x; |
| 322 | SH9 sh = ProjectOntoSH9(l) * brdf * nDotL / pdf; |
| 323 | |
| 324 | accumulatedSH += sh; |
| 325 | if(accumulatedSamples >= 1000) |
| 326 | { |
| 327 | sh += accumulatedSH / float(NumSamples); |
| 328 | accumulatedSH = SH9(); |
| 329 | accumulatedSamples = 0; |
| 330 | } |
| 331 | } |
| 332 |
nothing calls this directly
no test coverage detected