Cycles: Use per-microfacet Fresnel term for Glass closures

This commit replaces the current Glass approach, where Glass is a virtual closure
that gets replaced with a Glossy and a Refractive closure, with a combined
closure that handles Fresnel after sampling the microfacet. That way, the Fresnel
term is more accurate since it accounts for the microfacet normal, not the
shading normal.

Also updates the BSDF sampling to use a 3D sampler now, since we need two
dimensions to pick the microfacet normal and then a third dimension to pick
reflection/refraction. This can also be used to get rid of the LCG in the
Principled Hair BSDF, which means we can remove it altogether once MultiGGX is
gone.

Also, "sharp" is now supported as a microfacet distribution in OSL, and 2
is supported as the "refract" argument to microfacet() in order to get glass.
This commit is contained in:
Lukas Stockner 2023-03-05 17:15:26 +01:00
parent a30abe9c2e
commit 5f9b518a8b
20 changed files with 444 additions and 455 deletions

View File

@ -113,8 +113,6 @@ set(SRC_KERNEL_CLOSURE_HEADERS
closure/bsdf_microfacet_multi_impl.h
closure/bsdf_oren_nayar.h
closure/bsdf_phong_ramp.h
closure/bsdf_reflection.h
closure/bsdf_refraction.h
closure/bsdf_toon.h
closure/bsdf_transparent.h
closure/bsdf_util.h

View File

@ -11,8 +11,6 @@
#include "kernel/closure/bsdf_diffuse_ramp.h"
#include "kernel/closure/bsdf_microfacet.h"
#include "kernel/closure/bsdf_microfacet_multi.h"
#include "kernel/closure/bsdf_reflection.h"
#include "kernel/closure/bsdf_refraction.h"
#include "kernel/closure/bsdf_transparent.h"
#include "kernel/closure/bsdf_ashikhmin_shirley.h"
#include "kernel/closure/bsdf_toon.h"
@ -110,8 +108,8 @@ ccl_device_inline bool bsdf_is_transmission(ccl_private const ShaderClosure *sc,
ccl_device_inline int bsdf_sample(KernelGlobals kg,
ccl_private ShaderData *sd,
ccl_private const ShaderClosure *sc,
float randu,
float randv,
const int path_flag,
const float3 rand,
ccl_private Spectrum *eval,
ccl_private float3 *wo,
ccl_private float *pdf,
@ -125,110 +123,160 @@ ccl_device_inline int bsdf_sample(KernelGlobals kg,
switch (sc->type) {
case CLOSURE_BSDF_DIFFUSE_ID:
label = bsdf_diffuse_sample(sc, Ng, sd->wi, randu, randv, eval, wo, pdf);
label = bsdf_diffuse_sample(sc, Ng, sd->wi, rand.x, rand.y, eval, wo, pdf);
*sampled_roughness = one_float2();
*eta = 1.0f;
break;
#if defined(__SVM__) || defined(__OSL__)
case CLOSURE_BSDF_OREN_NAYAR_ID:
label = bsdf_oren_nayar_sample(sc, Ng, sd->wi, randu, randv, eval, wo, pdf);
label = bsdf_oren_nayar_sample(sc, Ng, sd->wi, rand.x, rand.y, eval, wo, pdf);
*sampled_roughness = one_float2();
*eta = 1.0f;
break;
# ifdef __OSL__
case CLOSURE_BSDF_PHONG_RAMP_ID:
label = bsdf_phong_ramp_sample(
sc, Ng, sd->wi, randu, randv, eval, wo, pdf, sampled_roughness);
sc, Ng, sd->wi, rand.x, rand.y, eval, wo, pdf, sampled_roughness);
*eta = 1.0f;
break;
case CLOSURE_BSDF_DIFFUSE_RAMP_ID:
label = bsdf_diffuse_ramp_sample(sc, Ng, sd->wi, randu, randv, eval, wo, pdf);
label = bsdf_diffuse_ramp_sample(sc, Ng, sd->wi, rand.x, rand.y, eval, wo, pdf);
*sampled_roughness = one_float2();
*eta = 1.0f;
break;
# endif
case CLOSURE_BSDF_TRANSLUCENT_ID:
label = bsdf_translucent_sample(sc, Ng, sd->wi, randu, randv, eval, wo, pdf);
label = bsdf_translucent_sample(sc, Ng, sd->wi, rand.x, rand.y, eval, wo, pdf);
*sampled_roughness = one_float2();
*eta = 1.0f;
break;
case CLOSURE_BSDF_REFLECTION_ID:
label = bsdf_reflection_sample(sc, Ng, sd->wi, randu, randv, eval, wo, pdf, eta);
*sampled_roughness = zero_float2();
break;
case CLOSURE_BSDF_REFRACTION_ID:
label = bsdf_refraction_sample(sc, Ng, sd->wi, randu, randv, eval, wo, pdf, eta);
*sampled_roughness = zero_float2();
break;
case CLOSURE_BSDF_TRANSPARENT_ID:
label = bsdf_transparent_sample(sc, Ng, sd->wi, randu, randv, eval, wo, pdf);
label = bsdf_transparent_sample(sc, Ng, sd->wi, rand.x, rand.y, eval, wo, pdf);
*sampled_roughness = zero_float2();
*eta = 1.0f;
break;
case CLOSURE_BSDF_REFLECTION_ID:
case CLOSURE_BSDF_REFRACTION_ID:
case CLOSURE_BSDF_SHARP_GLASS_ID:
label = bsdf_microfacet_sharp_sample(sc,
path_flag,
Ng,
sd->wi,
rand.x,
rand.y,
rand.z,
eval,
wo,
pdf,
sampled_roughness,
eta);
break;
case CLOSURE_BSDF_MICROFACET_GGX_ID:
case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
label = bsdf_microfacet_ggx_sample(
sc, Ng, sd->wi, randu, randv, eval, wo, pdf, sampled_roughness, eta);
case CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID:
label = bsdf_microfacet_ggx_sample(sc,
path_flag,
Ng,
sd->wi,
rand.x,
rand.y,
rand.z,
eval,
wo,
pdf,
sampled_roughness,
eta);
break;
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
label = bsdf_microfacet_multi_ggx_sample(
kg, sc, Ng, sd->wi, randu, randv, eval, wo, pdf, &sd->lcg_state, sampled_roughness, eta);
label = bsdf_microfacet_multi_ggx_sample(kg,
sc,
Ng,
sd->wi,
rand.x,
rand.y,
eval,
wo,
pdf,
&sd->lcg_state,
sampled_roughness,
eta);
break;
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
label = bsdf_microfacet_multi_ggx_glass_sample(
kg, sc, Ng, sd->wi, randu, randv, eval, wo, pdf, &sd->lcg_state, sampled_roughness, eta);
label = bsdf_microfacet_multi_ggx_glass_sample(kg,
sc,
Ng,
sd->wi,
rand.x,
rand.y,
eval,
wo,
pdf,
&sd->lcg_state,
sampled_roughness,
eta);
break;
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
label = bsdf_microfacet_beckmann_sample(
sc, Ng, sd->wi, randu, randv, eval, wo, pdf, sampled_roughness, eta);
case CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID:
label = bsdf_microfacet_beckmann_sample(sc,
path_flag,
Ng,
sd->wi,
rand.x,
rand.y,
rand.z,
eval,
wo,
pdf,
sampled_roughness,
eta);
break;
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
label = bsdf_ashikhmin_shirley_sample(
sc, Ng, sd->wi, randu, randv, eval, wo, pdf, sampled_roughness);
sc, Ng, sd->wi, rand.x, rand.y, eval, wo, pdf, sampled_roughness);
*eta = 1.0f;
break;
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
label = bsdf_ashikhmin_velvet_sample(sc, Ng, sd->wi, randu, randv, eval, wo, pdf);
label = bsdf_ashikhmin_velvet_sample(sc, Ng, sd->wi, rand.x, rand.y, eval, wo, pdf);
*sampled_roughness = one_float2();
*eta = 1.0f;
break;
case CLOSURE_BSDF_DIFFUSE_TOON_ID:
label = bsdf_diffuse_toon_sample(sc, Ng, sd->wi, randu, randv, eval, wo, pdf);
label = bsdf_diffuse_toon_sample(sc, Ng, sd->wi, rand.x, rand.y, eval, wo, pdf);
*sampled_roughness = one_float2();
*eta = 1.0f;
break;
case CLOSURE_BSDF_GLOSSY_TOON_ID:
label = bsdf_glossy_toon_sample(sc, Ng, sd->wi, randu, randv, eval, wo, pdf);
label = bsdf_glossy_toon_sample(sc, Ng, sd->wi, rand.x, rand.y, eval, wo, pdf);
// double check if this is valid
*sampled_roughness = one_float2();
*eta = 1.0f;
break;
case CLOSURE_BSDF_HAIR_REFLECTION_ID:
label = bsdf_hair_reflection_sample(
sc, Ng, sd->wi, randu, randv, eval, wo, pdf, sampled_roughness);
sc, Ng, sd->wi, rand.x, rand.y, eval, wo, pdf, sampled_roughness);
*eta = 1.0f;
break;
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
label = bsdf_hair_transmission_sample(
sc, Ng, sd->wi, randu, randv, eval, wo, pdf, sampled_roughness);
sc, Ng, sd->wi, rand.x, rand.y, eval, wo, pdf, sampled_roughness);
*eta = 1.0f;
break;
case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
label = bsdf_principled_hair_sample(
kg, sc, sd, randu, randv, eval, wo, pdf, sampled_roughness, eta);
kg, sc, sd, rand.x, rand.y, rand.z, eval, wo, pdf, sampled_roughness, eta);
break;
case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
label = bsdf_principled_diffuse_sample(sc, Ng, sd->wi, randu, randv, eval, wo, pdf);
label = bsdf_principled_diffuse_sample(sc, Ng, sd->wi, rand.x, rand.y, eval, wo, pdf);
*sampled_roughness = one_float2();
*eta = 1.0f;
break;
case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
label = bsdf_principled_sheen_sample(sc, Ng, sd->wi, randu, randv, eval, wo, pdf);
label = bsdf_principled_sheen_sample(sc, Ng, sd->wi, rand.x, rand.y, eval, wo, pdf);
*sampled_roughness = one_float2();
*eta = 1.0f;
break;
@ -277,7 +325,6 @@ ccl_device_inline void bsdf_roughness_eta(const KernelGlobals kg,
ccl_private float *eta)
{
#ifdef __SVM__
bool refractive = false;
float alpha = 1.0f;
#endif
switch (sc->type) {
@ -305,40 +352,28 @@ ccl_device_inline void bsdf_roughness_eta(const KernelGlobals kg,
*roughness = one_float2();
*eta = 1.0f;
break;
case CLOSURE_BSDF_REFLECTION_ID: {
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
*roughness = zero_float2();
*eta = bsdf->ior;
break;
}
case CLOSURE_BSDF_REFRACTION_ID: {
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
*roughness = zero_float2();
// do we need to inverse eta??
*eta = bsdf->ior;
break;
}
case CLOSURE_BSDF_TRANSPARENT_ID:
*roughness = zero_float2();
*eta = 1.0f;
break;
case CLOSURE_BSDF_REFLECTION_ID:
case CLOSURE_BSDF_REFRACTION_ID:
case CLOSURE_BSDF_SHARP_GLASS_ID:
case CLOSURE_BSDF_MICROFACET_GGX_ID:
case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID: {
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
case CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID: {
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
*roughness = make_float2(bsdf->alpha_x, bsdf->alpha_y);
refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
*eta = refractive ? 1.0f / bsdf->ior : bsdf->ior;
*eta = CLOSURE_IS_REFRACTIVE(bsdf->type) ? 1.0f / bsdf->ior : bsdf->ior;
break;
}
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID: {
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
*roughness = make_float2(bsdf->alpha_x, bsdf->alpha_y);
*eta = bsdf->ior;
break;
}
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID: {
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
@ -346,13 +381,6 @@ ccl_device_inline void bsdf_roughness_eta(const KernelGlobals kg,
*eta = bsdf->ior;
break;
}
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: {
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
*roughness = make_float2(bsdf->alpha_x, bsdf->alpha_y);
refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
*eta = refractive ? 1.0f / bsdf->ior : bsdf->ior;
} break;
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID: {
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
*roughness = make_float2(bsdf->alpha_x, bsdf->alpha_y);
@ -432,38 +460,29 @@ ccl_device_inline int bsdf_label(const KernelGlobals kg,
case CLOSURE_BSDF_TRANSLUCENT_ID:
label = LABEL_TRANSMIT | LABEL_DIFFUSE;
break;
case CLOSURE_BSDF_REFLECTION_ID:
label = LABEL_REFLECT | LABEL_SINGULAR;
break;
case CLOSURE_BSDF_REFRACTION_ID:
label = LABEL_TRANSMIT | LABEL_SINGULAR;
break;
case CLOSURE_BSDF_TRANSPARENT_ID:
label = LABEL_TRANSMIT | LABEL_TRANSPARENT;
break;
case CLOSURE_BSDF_REFLECTION_ID:
case CLOSURE_BSDF_REFRACTION_ID:
case CLOSURE_BSDF_SHARP_GLASS_ID:
case CLOSURE_BSDF_MICROFACET_GGX_ID:
case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID: {
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
label = (bsdf->alpha_x * bsdf->alpha_y <= 1e-7f) ? LABEL_REFLECT | LABEL_SINGULAR :
LABEL_REFLECT | LABEL_GLOSSY;
break;
}
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: {
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
case CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID:
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID: {
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
label = (bsdf->alpha_x * bsdf->alpha_y <= 1e-7f) ? LABEL_TRANSMIT | LABEL_SINGULAR :
LABEL_TRANSMIT | LABEL_GLOSSY;
label = ((bsdf_is_transmission(sc, wo)) ? LABEL_TRANSMIT : LABEL_REFLECT) |
((bsdf->alpha_x * bsdf->alpha_y <= 1e-7f) ? LABEL_SINGULAR : LABEL_GLOSSY);
break;
}
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
label = (bsdf_is_transmission(sc, wo)) ? LABEL_TRANSMIT | LABEL_GLOSSY :
LABEL_REFLECT | LABEL_GLOSSY;
break;
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
label = LABEL_REFLECT | LABEL_GLOSSY;
break;
@ -546,19 +565,19 @@ ccl_device_inline
case CLOSURE_BSDF_TRANSLUCENT_ID:
eval = bsdf_translucent_eval(sc, sd->wi, wo, pdf);
break;
case CLOSURE_BSDF_REFLECTION_ID:
eval = bsdf_reflection_eval(sc, sd->wi, wo, pdf);
break;
case CLOSURE_BSDF_REFRACTION_ID:
eval = bsdf_refraction_eval(sc, sd->wi, wo, pdf);
break;
case CLOSURE_BSDF_TRANSPARENT_ID:
eval = bsdf_transparent_eval(sc, sd->wi, wo, pdf);
break;
case CLOSURE_BSDF_REFLECTION_ID:
case CLOSURE_BSDF_REFRACTION_ID:
case CLOSURE_BSDF_SHARP_GLASS_ID:
eval = bsdf_microfacet_sharp_eval(sc, sd->N, sd->wi, wo, pdf);
break;
case CLOSURE_BSDF_MICROFACET_GGX_ID:
case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
case CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID:
eval = bsdf_microfacet_ggx_eval(sc, sd->N, sd->wi, wo, pdf);
break;
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
@ -571,6 +590,7 @@ ccl_device_inline
break;
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID:
eval = bsdf_microfacet_beckmann_eval(sc, sd->N, sd->wi, wo, pdf);
break;
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
@ -643,10 +663,12 @@ ccl_device void bsdf_blur(KernelGlobals kg, ccl_private ShaderClosure *sc, float
case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
case CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID:
bsdf_microfacet_ggx_blur(sc, roughness);
break;
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID:
bsdf_microfacet_beckmann_blur(sc, roughness);
break;
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
@ -678,9 +700,8 @@ ccl_device_inline Spectrum bsdf_albedo(ccl_private const ShaderData *sd,
switch (sc->type) {
case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
albedo *= microfacet_fresnel((ccl_private const MicrofacetBsdf *)sc, sd->wi, sc->N);
albedo *= microfacet_fresnel((ccl_private const MicrofacetBsdf *)sc, sd->wi, sc->N, false);
break;
case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
albedo *= ((ccl_private const PrincipledSheenBsdf *)sc)->avg_value;

View File

@ -338,6 +338,7 @@ ccl_device int bsdf_principled_hair_sample(KernelGlobals kg,
ccl_private ShaderData *sd,
float randu,
float randv,
float randw,
ccl_private Spectrum *eval,
ccl_private float3 *wo,
ccl_private float *pdf,
@ -359,8 +360,8 @@ ccl_device int bsdf_principled_hair_sample(KernelGlobals kg,
float2 u[2];
u[0] = make_float2(randu, randv);
u[1].x = lcg_step_float(&sd->lcg_state);
u[1].y = lcg_step_float(&sd->lcg_state);
u[1].x = randw;
u[1].y = hash_float3_to_float(make_float3(randu, randv, randw));
const float sin_theta_o = local_O.x;
const float cos_theta_o = cos_from_sin(sin_theta_o);

View File

@ -19,6 +19,7 @@ CCL_NAMESPACE_BEGIN
enum MicrofacetType {
BECKMANN,
GGX,
SHARP,
};
typedef struct MicrofacetExtra {
@ -183,14 +184,18 @@ ccl_device_forceinline float3 microfacet_ggx_sample_vndf(const float3 wi,
* Else it is simply white
*/
ccl_device_forceinline Spectrum microfacet_fresnel(ccl_private const MicrofacetBsdf *bsdf,
float3 wi,
float3 H)
const float3 wi,
const float3 H,
const bool refraction)
{
if (CLOSURE_IS_BSDF_MICROFACET_FRESNEL(bsdf->type)) {
kernel_assert(!refraction);
return interpolate_fresnel_color(wi, H, bsdf->ior, bsdf->extra->cspec0);
}
else if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) {
return make_spectrum(fresnel_dielectric_cos(dot(wi, H), bsdf->ior));
else if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID ||
CLOSURE_IS_GLASS(bsdf->type)) {
const float F = fresnel_dielectric_cos(dot(wi, H), bsdf->ior);
return make_spectrum(refraction ? 1.0f - F : F);
}
else {
return one_spectrum();
@ -200,7 +205,7 @@ ccl_device_forceinline Spectrum microfacet_fresnel(ccl_private const MicrofacetB
ccl_device_forceinline void bsdf_microfacet_adjust_weight(ccl_private const ShaderData *sd,
ccl_private MicrofacetBsdf *bsdf)
{
bsdf->sample_weight *= average(microfacet_fresnel(bsdf, sd->wi, bsdf->N));
bsdf->sample_weight *= average(microfacet_fresnel(bsdf, sd->wi, bsdf->N, false));
}
/* Generalized Trowbridge-Reitz for clearcoat. */
@ -227,8 +232,8 @@ ccl_device_inline float bsdf_lambda_from_sqr_alpha_tan_n(float sqr_alpha_tan_n)
return 0.5f * (sqrtf(1.0f + sqr_alpha_tan_n) - 1.0f);
}
else {
/* m_type == MicrofacetType::BECKMANN
* Approximation from below Equation 69. */
kernel_assert(m_type == MicrofacetType::BECKMANN);
/* Approximation from below Equation 69. */
if (sqr_alpha_tan_n < 0.39f) {
/* Equivalent to a >= 1.6f, but also handles sqr_alpha_tan_n == 0.0f cleanly. */
return 0.0f;
@ -267,7 +272,7 @@ template<MicrofacetType m_type> ccl_device_inline float bsdf_D(float alpha2, flo
return expf((1.0f - 1.0f / cos_NH2) / alpha2) / (M_PI_F * alpha2 * sqr(cos_NH2));
}
else {
/* m_type == MicrofacetType::GGX */
kernel_assert(m_type == MicrofacetType::GGX);
return alpha2 / (M_PI_F * sqr(1.0f + (alpha2 - 1.0f) * cos_NH2));
}
}
@ -284,7 +289,7 @@ ccl_device_inline float bsdf_aniso_D(float alpha_x, float alpha_y, float3 H)
return expf(-(sqr(H.x) + sqr(H.y)) / cos_NH2) / (M_PI_F * alpha2 * sqr(cos_NH2));
}
else {
/* m_type == MicrofacetType::GGX */
kernel_assert(m_type == MicrofacetType::GGX);
return M_1_PI_F / (alpha2 * sqr(len_squared(H)));
}
}
@ -296,9 +301,14 @@ ccl_device Spectrum bsdf_microfacet_eval(ccl_private const ShaderClosure *sc,
const float3 wo,
ccl_private float *pdf)
{
if (m_type == MicrofacetType::SHARP) {
*pdf = 0.0f;
return zero_spectrum();
}
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
const bool m_refractive = (bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID) ||
(bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID);
const bool m_refractive = CLOSURE_IS_REFRACTIVE(bsdf->type);
const bool m_glass = CLOSURE_IS_GLASS(bsdf->type);
const float3 N = bsdf->N;
const float cos_NI = dot(N, wi);
@ -308,14 +318,23 @@ ccl_device Spectrum bsdf_microfacet_eval(ccl_private const ShaderClosure *sc,
const float alpha_x = bsdf->alpha_x;
const float alpha_y = bsdf->alpha_y;
if ((cos_NI <= 0) || ((cos_NgO < 0.0f) != m_refractive) || ((cos_NO < 0.0f) != m_refractive) ||
(alpha_x * alpha_y <= 1e-7f)) {
const bool is_refraction = (cos_NO < 0.0f);
/* Check whether the pair of directions is valid for evaluation:
* - Incoming direction has to be in the upper hemisphere (Cycles convention)
* - Specular cases can't be evaluated, only sampled.
* - The outgoing direction has to be the in the same hemisphere w.r.t. both normals.
* - Purely reflective closures can't have refraction.
* - Purely refractive closures can't have reflection.
*/
if ((cos_NI <= 0) || (alpha_x * alpha_y <= 1e-7f) || ((cos_NgO < 0.0f) != is_refraction) ||
(is_refraction && !m_refractive) || (!is_refraction && m_refractive && !m_glass)) {
*pdf = 0.0f;
return zero_spectrum();
}
/* Compute half vector. */
float3 H = m_refractive ? -(bsdf->ior * wo + wi) : (wi + wo);
float3 H = is_refraction ? -(bsdf->ior * wo + wi) : (wi + wo);
const float inv_len_H = 1.0f / len(H);
H *= inv_len_H;
@ -323,7 +342,7 @@ ccl_device Spectrum bsdf_microfacet_eval(ccl_private const ShaderClosure *sc,
float D, lambdaI, lambdaO;
/* TODO: add support for anisotropic transmission. */
if (alpha_x == alpha_y || m_refractive) { /* Isotropic. */
if (alpha_x == alpha_y || is_refraction) { /* Isotropic. */
float alpha2 = alpha_x * alpha_y;
if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) {
@ -354,23 +373,31 @@ ccl_device Spectrum bsdf_microfacet_eval(ccl_private const ShaderClosure *sc,
lambdaO = bsdf_aniso_lambda<m_type>(alpha_x, alpha_y, local_O);
}
const float common = D / cos_NI *
(m_refractive ?
sqr(bsdf->ior * inv_len_H) * fabsf(dot(H, wi) * dot(H, wo)) :
0.25f);
float common = D / cos_NI *
(is_refraction ? sqr(bsdf->ior * inv_len_H) * fabsf(dot(H, wi) * dot(H, wo)) :
0.25f);
*pdf = common / (1.0f + lambdaI);
float lobe_pdf = 1.0f;
if (m_glass) {
float fresnel = fresnel_dielectric_cos(dot(H, wi), bsdf->ior);
float reflect_pdf = (fresnel == 1.0f) ? 1.0f : clamp(fresnel, 0.125f, 0.875f);
lobe_pdf = is_refraction ? (1.0f - reflect_pdf) : reflect_pdf;
}
const Spectrum F = microfacet_fresnel(bsdf, wo, H);
*pdf = common * lobe_pdf / (1.0f + lambdaI);
const Spectrum F = microfacet_fresnel(bsdf, wi, H, is_refraction);
return F * common / (1.0f + lambdaO + lambdaI);
}
template<MicrofacetType m_type>
ccl_device int bsdf_microfacet_sample(ccl_private const ShaderClosure *sc,
const int path_flag,
float3 Ng,
float3 wi,
float randu,
float randv,
float randw,
ccl_private Spectrum *eval,
ccl_private float3 *wo,
ccl_private float *pdf,
@ -380,70 +407,116 @@ ccl_device int bsdf_microfacet_sample(ccl_private const ShaderClosure *sc,
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
const float m_eta = bsdf->ior;
const bool m_refractive = (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID) ||
(bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID);
int label = m_refractive ? LABEL_TRANSMIT : LABEL_REFLECT;
const bool m_refractive = CLOSURE_IS_REFRACTIVE(bsdf->type);
const float alpha_x = bsdf->alpha_x;
const float alpha_y = bsdf->alpha_y;
bool m_singular = (m_type == MicrofacetType::SHARP) || (alpha_x * alpha_y <= 1e-7f);
const float3 N = bsdf->N;
const float cos_NI = dot(N, wi);
if (cos_NI <= 0) {
return label | LABEL_GLOSSY;
*eval = zero_spectrum();
*pdf = 0.0f;
return (m_refractive ? LABEL_TRANSMIT : LABEL_REFLECT) |
(m_singular ? LABEL_SINGULAR : LABEL_GLOSSY);
}
float3 X, Y;
const float alpha_x = bsdf->alpha_x;
const float alpha_y = bsdf->alpha_y;
if (alpha_x == alpha_y) {
make_orthonormals(N, &X, &Y);
float3 H;
float cos_NH, cos_HI;
float3 local_H, local_I, X, Y; /* Nneeded for anisotropic microfacets later. */
if (m_singular) {
H = N;
cos_NH = 1.0f;
cos_HI = cos_NI;
}
else {
make_orthonormals_tangent(N, bsdf->T, &X, &Y);
if (alpha_x == alpha_y) {
make_orthonormals(N, &X, &Y);
}
else {
make_orthonormals_tangent(N, bsdf->T, &X, &Y);
}
/* Importance sampling with distribution of visible normals. Vectors are transformed to local
* space before and after sampling. */
local_I = make_float3(dot(X, wi), dot(Y, wi), cos_NI);
if (m_type == MicrofacetType::GGX) {
local_H = microfacet_ggx_sample_vndf(local_I, alpha_x, alpha_y, randu, randv);
}
else {
/* m_type == MicrofacetType::BECKMANN */
local_H = microfacet_beckmann_sample_vndf(local_I, alpha_x, alpha_y, randu, randv);
}
H = X * local_H.x + Y * local_H.y + N * local_H.z;
cos_NH = local_H.z;
cos_HI = dot(H, wi);
}
/* Importance sampling with distribution of visible normals. Vectors are transformed to local
* space before and after sampling. */
const float3 local_I = make_float3(dot(X, wi), dot(Y, wi), cos_NI);
float3 local_H;
if (m_type == MicrofacetType::GGX) {
local_H = microfacet_ggx_sample_vndf(local_I, alpha_x, alpha_y, randu, randv);
}
else {
/* m_type == MicrofacetType::BECKMANN */
local_H = microfacet_beckmann_sample_vndf(local_I, alpha_x, alpha_y, randu, randv);
}
const float3 H = X * local_H.x + Y * local_H.y + N * local_H.z;
const float cos_NH = local_H.z;
const float cos_HI = dot(H, wi);
bool valid = false;
bool valid;
bool do_refract;
float lobe_pdf;
if (m_refractive) {
float3 R, T;
bool inside;
float fresnel = fresnel_dielectric(m_eta, H, wi, wo, &inside);
valid = !inside;
float fresnel = fresnel_dielectric(m_eta, H, wi, &R, &T, &inside);
*wo = T;
/* For glass closures, we decide between reflection and refraction here. */
if (CLOSURE_IS_GLASS(bsdf->type)) {
if (fresnel == 1.0f) {
/* TIR, reflection is the only option. */
do_refract = false;
lobe_pdf = 1.0f;
}
else {
/* Decide between reflection and refraction, using defensive sampling to avoid
* excessive noise for reflection highlights. */
float reflect_pdf = (path_flag & PATH_RAY_CAMERA) ? clamp(fresnel, 0.125f, 0.875f) :
fresnel;
do_refract = (randw >= reflect_pdf);
lobe_pdf = do_refract ? (1.0f - reflect_pdf) : reflect_pdf;
}
}
else {
/* For pure refractive closures, refraction is the only option. */
do_refract = true;
lobe_pdf = 1.0f;
valid = valid && (fresnel != 1.0f);
}
}
else {
/* Pure reflective closure, reflection is the only option. */
valid = true;
lobe_pdf = 1.0f;
do_refract = false;
}
valid = !inside && fresnel != 1.0f;
int label;
if (do_refract) {
/* wo was already set to the refracted direction by fresnel_dielectric. */
// valid = valid && (dot(Ng, *wo) < 0);
label = LABEL_TRANSMIT;
/* If the IOR is close enough to 1.0, just treat the interaction as specular. */
m_singular = m_singular || (fabsf(m_eta - 1.0f) < 1e-4f);
}
else {
/* Eq. 39 - compute actual reflected direction */
*wo = 2 * cos_HI * H - wi;
valid = dot(Ng, *wo) > 0;
valid = valid && (dot(Ng, *wo) > 0);
label = LABEL_REFLECT;
}
if (!valid) {
*eval = zero_spectrum();
*pdf = 0.0f;
return label | LABEL_GLOSSY;
return label | (m_singular ? LABEL_SINGULAR : LABEL_GLOSSY);
}
if (alpha_x * alpha_y <= 1e-7f || (m_refractive && fabsf(m_eta - 1.0f) < 1e-4f)) {
if (m_singular) {
label |= LABEL_SINGULAR;
/* Some high number for MIS. */
*pdf = 1e6f;
*eval = make_spectrum(1e6f) * microfacet_fresnel(bsdf, *wo, H);
*pdf = lobe_pdf * 1e6f;
*eval = make_spectrum(1e6f) * microfacet_fresnel(bsdf, wi, H, do_refract);
}
else {
label |= LABEL_GLOSSY;
@ -451,7 +524,7 @@ ccl_device int bsdf_microfacet_sample(ccl_private const ShaderClosure *sc,
float D, lambdaI, lambdaO;
/* TODO: add support for anisotropic transmission. */
if (alpha_x == alpha_y || m_refractive) { /* Isotropic. */
if (alpha_x == alpha_y || do_refract) { /* Isotropic. */
float alpha2 = alpha_x * alpha_y;
if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) {
@ -479,17 +552,17 @@ ccl_device int bsdf_microfacet_sample(ccl_private const ShaderClosure *sc,
const float cos_HO = dot(H, *wo);
const float common = D / cos_NI *
(m_refractive ? fabsf(cos_HI * cos_HO) / sqr(cos_HO + cos_HI / m_eta) :
0.25f);
(do_refract ? fabsf(cos_HI * cos_HO) / sqr(cos_HO + cos_HI / m_eta) :
0.25f);
*pdf = common / (1.0f + lambdaI);
*pdf = common * lobe_pdf / (1.0f + lambdaI);
Spectrum F = microfacet_fresnel(bsdf, *wo, H);
const Spectrum F = microfacet_fresnel(bsdf, wi, H, do_refract);
*eval = F * common / (1.0f + lambdaI + lambdaO);
}
*sampled_roughness = make_float2(alpha_x, alpha_y);
*eta = m_refractive ? 1.0f / m_eta : m_eta;
*eta = do_refract ? 1.0f / m_eta : m_eta;
return label;
}
@ -559,6 +632,18 @@ ccl_device int bsdf_microfacet_ggx_refraction_setup(ccl_private MicrofacetBsdf *
return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_HAS_TRANSMISSION;
}
ccl_device int bsdf_microfacet_ggx_glass_setup(ccl_private MicrofacetBsdf *bsdf)
{
bsdf->extra = NULL;
bsdf->alpha_x = saturatef(bsdf->alpha_x);
bsdf->alpha_y = bsdf->alpha_x;
bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID;
return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_HAS_TRANSMISSION;
}
ccl_device void bsdf_microfacet_ggx_blur(ccl_private ShaderClosure *sc, float roughness)
{
ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)sc;
@ -577,10 +662,12 @@ ccl_device Spectrum bsdf_microfacet_ggx_eval(ccl_private const ShaderClosure *sc
}
ccl_device int bsdf_microfacet_ggx_sample(ccl_private const ShaderClosure *sc,
const int path_flag,
float3 Ng,
float3 wi,
float randu,
float randv,
float randw,
ccl_private Spectrum *eval,
ccl_private float3 *wo,
ccl_private float *pdf,
@ -588,7 +675,7 @@ ccl_device int bsdf_microfacet_ggx_sample(ccl_private const ShaderClosure *sc,
ccl_private float *eta)
{
return bsdf_microfacet_sample<MicrofacetType::GGX>(
sc, Ng, wi, randu, randv, eval, wo, pdf, sampled_roughness, eta);
sc, path_flag, Ng, wi, randu, randv, randw, eval, wo, pdf, sampled_roughness, eta);
}
/* Beckmann microfacet with Smith shadow-masking from:
@ -614,6 +701,15 @@ ccl_device int bsdf_microfacet_beckmann_refraction_setup(ccl_private MicrofacetB
return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_HAS_TRANSMISSION;
}
ccl_device int bsdf_microfacet_beckmann_glass_setup(ccl_private MicrofacetBsdf *bsdf)
{
bsdf->alpha_x = saturatef(bsdf->alpha_x);
bsdf->alpha_y = bsdf->alpha_x;
bsdf->type = CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID;
return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_HAS_TRANSMISSION;
}
ccl_device void bsdf_microfacet_beckmann_blur(ccl_private ShaderClosure *sc, float roughness)
{
ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)sc;
@ -632,10 +728,12 @@ ccl_device Spectrum bsdf_microfacet_beckmann_eval(ccl_private const ShaderClosur
}
ccl_device int bsdf_microfacet_beckmann_sample(ccl_private const ShaderClosure *sc,
const int path_flag,
float3 Ng,
float3 wi,
float randu,
float randv,
float randw,
ccl_private Spectrum *eval,
ccl_private float3 *wo,
ccl_private float *pdf,
@ -643,7 +741,60 @@ ccl_device int bsdf_microfacet_beckmann_sample(ccl_private const ShaderClosure *
ccl_private float *eta)
{
return bsdf_microfacet_sample<MicrofacetType::BECKMANN>(
sc, Ng, wi, randu, randv, eval, wo, pdf, sampled_roughness, eta);
sc, path_flag, Ng, wi, randu, randv, randw, eval, wo, pdf, sampled_roughness, eta);
}
/* Specular interface, not really a microfacet model but close enough that sharing code makes
* sense. */
ccl_device int bsdf_reflection_setup(ccl_private MicrofacetBsdf *bsdf)
{
bsdf->type = CLOSURE_BSDF_REFLECTION_ID;
bsdf->alpha_x = 0.0f;
bsdf->alpha_y = 0.0f;
return SD_BSDF;
}
ccl_device int bsdf_refraction_setup(ccl_private MicrofacetBsdf *bsdf)
{
bsdf->type = CLOSURE_BSDF_REFRACTION_ID;
bsdf->alpha_x = 0.0f;
bsdf->alpha_y = 0.0f;
return SD_BSDF | SD_BSDF_HAS_TRANSMISSION;
}
ccl_device int bsdf_sharp_glass_setup(ccl_private MicrofacetBsdf *bsdf)
{
bsdf->type = CLOSURE_BSDF_SHARP_GLASS_ID;
bsdf->alpha_x = 0.0f;
bsdf->alpha_y = 0.0f;
return SD_BSDF | SD_BSDF_HAS_TRANSMISSION;
}
ccl_device Spectrum bsdf_microfacet_sharp_eval(ccl_private const ShaderClosure *sc,
const float3 Ng,
const float3 wi,
const float3 wo,
ccl_private float *pdf)
{
return bsdf_microfacet_eval<MicrofacetType::SHARP>(sc, Ng, wi, wo, pdf);
}
ccl_device int bsdf_microfacet_sharp_sample(ccl_private const ShaderClosure *sc,
const int path_flag,
float3 Ng,
float3 wi,
float randu,
float randv,
float randw,
ccl_private Spectrum *eval,
ccl_private float3 *wo,
ccl_private float *pdf,
ccl_private float2 *sampled_roughness,
ccl_private float *eta)
{
return bsdf_microfacet_sample<MicrofacetType::SHARP>(
sc, path_flag, Ng, wi, randu, randv, randw, eval, wo, pdf, sampled_roughness, eta);
}
CCL_NAMESPACE_END

View File

@ -640,14 +640,14 @@ ccl_device int bsdf_microfacet_multi_ggx_glass_sample(KernelGlobals kg,
*sampled_roughness = make_float2(bsdf->alpha_x, bsdf->alpha_y);
if (bsdf->alpha_x * bsdf->alpha_y < 1e-7f) {
float3 R, T;
float3 T;
bool inside;
float fresnel = fresnel_dielectric(bsdf->ior, Z, wi, &R, &T, &inside);
float fresnel = fresnel_dielectric(bsdf->ior, Z, wi, &T, &inside);
*pdf = 1e6f;
*eval = make_spectrum(1e6f);
if (randu < fresnel) {
*wo = R;
*wo = 2 * dot(Z, wi) * Z - wi;
return LABEL_REFLECT | LABEL_SINGULAR;
}
else {

View File

@ -1,61 +0,0 @@
/* SPDX-License-Identifier: BSD-3-Clause
*
* Adapted from Open Shading Language
* Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
* All Rights Reserved.
*
* Modifications Copyright 2011-2022 Blender Foundation. */
#pragma once
CCL_NAMESPACE_BEGIN
/* REFLECTION */
ccl_device int bsdf_reflection_setup(ccl_private MicrofacetBsdf *bsdf)
{
bsdf->type = CLOSURE_BSDF_REFLECTION_ID;
return SD_BSDF;
}
ccl_device Spectrum bsdf_reflection_eval(ccl_private const ShaderClosure *sc,
const float3 wi,
const float3 wo,
ccl_private float *pdf)
{
*pdf = 0.0f;
return zero_spectrum();
}
ccl_device int bsdf_reflection_sample(ccl_private const ShaderClosure *sc,
float3 Ng,
float3 wi,
float randu,
float randv,
ccl_private Spectrum *eval,
ccl_private float3 *wo,
ccl_private float *pdf,
ccl_private float *eta)
{
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
float3 N = bsdf->N;
*eta = bsdf->ior;
// only one direction is possible
float cosNI = dot(N, wi);
if (cosNI > 0) {
*wo = (2 * cosNI) * N - wi;
if (dot(Ng, *wo) > 0) {
/* Some high number for MIS. */
*pdf = 1e6f;
*eval = make_spectrum(1e6f);
}
}
else {
*pdf = 0.0f;
*eval = zero_spectrum();
}
return LABEL_REFLECT | LABEL_SINGULAR;
}
CCL_NAMESPACE_END

View File

@ -1,64 +0,0 @@
/* SPDX-License-Identifier: BSD-3-Clause
*
* Adapted from Open Shading Language
* Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
* All Rights Reserved.
*
* Modifications Copyright 2011-2022 Blender Foundation. */
#pragma once
CCL_NAMESPACE_BEGIN
/* REFRACTION */
ccl_device int bsdf_refraction_setup(ccl_private MicrofacetBsdf *bsdf)
{
bsdf->type = CLOSURE_BSDF_REFRACTION_ID;
return SD_BSDF;
}
ccl_device Spectrum bsdf_refraction_eval(ccl_private const ShaderClosure *sc,
const float3 wi,
const float3 wo,
ccl_private float *pdf)
{
*pdf = 0.0f;
return zero_spectrum();
}
ccl_device int bsdf_refraction_sample(ccl_private const ShaderClosure *sc,
float3 Ng,
float3 wi,
float randu,
float randv,
ccl_private Spectrum *eval,
ccl_private float3 *wo,
ccl_private float *pdf,
ccl_private float *eta)
{
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
float m_eta = bsdf->ior;
*eta = 1.0f / m_eta;
float3 N = bsdf->N;
float3 R, T;
bool inside;
float fresnel;
fresnel = fresnel_dielectric(m_eta, N, wi, &R, &T, &inside);
if (!inside && fresnel != 1.0f) {
/* Some high number for MIS. */
*pdf = 1e6f;
*eval = make_spectrum(1e6f);
*wo = T;
}
else {
*pdf = 0.0f;
*eval = zero_spectrum();
}
return LABEL_TRANSMIT | LABEL_SINGULAR;
}
CCL_NAMESPACE_END

View File

@ -10,12 +10,8 @@
CCL_NAMESPACE_BEGIN
ccl_device float fresnel_dielectric(float eta,
const float3 N,
const float3 I,
ccl_private float3 *R,
ccl_private float3 *T,
ccl_private bool *is_inside)
ccl_device float fresnel_dielectric(
float eta, const float3 N, const float3 I, ccl_private float3 *T, ccl_private bool *is_inside)
{
float cos = dot(N, I), neta;
float3 Nn;
@ -35,9 +31,6 @@ ccl_device float fresnel_dielectric(float eta,
*is_inside = true;
}
// compute reflection
*R = (2 * cos) * Nn - I;
float arg = 1 - (neta * neta * (1 - (cos * cos)));
if (arg < 0) {
*T = make_float3(0.0f, 0.0f, 0.0f);

View File

@ -975,20 +975,13 @@ ccl_device_forceinline int kernel_path_mnee_sample(KernelGlobals kg,
kg, state, sd_mnee, NULL, PATH_RAY_DIFFUSE, true);
/* Get and sample refraction bsdf */
bool found_transimissive_microfacet_bsdf = false;
bool found_refractive_microfacet_bsdf = false;
for (int ci = 0; ci < sd_mnee->num_closure; ci++) {
ccl_private ShaderClosure *bsdf = &sd_mnee->closure[ci];
if (bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID ||
bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID ||
bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID ||
bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID ||
bsdf->type == CLOSURE_BSDF_REFRACTION_ID ||
bsdf->type == CLOSURE_BSDF_SHARP_GLASS_ID) {
/* Note that CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID and
* CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID are treated as
* CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID further below. */
if (CLOSURE_IS_REFRACTIVE(bsdf->type)) {
/* Note that Glass closures are treates as refractive further below. */
found_transimissive_microfacet_bsdf = true;
found_refractive_microfacet_bsdf = true;
ccl_private MicrofacetBsdf *microfacet_bsdf = (ccl_private MicrofacetBsdf *)bsdf;
/* Figure out appropriate index of refraction ratio. */
@ -1011,7 +1004,7 @@ ccl_device_forceinline int kernel_path_mnee_sample(KernelGlobals kg,
break;
}
}
if (!found_transimissive_microfacet_bsdf)
if (!found_refractive_microfacet_bsdf)
return 0;
}

View File

@ -348,7 +348,7 @@ ccl_device_forceinline int integrate_surface_bsdf_bssrdf_bounce(
return LABEL_NONE;
}
float2 rand_bsdf = path_state_rng_2D(kg, rng_state, PRNG_SURFACE_BSDF);
float3 rand_bsdf = path_state_rng_3D(kg, rng_state, PRNG_SURFACE_BSDF);
ccl_private const ShaderClosure *sc = surface_shader_bsdf_bssrdf_pick(sd, &rand_bsdf);
#ifdef __SUBSURFACE__
@ -393,6 +393,7 @@ ccl_device_forceinline int integrate_surface_bsdf_bssrdf_bounce(
label = surface_shader_bsdf_sample_closure(kg,
sd,
sc,
INTEGRATOR_STATE(state, path, flag),
rand_bsdf,
&bsdf_eval,
&bsdf_wo,

View File

@ -334,7 +334,7 @@ ccl_device_inline
/* Randomly sample a BSSRDF or BSDF proportional to ShaderClosure.sample_weight. */
ccl_device_inline ccl_private const ShaderClosure *surface_shader_bsdf_bssrdf_pick(
ccl_private const ShaderData *ccl_restrict sd, ccl_private float2 *rand_bsdf)
ccl_private const ShaderData *ccl_restrict sd, ccl_private float3 *rand_bsdf)
{
int sampled = 0;
@ -350,7 +350,7 @@ ccl_device_inline ccl_private const ShaderClosure *surface_shader_bsdf_bssrdf_pi
}
}
float r = (*rand_bsdf).x * sum;
float r = (*rand_bsdf).z * sum;
float partial_sum = 0.0f;
for (int i = 0; i < sd->num_closure; i++) {
@ -363,7 +363,7 @@ ccl_device_inline ccl_private const ShaderClosure *surface_shader_bsdf_bssrdf_pi
sampled = i;
/* Rescale to reuse for direction sample, to better preserve stratification. */
(*rand_bsdf).x = (r - partial_sum) / sc->sample_weight;
(*rand_bsdf).z = (r - partial_sum) / sc->sample_weight;
break;
}
@ -405,7 +405,7 @@ ccl_device int surface_shader_bsdf_guided_sample_closure(KernelGlobals kg,
IntegratorState state,
ccl_private ShaderData *sd,
ccl_private const ShaderClosure *sc,
const float2 rand_bsdf,
const float3 rand_bsdf,
ccl_private BsdfEval *bsdf_eval,
ccl_private float3 *wo,
ccl_private float *bsdf_pdf,
@ -443,7 +443,7 @@ ccl_device int surface_shader_bsdf_guided_sample_closure(KernelGlobals kg,
if (sample_guiding) {
/* Sample guiding distribution. */
guide_pdf = guiding_bsdf_sample(kg, state, rand_bsdf, wo);
guide_pdf = guiding_bsdf_sample(kg, state, float3_to_float2(rand_bsdf), wo);
*bsdf_pdf = 0.0f;
if (guide_pdf != 0.0f) {
@ -483,8 +483,16 @@ ccl_device int surface_shader_bsdf_guided_sample_closure(KernelGlobals kg,
else {
/* Sample BSDF. */
*bsdf_pdf = 0.0f;
label = bsdf_sample(
kg, sd, sc, rand_bsdf.x, rand_bsdf.y, &eval, wo, unguided_bsdf_pdf, sampled_rougness, eta);
label = bsdf_sample(kg,
sd,
sc,
INTEGRATOR_STATE(state, path, flag),
rand_bsdf,
&eval,
wo,
unguided_bsdf_pdf,
sampled_rougness,
eta);
# if 0
if (*unguided_bsdf_pdf > 0.0f) {
surface_shader_validate_bsdf_sample(kg, sc, *wo, label, sampled_roughness, eta);
@ -523,7 +531,8 @@ ccl_device int surface_shader_bsdf_guided_sample_closure(KernelGlobals kg,
ccl_device int surface_shader_bsdf_sample_closure(KernelGlobals kg,
ccl_private ShaderData *sd,
ccl_private const ShaderClosure *sc,
const float2 rand_bsdf,
const int path_flag,
const float3 rand_bsdf,
ccl_private BsdfEval *bsdf_eval,
ccl_private float3 *wo,
ccl_private float *pdf,
@ -537,8 +546,7 @@ ccl_device int surface_shader_bsdf_sample_closure(KernelGlobals kg,
Spectrum eval = zero_spectrum();
*pdf = 0.0f;
label = bsdf_sample(
kg, sd, sc, rand_bsdf.x, rand_bsdf.y, &eval, wo, pdf, sampled_roughness, eta);
label = bsdf_sample(kg, sd, sc, path_flag, rand_bsdf, &eval, wo, pdf, sampled_roughness, eta);
if (*pdf != 0.0f) {
bsdf_eval_init(bsdf_eval, sc->type, eval * sc->weight);

View File

@ -16,8 +16,6 @@
#include "kernel/closure/bsdf_microfacet.h"
#include "kernel/closure/bsdf_microfacet_multi.h"
#include "kernel/closure/bsdf_oren_nayar.h"
#include "kernel/closure/bsdf_reflection.h"
#include "kernel/closure/bsdf_refraction.h"
#include "kernel/closure/bsdf_transparent.h"
#include "kernel/closure/bsdf_ashikhmin_shirley.h"
#include "kernel/closure/bsdf_toon.h"
@ -205,23 +203,44 @@ ccl_device void osl_closure_microfacet_setup(KernelGlobals kg,
bsdf->ior = closure->ior;
bsdf->T = closure->T;
/* GGX */
if (closure->distribution == make_string("ggx", 11253504724482777663ull) ||
closure->distribution == make_string("default", 4430693559278735917ull)) {
if (!closure->refract) {
sd->flag |= bsdf_microfacet_ggx_setup(bsdf);
/* Beckmann */
if (closure->distribution == make_string("beckmann", 14712237670914973463ull)) {
if (closure->refract == 1) {
sd->flag |= bsdf_microfacet_beckmann_refraction_setup(bsdf);
}
else if (closure->refract == 2) {
sd->flag |= bsdf_microfacet_beckmann_glass_setup(bsdf);
}
else {
sd->flag |= bsdf_microfacet_ggx_refraction_setup(bsdf);
}
}
/* Beckmann */
else {
if (!closure->refract) {
sd->flag |= bsdf_microfacet_beckmann_setup(bsdf);
}
}
/* Sharp */
else if (closure->distribution == make_string("sharp", 1870681295563127462ull)) {
if (closure->refract == 1) {
sd->flag |= bsdf_refraction_setup(bsdf);
}
else if (closure->refract == 2) {
sd->flag |= bsdf_sharp_glass_setup(bsdf);
}
else {
sd->flag |= bsdf_microfacet_beckmann_refraction_setup(bsdf);
sd->flag |= bsdf_reflection_setup(bsdf);
}
}
/* Ashikhmin-Shirley */
else if (closure->distribution == make_string("ashikhmin_shirley", 11318482998918370922ull)) {
sd->flag |= bsdf_ashikhmin_shirley_setup(bsdf);
}
/* GGX */
else {
if (closure->refract == 1) {
sd->flag |= bsdf_microfacet_ggx_refraction_setup(bsdf);
}
else if (closure->refract == 2) {
sd->flag |= bsdf_microfacet_ggx_glass_setup(bsdf);
}
else {
sd->flag |= bsdf_microfacet_ggx_setup(bsdf);
}
}
}

View File

@ -13,18 +13,10 @@ shader node_glass_bsdf(color Color = 0.8,
{
float f = max(IOR, 1e-5);
float eta = backfacing() ? 1.0 / f : f;
float cosi = dot(I, Normal);
float Fr = fresnel_dielectric_cos(cosi, eta);
float roughness = Roughness * Roughness;
if (distribution == "sharp")
BSDF = Color * (Fr * reflection(Normal) + (1.0 - Fr) * refraction(Normal, eta));
else if (distribution == "beckmann")
BSDF = Color * (Fr * microfacet_beckmann(Normal, roughness) +
(1.0 - Fr) * microfacet_beckmann_refraction(Normal, roughness, eta));
else if (distribution == "Multiscatter GGX")
if (distribution == "Multiscatter GGX")
BSDF = Color * microfacet_multi_ggx_glass(Normal, roughness, eta, Color);
else if (distribution == "GGX")
BSDF = Color * (Fr * microfacet_ggx(Normal, roughness) +
(1.0 - Fr) * microfacet_ggx_refraction(Normal, roughness, eta));
else
BSDF = Color * microfacet(distribution, Normal, roughness, eta, 2);
}

View File

@ -5,21 +5,15 @@
#include "stdcycles.h"
shader node_glossy_bsdf(color Color = 0.8,
string distribution = "GGX",
string distribution = "ggx",
float Roughness = 0.2,
normal Normal = N,
output closure color BSDF = 0)
{
float roughness = Roughness * Roughness;
if (distribution == "sharp")
BSDF = Color * reflection(Normal);
else if (distribution == "beckmann")
BSDF = Color * microfacet_beckmann(Normal, roughness);
else if (distribution == "GGX")
BSDF = Color * microfacet_ggx(Normal, roughness);
else if (distribution == "Multiscatter GGX")
if (distribution == "Multiscatter GGX")
BSDF = Color * microfacet_multi_ggx(Normal, roughness, Color);
else
BSDF = Color * ashikhmin_shirley(Normal, vector(0, 0, 0), roughness, roughness);
BSDF = Color * microfacet(distribution, Normal, roughness, 0.0, 0);
}

View File

@ -14,10 +14,5 @@ shader node_refraction_bsdf(color Color = 0.8,
float eta = backfacing() ? 1.0 / f : f;
float roughness = Roughness * Roughness;
if (distribution == "sharp")
BSDF = Color * refraction(Normal, eta);
else if (distribution == "beckmann")
BSDF = Color * microfacet_beckmann_refraction(Normal, roughness, eta);
else if (distribution == "GGX")
BSDF = Color * microfacet_ggx_refraction(Normal, roughness, eta);
BSDF = microfacet(distribution, Normal, roughness, eta, 1);
}

View File

@ -14,49 +14,6 @@ CCL_NAMESPACE_BEGIN
/* Closure Nodes */
ccl_device void svm_node_glass_setup(ccl_private ShaderData *sd,
ccl_private MicrofacetBsdf *bsdf,
int type,
float eta,
float roughness,
bool refract)
{
if (type == CLOSURE_BSDF_SHARP_GLASS_ID) {
if (refract) {
bsdf->alpha_y = 0.0f;
bsdf->alpha_x = 0.0f;
bsdf->ior = eta;
sd->flag |= bsdf_refraction_setup(bsdf);
}
else {
bsdf->alpha_y = 0.0f;
bsdf->alpha_x = 0.0f;
bsdf->ior = eta;
sd->flag |= bsdf_reflection_setup(bsdf);
}
}
else if (type == CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID) {
bsdf->alpha_x = roughness;
bsdf->alpha_y = roughness;
bsdf->ior = eta;
if (refract)
sd->flag |= bsdf_microfacet_beckmann_refraction_setup(bsdf);
else
sd->flag |= bsdf_microfacet_beckmann_setup(bsdf);
}
else {
bsdf->alpha_x = roughness;
bsdf->alpha_y = roughness;
bsdf->ior = eta;
if (refract)
sd->flag |= bsdf_microfacet_ggx_refraction_setup(bsdf);
else
sd->flag |= bsdf_microfacet_ggx_setup(bsdf);
}
}
ccl_device_inline int svm_node_closure_bsdf_skip(KernelGlobals kg, int offset, uint type)
{
if (type == CLOSURE_BSDF_PRINCIPLED_ID) {
@ -627,52 +584,39 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
case CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID: {
#ifdef __CAUSTICS_TRICKS__
if (!kernel_data.integrator.caustics_reflective &&
!kernel_data.integrator.caustics_refractive && (path_flag & PATH_RAY_DIFFUSE)) {
!kernel_data.integrator.caustics_refractive && (path_flag & PATH_RAY_DIFFUSE))
break;
}
#endif
Spectrum weight = sd->svm_closure_weight * mix_weight;
ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
sd, sizeof(MicrofacetBsdf), weight);
/* index of refraction */
float eta = fmaxf(param2, 1e-5f);
eta = (sd->flag & SD_BACKFACING) ? 1.0f / eta : eta;
if (bsdf) {
bsdf->N = N;
bsdf->T = zero_float3();
bsdf->extra = NULL;
/* fresnel */
float cosNI = dot(N, sd->wi);
float fresnel = fresnel_dielectric_cos(cosNI, eta);
float roughness = sqr(param1);
float eta = fmaxf(param2, 1e-5f);
eta = (sd->flag & SD_BACKFACING) ? 1.0f / eta : eta;
/* reflection */
#ifdef __CAUSTICS_TRICKS__
if (kernel_data.integrator.caustics_reflective || (path_flag & PATH_RAY_DIFFUSE) == 0)
#endif
{
ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
sd, sizeof(MicrofacetBsdf), weight * fresnel);
/* setup bsdf */
if (type == CLOSURE_BSDF_SHARP_GLASS_ID) {
bsdf->alpha_x = 0.0f;
bsdf->alpha_y = 0.0f;
bsdf->ior = eta;
if (bsdf) {
bsdf->N = N;
bsdf->T = zero_float3();
bsdf->extra = NULL;
svm_node_glass_setup(sd, bsdf, type, eta, roughness, false);
sd->flag |= bsdf_sharp_glass_setup(bsdf);
}
}
else {
float roughness = sqr(param1);
bsdf->alpha_x = roughness;
bsdf->alpha_y = roughness;
bsdf->ior = eta;
/* refraction */
#ifdef __CAUSTICS_TRICKS__
if (kernel_data.integrator.caustics_refractive || (path_flag & PATH_RAY_DIFFUSE) == 0)
#endif
{
/* This is to prevent MNEE from receiving a null BSDF. */
float refraction_fresnel = fmaxf(0.0001f, 1.0f - fresnel);
ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
sd, sizeof(MicrofacetBsdf), weight * refraction_fresnel);
if (bsdf) {
bsdf->N = N;
bsdf->T = zero_float3();
bsdf->extra = NULL;
svm_node_glass_setup(sd, bsdf, type, eta, roughness, true);
if (type == CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID)
sd->flag |= bsdf_microfacet_beckmann_glass_setup(bsdf);
else
sd->flag |= bsdf_microfacet_ggx_glass_setup(bsdf);
}
}

View File

@ -436,11 +436,11 @@ typedef enum ClosureType {
CLOSURE_BSDF_REFRACTION_ID,
CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID,
CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID,
CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID,
CLOSURE_BSDF_SHARP_GLASS_ID,
CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID,
CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID,
CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID,
CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID,
CLOSURE_BSDF_SHARP_GLASS_ID,
CLOSURE_BSDF_HAIR_PRINCIPLED_ID,
CLOSURE_BSDF_HAIR_TRANSMISSION_ID,
@ -484,11 +484,9 @@ typedef enum ClosureType {
#define CLOSURE_IS_BSDF_MICROFACET(type) \
((type >= CLOSURE_BSDF_MICROFACET_GGX_ID && type <= CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID) || \
(type >= CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID && \
type <= CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID) || \
(type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID))
type <= CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID))
#define CLOSURE_IS_BSDF_MICROFACET_FRESNEL(type) \
(type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID || \
type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID || \
type == CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID)
#define CLOSURE_IS_BSDF_OR_BSSRDF(type) (type <= CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID)
#define CLOSURE_IS_BSSRDF(type) \
@ -499,8 +497,12 @@ typedef enum ClosureType {
#define CLOSURE_IS_VOLUME_ABSORPTION(type) (type == CLOSURE_VOLUME_ABSORPTION_ID)
#define CLOSURE_IS_HOLDOUT(type) (type == CLOSURE_HOLDOUT_ID)
#define CLOSURE_IS_PHASE(type) (type == CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID)
#define CLOSURE_IS_REFRACTIVE(type) \
(type >= CLOSURE_BSDF_REFRACTION_ID && \
type <= CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID)
#define CLOSURE_IS_GLASS(type) \
(type >= CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID && type <= CLOSURE_BSDF_SHARP_GLASS_ID)
(type >= CLOSURE_BSDF_SHARP_GLASS_ID && \
type <= CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID)
#define CLOSURE_IS_PRINCIPLED(type) (type == CLOSURE_BSDF_PRINCIPLED_ID)
#define CLOSURE_WEIGHT_CUTOFF 1e-5f

View File

@ -1126,9 +1126,6 @@ int ShaderGraph::get_num_closures()
else if (CLOSURE_IS_BSSRDF(closure_type)) {
num_closures += 3;
}
else if (CLOSURE_IS_GLASS(closure_type)) {
num_closures += 2;
}
else if (CLOSURE_IS_BSDF_MULTISCATTER(closure_type)) {
num_closures += 2;
}

View File

@ -2417,7 +2417,7 @@ NODE_DEFINE(GlossyBsdfNode)
static NodeEnum distribution_enum;
distribution_enum.insert("sharp", CLOSURE_BSDF_REFLECTION_ID);
distribution_enum.insert("beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_ID);
distribution_enum.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_ID);
distribution_enum.insert("ggx", CLOSURE_BSDF_MICROFACET_GGX_ID);
distribution_enum.insert("ashikhmin_shirley", CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID);
distribution_enum.insert("Multiscatter GGX", CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID);
SOCKET_ENUM(distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_GGX_ID);
@ -2509,7 +2509,7 @@ NODE_DEFINE(GlassBsdfNode)
static NodeEnum distribution_enum;
distribution_enum.insert("sharp", CLOSURE_BSDF_SHARP_GLASS_ID);
distribution_enum.insert("beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID);
distribution_enum.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID);
distribution_enum.insert("ggx", CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID);
distribution_enum.insert("Multiscatter GGX", CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID);
SOCKET_ENUM(
distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID);
@ -2602,7 +2602,7 @@ NODE_DEFINE(RefractionBsdfNode)
static NodeEnum distribution_enum;
distribution_enum.insert("sharp", CLOSURE_BSDF_REFRACTION_ID);
distribution_enum.insert("beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID);
distribution_enum.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID);
distribution_enum.insert("ggx", CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID);
SOCKET_ENUM(
distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID);

View File

@ -503,6 +503,11 @@ ccl_device_inline float3 float2_to_float3(const float2 a)
return make_float3(a.x, a.y, 0.0f);
}
ccl_device_inline float2 float3_to_float2(const float3 a)
{
return make_float2(a.x, a.y);
}
ccl_device_inline float3 float4_to_float3(const float4 a)
{
return make_float3(a.x, a.y, a.z);