MCPcopy Create free account
hub / github.com/AcademySoftwareFoundation/OpenShadingLanguage / BeckmannDist

Class BeckmannDist

src/testrender/shading.cpp:330–380  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

328};
329
330struct BeckmannDist {
331 static float F(const float tan_m2) {
332 return float(1 / M_PI) * OIIO::fast_exp(-tan_m2);
333 }
334
335 static float Lambda(const float a2) {
336 const float a = sqrtf(a2);
337 return a < 1.6f ? (1.0f - 1.259f * a + 0.396f * a2) / (3.535f * a + 2.181f * a2) : 0.0f;
338 }
339
340 static Vec2 sampleSlope(float cos_theta, float randu, float randv) {
341 const float SQRT_PI_INV = 1 / sqrtf(float(M_PI));
342 float ct = cos_theta < 1e-6f ? 1e-6f : cos_theta;
343 float tanThetaI = sqrtf(1 - ct * ct) / ct;
344 float cotThetaI = 1 / tanThetaI;
345
346 /* sample slope X */
347 // compute a coarse approximation using the approximation:
348 // exp(-ierf(x)^2) ~= 1 - x * x
349 // solve y = 1 + b + K * (1 - b * b)
350 float c = OIIO::fast_erf(cotThetaI);
351 float K = tanThetaI * SQRT_PI_INV;
352 float yApprox = randu * (1.0f + c + K * (1 - c * c));
353 float yExact = randu * (1.0f + c + K * OIIO::fast_exp(-cotThetaI * cotThetaI));
354 float b = K > 0 ? (0.5f - sqrtf(K * (K - yApprox + 1.0f) + 0.25f)) / K : yApprox - 1.0f;
355
356 // perform newton step to refine toward the true root
357 float invErf = OIIO::fast_ierf(b);
358 float value = 1.0f + b + K * OIIO::fast_exp(-invErf * invErf) - yExact;
359
360 // check if we are close enough already
361 // this also avoids NaNs as we get close to the root
362 Vec2 slope;
363 if (fabsf(value) > 1e-6f) {
364 b -= value / (1 - invErf * tanThetaI); // newton step 1
365 invErf = OIIO::fast_ierf(b);
366 value = 1.0f + b + K * OIIO::fast_exp(-invErf * invErf) - yExact;
367 b -= value / (1 - invErf * tanThetaI); // newton step 2
368 // compute the slope from the refined value
369 slope.x = OIIO::fast_ierf(b);
370 } else {
371 // we are close enough already
372 slope.x = invErf;
373 }
374
375 /* sample slope Y */
376 slope.y = OIIO::fast_ierf(2.0f * randv - 1.0f);
377
378 return slope;
379 }
380};
381
382
383template <typename Distribution, int Refract>

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected