36 #include <cugar/linalg/vector.h> 37 #include <cugar/basic/numbers.h> 38 #include <cugar/bsdf/differential_geometry.h> 41 #define USE_APPROX_SMITH 49 struct GGXSmithMicrofacetDistribution
56 CUGAR_FORCEINLINE CUGAR_HOST_DEVICE
57 GGXSmithMicrofacetDistribution(
const float _roughness) :
58 roughness(_roughness),
59 inv_roughness(1.0f / _roughness) {}
64 CUGAR_FORCEINLINE CUGAR_HOST_DEVICE
65 float SmithG1V(
const float NoV)
const 67 const float a = roughness;
69 const float G_V = NoV + sqrtf((NoV - NoV * a2) * NoV + a2);
70 return 2.0f * NoV / G_V;
73 CUGAR_FORCEINLINE CUGAR_HOST_DEVICE
74 float SmithG1V(
const float NoV)
const 76 const float CosThetaV2 = NoV*NoV;
77 const float SinThetaV2 = 1 - CosThetaV2;
78 const float TanThetaV2 = fabsf(SinThetaV2 <= 0.0f ? 0.0f : SinThetaV2 / CosThetaV2);
80 if (TanThetaV2 == 0.0f)
83 const float alpha = roughness ;
84 const float R2 = alpha * alpha * TanThetaV2;
85 return 2.0f / (1.0f + sqrtf(1.0f + R2));
91 CUGAR_FORCEINLINE CUGAR_HOST_DEVICE
94 const float2 inv_alpha = make_float2(inv_roughness, inv_roughness);
96 const float VoH = fabsf( dot(V, H) );
97 const float NoV = fabsf( V.z );
98 const float NoH = fabsf( H.z );
100 const float G1 = SmithG1V(NoV);
103 float p = D * G1 * VoH / NoV;
108 return (!isfinite(p) || isnan(p)) ? 1.0e8f :
p;
113 CUGAR_FORCEINLINE CUGAR_HOST_DEVICE
117 float*
p = NULL)
const 119 const float2 alpha = make_float2(roughness, roughness);
120 const float2 inv_alpha = make_float2(inv_roughness, inv_roughness);
123 const float sgn_V = V.z >= 0.0f ? 1.0f : -1.0f;
138 CUGAR_FORCEINLINE CUGAR_HOST_DEVICE
141 const float2 inv_alpha = make_float2(inv_roughness, inv_roughness);
143 const Vector3f N = geometry.normal_s;
145 const float VoH = fabsf( dot(V, H) );
146 const float NoV = fabsf( dot(N, V) );
147 const float NoH = fabsf( dot(N, H) );
149 const float G1 = SmithG1V(NoV);
151 const float D =
hvd_ggx_eval(inv_alpha, NoH, dot(geometry.tangent, H), dot(geometry.binormal, H));
152 float p = D * G1 * VoH / NoV;
157 return (!isfinite(p) || isnan(p)) ? 1.0e8f :
p;
162 CUGAR_FORCEINLINE CUGAR_HOST_DEVICE
167 float*
p = NULL)
const 169 const float2 alpha = make_float2(roughness, roughness);
170 const float2 inv_alpha = make_float2(inv_roughness, inv_roughness);
172 const float NoV = dot(V, geometry.normal_s);
173 const float sgn_V = NoV > 0.0f ? 1.0f : -1.0f;
176 dot(V, geometry.tangent),
177 dot(V, geometry.binormal),
183 H.x * geometry.tangent +
184 H.y * geometry.binormal +
185 H.z * geometry.normal_s * sgn_V;
188 *
p = this->
p(geometry, V, H);
215 CUGAR_FORCEINLINE CUGAR_HOST_DEVICE
216 GGXSmithBsdf(
const float _roughness,
bool _transmission =
false,
float _int_ior = 1.0f,
float _ext_ior = 1.0f) :
217 roughness(_roughness),
218 inv_roughness(1.0f / _roughness),
219 int_ior(_transmission ? _int_ior : -1.0f),
220 ext_ior(_transmission ? _ext_ior : -1.0f) {}
222 CUGAR_FORCEINLINE CUGAR_HOST_DEVICE
223 bool is_transmissive()
const {
return int_ior > 0.0f; }
225 CUGAR_FORCEINLINE CUGAR_HOST_DEVICE
226 bool is_reflective()
const {
return int_ior < 0.0f; }
230 CUGAR_FORCEINLINE CUGAR_HOST_DEVICE
231 float get_eta(
const float NoV)
const {
return NoV >= 0.0f ? ext_ior / int_ior : int_ior / ext_ior; }
235 CUGAR_FORCEINLINE CUGAR_HOST_DEVICE
240 CUGAR_FORCEINLINE CUGAR_HOST_DEVICE
241 float get_inv_eta(
const float NoV)
const {
return NoV >= 0.0f ? int_ior / ext_ior : ext_ior / int_ior; }
243 CUGAR_FORCEINLINE CUGAR_HOST_DEVICE
244 static float clamp_inf(
const float p) {
return (!isfinite(p) || isnan(p)) ? 1.0e8f : max( p, 0.0f ); }
248 CUGAR_FORCEINLINE CUGAR_HOST_DEVICE
251 const float a = roughness ;
252 const float Vis_SmithV = NoL * (NoV * (1 - a) + a);
253 const float Vis_SmithL = NoV * (NoL * (1 - a) + a);
255 return 0.5f * 1.0f / (Vis_SmithV + Vis_SmithL);
259 CUGAR_FORCEINLINE CUGAR_HOST_DEVICE
262 const float a = roughness ;
263 const float a2 = a*a;
264 const float G_V = NoV + sqrtf((NoV - NoV * a2) * NoV + a2);
265 const float G_L = NoL + sqrtf((NoL - NoL * a2) * NoL + a2);
266 return 1.0f / (G_V * G_L);
271 CUGAR_FORCEINLINE CUGAR_HOST_DEVICE
274 const float a = roughness ;
275 const float a2 = a*a;
276 const float G_V = NoV + sqrtf((NoV - NoV * a2) * NoV + a2);
277 return 0.5f / (G_V * NoL);
282 CUGAR_FORCEINLINE CUGAR_HOST_DEVICE
283 float SmithJoint(
const float NoV,
const float NoL)
const 288 const float CosThetaV2 = NoV*NoV;
289 const float SinThetaV2 = 1 - CosThetaV2;
290 const float TanThetaV2 = fabsf(SinThetaV2 <= 0.0f ? 0.0f : SinThetaV2 / CosThetaV2);
291 const float a_V2 = inv_roughness * inv_roughness / TanThetaV2;
292 const float LambdaV = (NoV < 1.0f) ? 0.5f * (-1.0f + sqrtf(1.0f + 1.0f / a_V2)) : 0.0f;
297 const float CosThetaL2 = NoL*NoL;
298 const float SinThetaL2 = 1 - CosThetaL2;
299 const float TanThetaL2 = fabsf(SinThetaL2 <= 0.0f ? 0.0f : SinThetaL2 / CosThetaL2);
300 const float a_L2 = inv_roughness * inv_roughness / TanThetaL2;
301 const float LambdaL = (NoL < 1.0f) ? 0.5f * (-1.0f + sqrtf(1.0f + 1.0f / a_L2)) : 0.0f;
304 return 1.0f / (1.0f + LambdaV + LambdaL);
307 CUGAR_FORCEINLINE CUGAR_HOST_DEVICE
310 const float CosThetaV2 = NoV*NoV;
311 const float SinThetaV2 = 1 - CosThetaV2;
312 const float TanThetaV2 = fabsf(SinThetaV2 <= 0.0f ? 0.0f : SinThetaV2 / CosThetaV2);
314 if (TanThetaV2 == 0.0f)
317 const float alpha = roughness ;
318 const float R2 = alpha * alpha * TanThetaV2;
319 return 2.0f / (1.0f + sqrtf(1.0f + R2));
322 CUGAR_FORCEINLINE CUGAR_HOST_DEVICE
323 float dwo_dh_transmission_factor(
const float VoH,
const float LoH,
const float eta,
const float inv_eta)
const 327 const float cos_theta_i = fabsf(VoH);
328 const float cos_theta_t2 = 1.f - eta * eta * (1.f - cos_theta_i * cos_theta_i);
329 if (cos_theta_t2 < 0.0f)
333 const float sqrtDenom = VoH + inv_eta * LoH;
334 const float factor = 4 * inv_eta * inv_eta
335 * fabsf( VoH * LoH ) /
336 (sqrtDenom * sqrtDenom);
345 CUGAR_FORCEINLINE CUGAR_HOST_DEVICE
348 const float2 inv_alpha = make_float2(inv_roughness, inv_roughness);
350 const Vector3f N = geometry.normal_s;
352 const float NoL = dot(N, L);
353 const float NoV = dot(N, V);
355 const float eta = get_eta(NoV);
356 const float inv_eta = get_inv_eta(NoV);
360 const float NoH = dot(N, H);
362 const float transmission_sign = is_transmissive() ? -1.0f : 1.0f;
365 if (transmission_sign * NoL * NoV <= 0.0f || NoH == 0.0f)
368 const float D =
hvd_ggx_eval(inv_alpha, fabsf( NoH ), dot(geometry.tangent, H), dot(geometry.binormal, H));
371 #if defined(USE_APPROX_SMITH) 372 const float G = PredividedSmithJointApprox(fabsf(NoV), fabsf(NoL));
374 const float G = PredividedSmithJoint(fabsf(NoV), fabsf(NoL));
377 if (!is_transmissive())
378 return clamp_inf( G * D );
383 const float VoH = dot(V, H);
384 const float LoH = dot(L, H);
386 const float transmission_factor = dwo_dh_transmission_factor(VoH, LoH, eta, inv_eta);
388 return clamp_inf( G * D * transmission_factor );
394 CUGAR_FORCEINLINE CUGAR_HOST_DEVICE
397 const Vector3f N = geometry.normal_s;
399 const float NoL = dot(N, L);
400 const float NoV = dot(N, V);
402 const float inv_eta = get_inv_eta(NoV);
406 const float NoH = dot(N, H);
408 const float transmission_sign = is_transmissive() ? -1.0f : 1.0f;
411 if (transmission_sign * NoL * NoV <= 0.0f || NoH == 0.0f)
414 const float G1 = PredividedSmithG1V(fabsf(NoV), fabsf(NoL));
416 #if defined(USE_APPROX_SMITH) 417 const float G = PredividedSmithJointApprox(fabsf(NoV), fabsf(NoL));
419 const float G = PredividedSmithJoint(fabsf(NoV), fabsf(NoL));
422 return Vector3f(clamp_inf( G / G1 ));
427 CUGAR_FORCEINLINE CUGAR_HOST_DEVICE
430 const float2 inv_alpha = make_float2(inv_roughness, inv_roughness);
432 const Vector3f N = geometry.normal_s;
434 const float NoL = dot(N, L);
435 const float NoV = dot(N, V);
438 const float eta = get_eta(NoV);
439 const float inv_eta = get_inv_eta(NoV);
443 const float NoH = dot(N, H);
445 const float transmission_sign = is_transmissive() ? -1.0f : 1.0f;
448 if (transmission_sign * NoL * NoV <= 0.0f || NoH == 0.0f)
455 const float D =
hvd_ggx_eval(inv_alpha, fabsf( NoH ), dot(geometry.tangent, H), dot(geometry.binormal, H));
457 #if defined(USE_APPROX_SMITH) 458 const float G = PredividedSmithJointApprox(fabsf(NoV), fabsf(NoL));
460 const float G = PredividedSmithJoint(fabsf(NoV), fabsf(NoL));
463 const float G1 = PredividedSmithG1V(fabsf(NoV), fabsf(NoL));
465 float transmission_factor = 1.0f;
466 if (is_transmissive())
468 const float VoH = dot(V, H);
469 const float LoH = dot(L, H);
471 transmission_factor = dwo_dh_transmission_factor(VoH, LoH, eta, inv_eta);
474 f = clamp_inf( G * D * transmission_factor );
475 p = clamp_inf( G1 * D * transmission_factor );
477 if (measure == kSolidAngle)
483 CUGAR_FORCEINLINE CUGAR_HOST_DEVICE
486 const float2 inv_alpha = make_float2(inv_roughness, inv_roughness);
488 const Vector3f N = geometry.normal_s;
490 const float NoL = dot(N, L);
491 const float NoV = dot(N, V);
493 const float eta = get_eta(NoV);
494 const float inv_eta = get_inv_eta(NoV);
498 const float NoH = dot(N, H);
500 const float transmission_sign = is_transmissive() ? -1.0f : 1.0f;
503 if (transmission_sign * NoL * NoV <= 0.0f || NoH == 0.0f)
506 const float D =
hvd_ggx_eval(inv_alpha, fabsf( NoH ), dot(geometry.tangent, H), dot(geometry.binormal, H));
507 const float G1 = PredividedSmithG1V(fabsf(NoV), fabsf(NoL));
509 float transmission_factor = 1.0f;
510 if (is_transmissive())
512 const float VoH = dot(V, H);
513 const float LoH = dot(L, H);
515 transmission_factor = dwo_dh_transmission_factor(VoH, LoH, eta, inv_eta);
518 float p = clamp_inf( G1 * D * transmission_factor );
520 if (measure == kSolidAngle)
528 CUGAR_FORCEINLINE CUGAR_HOST_DEVICE
538 const float2 alpha = make_float2(roughness, roughness);
539 const float2 inv_alpha = make_float2(inv_roughness, inv_roughness);
541 const Vector3f N = geometry.normal_s;
543 const float NoV = dot(N, V);
545 const float eta = get_eta(NoV);
546 const float inv_eta = get_inv_eta(NoV);
556 if (!is_transmissive())
559 L = 2 * dot(V, H) * H - V;
565 const float VoH = dot(V, H);
566 const float cos_theta_i = VoH;
567 const float cos_theta_t2 = 1.f - eta * eta * (1.f - cos_theta_i * cos_theta_i);
568 if (cos_theta_t2 < 0.0f)
570 L = 2 * dot(V, H) * H - V;
576 const float cos_theta_t = (cos_theta_i >= 0.0f ? 1.0f : -1.0f) * sqrtf(cos_theta_t2);
579 L = (eta * cos_theta_i - cos_theta_t) * H - eta * V;
582 const float NoL = dot(N, L);
583 const float NoH = dot(N, H);
585 const float transmission_sign = is_transmissive() ? -1.0f : 1.0f;
588 if (transmission_sign * NoL * NoV <= 0.0f || NoH == 0.0f)
596 const float D =
hvd_ggx_eval(inv_alpha, fabsf( NoH ), dot(geometry.tangent, H), dot(geometry.binormal, H));
598 #if defined(USE_APPROX_SMITH) 599 const float G = PredividedSmithJointApprox(fabsf(NoV), fabsf(NoL));
601 const float G = PredividedSmithJoint(fabsf(NoV), fabsf(NoL));
604 const float G1 = PredividedSmithG1V(fabsf(NoV), fabsf(NoL));
606 float transmission_factor = 1.0f;
607 if (is_transmissive())
609 const float VoH = dot(V, H);
610 const float LoH = dot(L, H);
612 transmission_factor = dwo_dh_transmission_factor(VoH, LoH, eta, inv_eta);
615 p_proj = clamp_inf( G1 * D * transmission_factor );
616 p = p_proj * fabsf(NoL);
617 g = clamp_inf( G / G1 );
618 assert(is_finite(g.x) && is_finite(g.y) && is_finite(g.z));
624 CUGAR_FORCEINLINE CUGAR_HOST_DEVICE
634 const float2 alpha = make_float2(roughness, roughness);
635 const float2 inv_alpha = make_float2(inv_roughness, inv_roughness);
637 const Vector3f N = geometry.normal_s;
639 const float NoV = dot(N, V);
641 const float eta = get_eta(NoV);
642 const float inv_eta = get_inv_eta(NoV);
644 const float sgn_V = NoV > 0.0f ? 1.0f : -1.0f;
647 dot(V, geometry.tangent),
648 dot(V, geometry.binormal),
663 H.x * geometry.tangent +
664 H.y * geometry.binormal +
665 H.z * geometry.normal_s * sgn_V;
667 if (!is_transmissive())
670 L = 2 * dot(V, H) * H - V;
676 const float VoH = dot(V, H);
677 const float cos_theta_i = VoH;
678 const float cos_theta_t2 = 1.f - eta * eta * (1.f - cos_theta_i * cos_theta_i);
679 if (cos_theta_t2 < 0.0f)
681 L = 2 * dot(V, H) * H - V;
687 const float cos_theta_t = -(cos_theta_i >= 0.0f ? 1.0f : -1.0f) * sqrtf(cos_theta_t2);
690 L = (eta * cos_theta_i + cos_theta_t) * H - eta * V;
693 const float NoL = dot(N, L);
694 const float NoH = dot(N, H);
696 const float transmission_sign = is_transmissive() ? -1.0f : 1.0f;
699 if (transmission_sign * NoL * NoV <= 0.0f || NoH == 0.0f)
707 const float D =
hvd_ggx_eval(inv_alpha, fabsf( NoH ), dot(geometry.tangent, H), dot(geometry.binormal, H));
709 #if defined(USE_APPROX_SMITH) 710 const float G = PredividedSmithJointApprox(fabsf(NoV), fabsf(NoL));
712 const float G = PredividedSmithJoint(fabsf(NoV), fabsf(NoL));
715 const float G1 = PredividedSmithG1V(fabsf(NoV), fabsf(NoL));
717 float transmission_factor = 1.0f;
718 if (is_transmissive())
720 const float VoH = dot(V, H);
721 const float LoH = dot(L, H);
723 transmission_factor = dwo_dh_transmission_factor(VoH, LoH, eta, inv_eta);
726 p_proj = clamp_inf( G1 * D * transmission_factor );
727 p = p_proj * fabsf(NoL);
728 g = clamp_inf( G / G1 );
729 assert(is_finite(g.x) && is_finite(g.y) && is_finite(g.z));
735 template <
typename RandomGeneratorT>
736 CUGAR_FORCEINLINE CUGAR_HOST_DEVICE
746 const float2 alpha = make_float2(roughness, roughness);
747 const float2 inv_alpha = make_float2(inv_roughness, inv_roughness);
749 const Vector3f N = geometry.normal_s;
751 const float NoV = dot(N, V);
752 const float NoL = dot(N, L);
754 const float eta = get_eta(NoV);
755 const float inv_eta = get_inv_eta(NoV);
757 const float sgn_N = NoV > 0.0f ? 1.0f : -1.0f;
760 dot(V, geometry.tangent),
761 dot(V, geometry.binormal),
766 const float NoH = dot(N, H);
769 dot(H, geometry.tangent),
770 dot(H, geometry.binormal),
779 const float transmission_sign = is_transmissive() ? -1.0f : 1.0f;
782 if (transmission_sign * NoL * NoV <= 0.0f || NoH == 0.0f)
789 const float D =
hvd_ggx_eval(inv_alpha, fabsf( NoH ), H_local.x, H_local.y);
791 #if defined(USE_APPROX_SMITH) 792 const float G = PredividedSmithJointApprox(fabsf(NoV), fabsf(NoL));
794 const float G = PredividedSmithJoint(fabsf(NoV), fabsf(NoL));
797 const float G1 = PredividedSmithG1V(fabsf(NoV), fabsf(NoL));
799 float transmission_factor = 1.0f;
800 if (is_transmissive())
802 const float VoH = dot(V, H);
803 const float LoH = dot(L, H);
805 transmission_factor = dwo_dh_transmission_factor(VoH, LoH, eta, inv_eta);
808 p_proj = clamp_inf( G1 * D * transmission_factor );
809 p = p_proj * fabsf(NoL);
813 p_proj = clamp_inf( 1.0f / p_proj );
814 p = clamp_inf( 1.0f / p );
820 CUGAR_FORCEINLINE CUGAR_HOST_DEVICE
829 const Vector3f N = geometry.normal_s;
831 p_proj = 1.0f / cugar::max(this->
p(geometry, V, L, kProjectedSolidAngle), 1.0e-8f);
832 p = p_proj / cugar::max(fabsf(dot(L, N)), 1.0e-8f);
SphericalMeasure
Definition: differential_geometry.h:50
CUGAR_FORCEINLINE CUGAR_HOST_DEVICE Vector3f f(const DifferentialGeometry &geometry, const Vector3f V, const Vector3f L) const
Definition: ggx_smith.h:346
CUGAR_FORCEINLINE CUGAR_HOST_DEVICE Vector3f sample(const Vector3f u, const Vector3f V, float *p=NULL) const
Definition: ggx_smith.h:114
CUGAR_FORCEINLINE CUGAR_HOST_DEVICE float p(const DifferentialGeometry &geometry, const Vector3f V, const Vector3f H) const
Definition: ggx_smith.h:139
CUGAR_FORCEINLINE CUGAR_HOST_DEVICE void sample(const DifferentialGeometry &geometry, const Vector3f H, const Vector3f V, Vector3f &L, Vector3f &g, float &p, float &p_proj) const
Definition: ggx_smith.h:529
CUGAR_FORCEINLINE CUGAR_HOST_DEVICE float hvd_ggx_eval(const float2 &inv_alpha, const float nh, const float ht, const float hb)
Definition: ggx_common.h:92
CUGAR_FORCEINLINE CUGAR_HOST_DEVICE bool invert(const DifferentialGeometry &geometry, const Vector3f V, const Vector3f L, RandomGeneratorT &random, Vector3f &z, float &p, float &p_proj) const
Definition: ggx_smith.h:737
CUGAR_FORCEINLINE CUGAR_HOST_DEVICE Vector3f vndf_microfacet(const Vector3f V, const Vector3f L, const Vector3f N, const float inv_eta)
Definition: ggx_common.h:70
CUGAR_FORCEINLINE CUGAR_HOST_DEVICE GGXSmithMicrofacetDistribution distribution() const
Definition: ggx_smith.h:236
CUGAR_FORCEINLINE CUGAR_HOST_DEVICE float p(const DifferentialGeometry &geometry, const Vector3f V, const Vector3f L, const SphericalMeasure measure=kProjectedSolidAngle) const
Definition: ggx_smith.h:484
CUGAR_FORCEINLINE CUGAR_HOST_DEVICE float2 vndf_ggx_smith_invert(const Vector3f _N, const float2 alpha, const Vector3f _V)
Definition: ggx_common.h:296
CUGAR_FORCEINLINE CUGAR_HOST_DEVICE float get_inv_eta(const float NoV) const
Definition: ggx_smith.h:241
CUGAR_FORCEINLINE CUGAR_HOST_DEVICE float p(const Vector3f V, const Vector3f H) const
Definition: ggx_smith.h:92
CUGAR_FORCEINLINE CUGAR_HOST_DEVICE float PredividedSmithJointApprox(const float NoV, const float NoL) const
Definition: ggx_smith.h:249
Definition: ggx_smith.h:54
CUGAR_FORCEINLINE CUGAR_HOST_DEVICE float get_eta(const float NoV) const
Definition: ggx_smith.h:231
CUGAR_FORCEINLINE CUGAR_HOST_DEVICE float SmithG1(const float NoV) const
Definition: ggx_smith.h:308
Definition: differential_geometry.h:59
float random()
Definition: tiled_sampling.h:44
CUGAR_FORCEINLINE CUGAR_HOST_DEVICE float3 vndf_ggx_smith_sample(const float2 samples, const float2 alpha, const Vector3f _V)
Definition: ggx_common.h:265
Definition: ggx_smith.h:204
Define a vector_view POD type and plain_view() for std::vector.
Definition: diff.h:38
CUGAR_FORCEINLINE CUGAR_HOST_DEVICE float PredividedSmithJoint(const float NoV, const float NoL) const
Definition: ggx_smith.h:260
CUGAR_FORCEINLINE CUGAR_HOST_DEVICE Vector3f sample(const Vector3f u, const DifferentialGeometry &geometry, const Vector3f V, float *p=NULL) const
Definition: ggx_smith.h:163
CUGAR_FORCEINLINE CUGAR_HOST_DEVICE GGXSmithBsdf(const float _roughness, bool _transmission=false, float _int_ior=1.0f, float _ext_ior=1.0f)
Definition: ggx_smith.h:216
CUGAR_FORCEINLINE CUGAR_HOST_DEVICE float PredividedSmithG1V(const float NoV, const float NoL) const
Definition: ggx_smith.h:272
CUGAR_FORCEINLINE CUGAR_HOST_DEVICE void f_and_p(const DifferentialGeometry &geometry, const Vector3f V, const Vector3f L, Vector3f &f, float &p, const SphericalMeasure measure=kProjectedSolidAngle) const
Definition: ggx_smith.h:428
CUGAR_FORCEINLINE CUGAR_HOST_DEVICE void inverse_pdf(const DifferentialGeometry &geometry, const Vector3f V, const Vector3f L, const Vector3f u, float &p, float &p_proj) const
Definition: ggx_smith.h:821
CUGAR_FORCEINLINE CUGAR_HOST_DEVICE Vector3f f_over_p(const DifferentialGeometry &geometry, const Vector3f V, const Vector3f L) const
Definition: ggx_smith.h:395
CUGAR_FORCEINLINE CUGAR_HOST_DEVICE void sample(const Vector3f u, const DifferentialGeometry &geometry, const Vector3f V, Vector3f &L, Vector3f &g, float &p, float &p_proj) const
Definition: ggx_smith.h:625