Cycles: BSDF eval refactor to remove separate reflection/refraction methods

Simplifies code overall to do it inside the eval function, most of the BSDFs
already compute the dot product.

The refactoring in bsdf_principled_hair_eval() was needed to avoid a HIP
compiler bug. Cause is unclear, just changing the implementation enough
is meant to sidestep it.

Ref T92571, D15286
This commit is contained in:
Brecht Van Lommel 2022-09-22 20:03:24 +02:00
parent bd249eb4f3
commit 6d19da0b2d
Notes: blender-bot 2023-02-13 17:18:35 +01:00
Referenced by issue #92571, Cycles: path guiding
20 changed files with 688 additions and 924 deletions

View File

@ -69,7 +69,11 @@ ccl_device_inline float bsdf_get_roughness_squared(ccl_private const ShaderClosu
* Yining Karl Li and Brent Burley. */
ccl_device_inline float bump_shadowing_term(float3 Ng, float3 N, float3 I)
{
float g = safe_divide(dot(Ng, I), dot(N, I) * dot(Ng, N));
const float cosNI = dot(N, I);
if (cosNI < 0.0f) {
Ng = -Ng;
}
float g = safe_divide(dot(Ng, I), cosNI * dot(Ng, N));
/* If the incoming light is on the unshadowed side, return full brightness. */
if (g >= 1.0f) {
@ -98,6 +102,12 @@ ccl_device_inline float shift_cos_in(float cos_in, const float frequency_multipl
return val;
}
ccl_device_inline bool bsdf_is_transmission(ccl_private const ShaderClosure *sc,
const float3 omega_in)
{
return dot(sc->N, omega_in) < 0.0f;
}
ccl_device_inline int bsdf_sample(KernelGlobals kg,
ccl_private ShaderData *sd,
ccl_private const ShaderClosure *sc,
@ -264,11 +274,12 @@ ccl_device_inline int bsdf_sample(KernelGlobals kg,
const float frequency_multiplier =
kernel_data_fetch(objects, sd->object).shadow_terminator_shading_offset;
if (frequency_multiplier > 1.0f) {
*eval *= shift_cos_in(dot(*omega_in, sc->N), frequency_multiplier);
const float cosNI = dot(*omega_in, sc->N);
*eval *= shift_cos_in(cosNI, frequency_multiplier);
}
if (label & LABEL_DIFFUSE) {
if (!isequal(sc->N, sd->N)) {
*eval *= bump_shadowing_term((label & LABEL_TRANSMIT) ? -sd->N : sd->N, sc->N, *omega_in);
*eval *= bump_shadowing_term(sd->N, sc->N, *omega_in);
}
}
}
@ -491,7 +502,7 @@ ccl_device_inline int bsdf_label(const KernelGlobals kg,
label = LABEL_TRANSMIT | LABEL_GLOSSY;
break;
case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
if (is_transmission)
if (bsdf_is_transmission(sc, omega_in))
label = LABEL_TRANSMIT | LABEL_GLOSSY;
else
label = LABEL_REFLECT | LABEL_GLOSSY;
@ -531,179 +542,104 @@ ccl_device_inline
ccl_private ShaderData *sd,
ccl_private const ShaderClosure *sc,
const float3 omega_in,
const bool is_transmission,
ccl_private float *pdf)
{
Spectrum eval = zero_spectrum();
if (!is_transmission) {
switch (sc->type) {
case CLOSURE_BSDF_DIFFUSE_ID:
eval = bsdf_diffuse_eval_reflect(sc, sd->I, omega_in, pdf);
break;
switch (sc->type) {
case CLOSURE_BSDF_DIFFUSE_ID:
eval = bsdf_diffuse_eval(sc, sd->I, omega_in, pdf);
break;
#if defined(__SVM__) || defined(__OSL__)
case CLOSURE_BSDF_OREN_NAYAR_ID:
eval = bsdf_oren_nayar_eval_reflect(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_OREN_NAYAR_ID:
eval = bsdf_oren_nayar_eval(sc, sd->I, omega_in, pdf);
break;
# ifdef __OSL__
case CLOSURE_BSDF_PHONG_RAMP_ID:
eval = bsdf_phong_ramp_eval_reflect(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_DIFFUSE_RAMP_ID:
eval = bsdf_diffuse_ramp_eval_reflect(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_PHONG_RAMP_ID:
eval = bsdf_phong_ramp_eval(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_DIFFUSE_RAMP_ID:
eval = bsdf_diffuse_ramp_eval(sc, sd->I, omega_in, pdf);
break;
# endif
case CLOSURE_BSDF_TRANSLUCENT_ID:
eval = bsdf_translucent_eval_reflect(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_REFLECTION_ID:
eval = bsdf_reflection_eval_reflect(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_REFRACTION_ID:
eval = bsdf_refraction_eval_reflect(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_TRANSPARENT_ID:
eval = bsdf_transparent_eval_reflect(sc, sd->I, omega_in, 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:
eval = bsdf_microfacet_ggx_eval_reflect(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
eval = bsdf_microfacet_multi_ggx_eval_reflect(sc, sd->I, omega_in, pdf, &sd->lcg_state);
break;
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
eval = bsdf_microfacet_multi_ggx_glass_eval_reflect(
sc, sd->I, omega_in, pdf, &sd->lcg_state);
break;
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
eval = bsdf_microfacet_beckmann_eval_reflect(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
eval = bsdf_ashikhmin_shirley_eval_reflect(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
eval = bsdf_ashikhmin_velvet_eval_reflect(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_DIFFUSE_TOON_ID:
eval = bsdf_diffuse_toon_eval_reflect(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_GLOSSY_TOON_ID:
eval = bsdf_glossy_toon_eval_reflect(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
eval = bsdf_principled_hair_eval(kg, sd, sc, omega_in, pdf);
break;
case CLOSURE_BSDF_HAIR_REFLECTION_ID:
eval = bsdf_hair_reflection_eval_reflect(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
eval = bsdf_hair_transmission_eval_reflect(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
eval = bsdf_principled_diffuse_eval_reflect(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
eval = bsdf_principled_sheen_eval_reflect(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_TRANSLUCENT_ID:
eval = bsdf_translucent_eval(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_REFLECTION_ID:
eval = bsdf_reflection_eval(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_REFRACTION_ID:
eval = bsdf_refraction_eval(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_TRANSPARENT_ID:
eval = bsdf_transparent_eval(sc, sd->I, omega_in, 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:
eval = bsdf_microfacet_ggx_eval(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
eval = bsdf_microfacet_multi_ggx_eval(sc, sd->I, omega_in, pdf, &sd->lcg_state);
break;
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
eval = bsdf_microfacet_multi_ggx_glass_eval(sc, sd->I, omega_in, pdf, &sd->lcg_state);
break;
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
eval = bsdf_microfacet_beckmann_eval(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
eval = bsdf_ashikhmin_shirley_eval(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
eval = bsdf_ashikhmin_velvet_eval(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_DIFFUSE_TOON_ID:
eval = bsdf_diffuse_toon_eval(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_GLOSSY_TOON_ID:
eval = bsdf_glossy_toon_eval(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
eval = bsdf_principled_hair_eval(kg, sd, sc, omega_in, pdf);
break;
case CLOSURE_BSDF_HAIR_REFLECTION_ID:
eval = bsdf_hair_reflection_eval(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
eval = bsdf_hair_transmission_eval(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
eval = bsdf_principled_diffuse_eval(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
eval = bsdf_principled_sheen_eval(sc, sd->I, omega_in, pdf);
break;
#endif
default:
break;
}
if (CLOSURE_IS_BSDF_DIFFUSE(sc->type)) {
if (!isequal(sc->N, sd->N)) {
eval *= bump_shadowing_term(sd->N, sc->N, omega_in);
}
}
/* Shadow terminator offset. */
const float frequency_multiplier =
kernel_data_fetch(objects, sd->object).shadow_terminator_shading_offset;
if (frequency_multiplier > 1.0f) {
eval *= shift_cos_in(dot(omega_in, sc->N), frequency_multiplier);
default:
break;
}
if (CLOSURE_IS_BSDF_DIFFUSE(sc->type)) {
if (!isequal(sc->N, sd->N)) {
eval *= bump_shadowing_term(sd->N, sc->N, omega_in);
}
}
else {
switch (sc->type) {
case CLOSURE_BSDF_DIFFUSE_ID:
eval = bsdf_diffuse_eval_transmit(sc, sd->I, omega_in, pdf);
break;
#if defined(__SVM__) || defined(__OSL__)
case CLOSURE_BSDF_OREN_NAYAR_ID:
eval = bsdf_oren_nayar_eval_transmit(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_TRANSLUCENT_ID:
eval = bsdf_translucent_eval_transmit(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_REFLECTION_ID:
eval = bsdf_reflection_eval_transmit(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_REFRACTION_ID:
eval = bsdf_refraction_eval_transmit(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_TRANSPARENT_ID:
eval = bsdf_transparent_eval_transmit(sc, sd->I, omega_in, 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:
eval = bsdf_microfacet_ggx_eval_transmit(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
eval = bsdf_microfacet_multi_ggx_eval_transmit(sc, sd->I, omega_in, pdf, &sd->lcg_state);
break;
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
eval = bsdf_microfacet_multi_ggx_glass_eval_transmit(
sc, sd->I, omega_in, pdf, &sd->lcg_state);
break;
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
eval = bsdf_microfacet_beckmann_eval_transmit(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
eval = bsdf_ashikhmin_shirley_eval_transmit(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
eval = bsdf_ashikhmin_velvet_eval_transmit(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_DIFFUSE_TOON_ID:
eval = bsdf_diffuse_toon_eval_transmit(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_GLOSSY_TOON_ID:
eval = bsdf_glossy_toon_eval_transmit(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
eval = bsdf_principled_hair_eval(kg, sd, sc, omega_in, pdf);
break;
case CLOSURE_BSDF_HAIR_REFLECTION_ID:
eval = bsdf_hair_reflection_eval_transmit(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
eval = bsdf_hair_transmission_eval_transmit(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
eval = bsdf_principled_diffuse_eval_transmit(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
eval = bsdf_principled_sheen_eval_transmit(sc, sd->I, omega_in, pdf);
break;
#endif
default:
break;
}
if (CLOSURE_IS_BSDF_DIFFUSE(sc->type)) {
if (!isequal(sc->N, sd->N)) {
eval *= bump_shadowing_term(-sd->N, sc->N, omega_in);
}
/* Shadow terminator offset. */
const float frequency_multiplier =
kernel_data_fetch(objects, sd->object).shadow_terminator_shading_offset;
if (frequency_multiplier > 1.0f) {
const float cosNI = dot(omega_in, sc->N);
if (cosNI >= 0.0f) {
eval *= shift_cos_in(cosNI, frequency_multiplier);
}
}
#ifdef WITH_CYCLES_DEBUG
kernel_assert(*pdf >= 0.0f);
kernel_assert(eval.x >= 0.0f && eval.y >= 0.0f && eval.z >= 0.0f);

View File

@ -39,11 +39,10 @@ ccl_device_inline float bsdf_ashikhmin_shirley_roughness_to_exponent(float rough
return 2.0f / (roughness * roughness) - 2.0f;
}
ccl_device_forceinline Spectrum
bsdf_ashikhmin_shirley_eval_reflect(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
ccl_device_forceinline Spectrum bsdf_ashikhmin_shirley_eval(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
{
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
float3 N = bsdf->N;
@ -53,70 +52,60 @@ bsdf_ashikhmin_shirley_eval_reflect(ccl_private const ShaderClosure *sc,
float out = 0.0f;
if (fmaxf(bsdf->alpha_x, bsdf->alpha_y) <= 1e-4f) {
if (fmaxf(bsdf->alpha_x, bsdf->alpha_y) <= 1e-4f || !(NdotI > 0.0f && NdotO > 0.0f)) {
*pdf = 0.0f;
return zero_spectrum();
}
if (NdotI > 0.0f && NdotO > 0.0f) {
NdotI = fmaxf(NdotI, 1e-6f);
NdotO = fmaxf(NdotO, 1e-6f);
float3 H = normalize(omega_in + I);
float HdotI = fmaxf(fabsf(dot(H, I)), 1e-6f);
float HdotN = fmaxf(dot(H, N), 1e-6f);
/* pump from original paper
* (first derivative disc., but cancels the HdotI in the pdf nicely) */
float pump = 1.0f / fmaxf(1e-6f, (HdotI * fmaxf(NdotO, NdotI)));
/* pump from d-brdf paper */
/*float pump = 1.0f / fmaxf(1e-4f, ((NdotO + NdotI) * (NdotO*NdotI))); */
NdotI = fmaxf(NdotI, 1e-6f);
NdotO = fmaxf(NdotO, 1e-6f);
float3 H = normalize(omega_in + I);
float HdotI = fmaxf(fabsf(dot(H, I)), 1e-6f);
float HdotN = fmaxf(dot(H, N), 1e-6f);
float n_x = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_x);
float n_y = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_y);
/* pump from original paper
* (first derivative disc., but cancels the HdotI in the pdf nicely) */
float pump = 1.0f / fmaxf(1e-6f, (HdotI * fmaxf(NdotO, NdotI)));
/* pump from d-brdf paper */
/*float pump = 1.0f / fmaxf(1e-4f, ((NdotO + NdotI) * (NdotO*NdotI))); */
if (n_x == n_y) {
/* isotropic */
float e = n_x;
float lobe = powf(HdotN, e);
float norm = (n_x + 1.0f) / (8.0f * M_PI_F);
float n_x = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_x);
float n_y = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_y);
out = NdotO * norm * lobe * pump;
/* this is p_h / 4(H.I) (conversion from 'wh measure' to 'wi measure', eq. 8 in paper). */
*pdf = norm * lobe / HdotI;
if (n_x == n_y) {
/* isotropic */
float e = n_x;
float lobe = powf(HdotN, e);
float norm = (n_x + 1.0f) / (8.0f * M_PI_F);
out = NdotO * norm * lobe * pump;
/* this is p_h / 4(H.I) (conversion from 'wh measure' to 'wi measure', eq. 8 in paper). */
*pdf = norm * lobe / HdotI;
}
else {
/* anisotropic */
float3 X, Y;
make_orthonormals_tangent(N, bsdf->T, &X, &Y);
float HdotX = dot(H, X);
float HdotY = dot(H, Y);
float lobe;
if (HdotN < 1.0f) {
float e = (n_x * HdotX * HdotX + n_y * HdotY * HdotY) / (1.0f - HdotN * HdotN);
lobe = powf(HdotN, e);
}
else {
/* anisotropic */
float3 X, Y;
make_orthonormals_tangent(N, bsdf->T, &X, &Y);
float HdotX = dot(H, X);
float HdotY = dot(H, Y);
float lobe;
if (HdotN < 1.0f) {
float e = (n_x * HdotX * HdotX + n_y * HdotY * HdotY) / (1.0f - HdotN * HdotN);
lobe = powf(HdotN, e);
}
else {
lobe = 1.0f;
}
float norm = sqrtf((n_x + 1.0f) * (n_y + 1.0f)) / (8.0f * M_PI_F);
out = NdotO * norm * lobe * pump;
*pdf = norm * lobe / HdotI;
lobe = 1.0f;
}
float norm = sqrtf((n_x + 1.0f) * (n_y + 1.0f)) / (8.0f * M_PI_F);
out = NdotO * norm * lobe * pump;
*pdf = norm * lobe / HdotI;
}
return make_spectrum(out);
}
ccl_device Spectrum bsdf_ashikhmin_shirley_eval_transmit(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
{
*pdf = 0.0f;
return zero_spectrum();
}
ccl_device_inline void bsdf_ashikhmin_shirley_sample_first_quadrant(float n_x,
float n_y,
float randu,
@ -146,81 +135,84 @@ ccl_device int bsdf_ashikhmin_shirley_sample(ccl_private const ShaderClosure *sc
int label = LABEL_REFLECT | LABEL_GLOSSY;
float NdotI = dot(N, I);
if (NdotI > 0.0f) {
if (!(NdotI > 0.0f)) {
*pdf = 0.0f;
*eval = zero_spectrum();
return LABEL_NONE;
}
float n_x = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_x);
float n_y = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_y);
float n_x = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_x);
float n_y = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_y);
/* get x,y basis on the surface for anisotropy */
float3 X, Y;
/* get x,y basis on the surface for anisotropy */
float3 X, Y;
if (n_x == n_y)
make_orthonormals(N, &X, &Y);
else
make_orthonormals_tangent(N, bsdf->T, &X, &Y);
if (n_x == n_y)
make_orthonormals(N, &X, &Y);
else
make_orthonormals_tangent(N, bsdf->T, &X, &Y);
/* sample spherical coords for h in tangent space */
float phi;
float cos_theta;
if (n_x == n_y) {
/* isotropic sampling */
phi = M_2PI_F * randu;
cos_theta = powf(randv, 1.0f / (n_x + 1.0f));
/* sample spherical coords for h in tangent space */
float phi;
float cos_theta;
if (n_x == n_y) {
/* isotropic sampling */
phi = M_2PI_F * randu;
cos_theta = powf(randv, 1.0f / (n_x + 1.0f));
}
else {
/* anisotropic sampling */
if (randu < 0.25f) { /* first quadrant */
float remapped_randu = 4.0f * randu;
bsdf_ashikhmin_shirley_sample_first_quadrant(
n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
}
else {
/* anisotropic sampling */
if (randu < 0.25f) { /* first quadrant */
float remapped_randu = 4.0f * randu;
bsdf_ashikhmin_shirley_sample_first_quadrant(
n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
}
else if (randu < 0.5f) { /* second quadrant */
float remapped_randu = 4.0f * (.5f - randu);
bsdf_ashikhmin_shirley_sample_first_quadrant(
n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
phi = M_PI_F - phi;
}
else if (randu < 0.75f) { /* third quadrant */
float remapped_randu = 4.0f * (randu - 0.5f);
bsdf_ashikhmin_shirley_sample_first_quadrant(
n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
phi = M_PI_F + phi;
}
else { /* fourth quadrant */
float remapped_randu = 4.0f * (1.0f - randu);
bsdf_ashikhmin_shirley_sample_first_quadrant(
n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
phi = 2.0f * M_PI_F - phi;
}
else if (randu < 0.5f) { /* second quadrant */
float remapped_randu = 4.0f * (.5f - randu);
bsdf_ashikhmin_shirley_sample_first_quadrant(
n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
phi = M_PI_F - phi;
}
/* get half vector in tangent space */
float sin_theta = sqrtf(fmaxf(0.0f, 1.0f - cos_theta * cos_theta));
float cos_phi = cosf(phi);
float sin_phi = sinf(phi); /* no sqrt(1-cos^2) here b/c it causes artifacts */
float3 h = make_float3(sin_theta * cos_phi, sin_theta * sin_phi, cos_theta);
/* half vector to world space */
float3 H = h.x * X + h.y * Y + h.z * N;
float HdotI = dot(H, I);
if (HdotI < 0.0f)
H = -H;
/* reflect I on H to get omega_in */
*omega_in = -I + (2.0f * HdotI) * H;
if (fmaxf(bsdf->alpha_x, bsdf->alpha_y) <= 1e-4f) {
/* Some high number for MIS. */
*pdf = 1e6f;
*eval = make_spectrum(1e6f);
label = LABEL_REFLECT | LABEL_SINGULAR;
else if (randu < 0.75f) { /* third quadrant */
float remapped_randu = 4.0f * (randu - 0.5f);
bsdf_ashikhmin_shirley_sample_first_quadrant(
n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
phi = M_PI_F + phi;
}
else {
/* leave the rest to eval_reflect */
*eval = bsdf_ashikhmin_shirley_eval_reflect(sc, I, *omega_in, pdf);
else { /* fourth quadrant */
float remapped_randu = 4.0f * (1.0f - randu);
bsdf_ashikhmin_shirley_sample_first_quadrant(
n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
phi = 2.0f * M_PI_F - phi;
}
}
/* get half vector in tangent space */
float sin_theta = sqrtf(fmaxf(0.0f, 1.0f - cos_theta * cos_theta));
float cos_phi = cosf(phi);
float sin_phi = sinf(phi); /* no sqrt(1-cos^2) here b/c it causes artifacts */
float3 h = make_float3(sin_theta * cos_phi, sin_theta * sin_phi, cos_theta);
/* half vector to world space */
float3 H = h.x * X + h.y * Y + h.z * N;
float HdotI = dot(H, I);
if (HdotI < 0.0f)
H = -H;
/* reflect I on H to get omega_in */
*omega_in = -I + (2.0f * HdotI) * H;
if (fmaxf(bsdf->alpha_x, bsdf->alpha_y) <= 1e-4f) {
/* Some high number for MIS. */
*pdf = 1e6f;
*eval = make_spectrum(1e6f);
label = LABEL_REFLECT | LABEL_SINGULAR;
}
else {
/* leave the rest to eval */
*eval = bsdf_ashikhmin_shirley_eval(sc, I, *omega_in, pdf);
}
return label;
}

View File

@ -31,10 +31,10 @@ ccl_device int bsdf_ashikhmin_velvet_setup(ccl_private VelvetBsdf *bsdf)
return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device Spectrum bsdf_ashikhmin_velvet_eval_reflect(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
ccl_device Spectrum bsdf_ashikhmin_velvet_eval(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
{
ccl_private const VelvetBsdf *bsdf = (ccl_private const VelvetBsdf *)sc;
float m_invsigma2 = bsdf->invsigma2;
@ -42,46 +42,37 @@ ccl_device Spectrum bsdf_ashikhmin_velvet_eval_reflect(ccl_private const ShaderC
float cosNO = dot(N, I);
float cosNI = dot(N, omega_in);
if (cosNO > 0 && cosNI > 0) {
float3 H = normalize(omega_in + I);
float cosNH = dot(N, H);
float cosHO = fabsf(dot(I, H));
if (!(fabsf(cosNH) < 1.0f - 1e-5f && cosHO > 1e-5f)) {
*pdf = 0.0f;
return zero_spectrum();
}
float cosNHdivHO = cosNH / cosHO;
cosNHdivHO = fmaxf(cosNHdivHO, 1e-5f);
float fac1 = 2 * fabsf(cosNHdivHO * cosNO);
float fac2 = 2 * fabsf(cosNHdivHO * cosNI);
float sinNH2 = 1 - cosNH * cosNH;
float sinNH4 = sinNH2 * sinNH2;
float cotangent2 = (cosNH * cosNH) / sinNH2;
float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * M_1_PI_F / sinNH4;
float G = fminf(1.0f, fminf(fac1, fac2)); // TODO: derive G from D analytically
float out = 0.25f * (D * G) / cosNO;
*pdf = 0.5f * M_1_PI_F;
return make_spectrum(out);
if (!(cosNO > 0 && cosNI > 0)) {
*pdf = 0.0f;
return zero_spectrum();
}
*pdf = 0.0f;
return zero_spectrum();
}
float3 H = normalize(omega_in + I);
ccl_device Spectrum bsdf_ashikhmin_velvet_eval_transmit(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
{
*pdf = 0.0f;
return zero_spectrum();
float cosNH = dot(N, H);
float cosHO = fabsf(dot(I, H));
if (!(fabsf(cosNH) < 1.0f - 1e-5f && cosHO > 1e-5f)) {
*pdf = 0.0f;
return zero_spectrum();
}
float cosNHdivHO = cosNH / cosHO;
cosNHdivHO = fmaxf(cosNHdivHO, 1e-5f);
float fac1 = 2 * fabsf(cosNHdivHO * cosNO);
float fac2 = 2 * fabsf(cosNHdivHO * cosNI);
float sinNH2 = 1 - cosNH * cosNH;
float sinNH4 = sinNH2 * sinNH2;
float cotangent2 = (cosNH * cosNH) / sinNH2;
float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * M_1_PI_F / sinNH4;
float G = fminf(1.0f, fminf(fac1, fac2)); // TODO: derive G from D analytically
float out = 0.25f * (D * G) / cosNO;
*pdf = 0.5f * M_1_PI_F;
return make_spectrum(out);
}
ccl_device int bsdf_ashikhmin_velvet_sample(ccl_private const ShaderClosure *sc,
@ -101,41 +92,42 @@ ccl_device int bsdf_ashikhmin_velvet_sample(ccl_private const ShaderClosure *sc,
// distribution over the hemisphere
sample_uniform_hemisphere(N, randu, randv, omega_in, pdf);
if (dot(Ng, *omega_in) > 0) {
float3 H = normalize(*omega_in + I);
float cosNI = dot(N, *omega_in);
float cosNO = dot(N, I);
float cosNH = dot(N, H);
float cosHO = fabsf(dot(I, H));
if (fabsf(cosNO) > 1e-5f && fabsf(cosNH) < 1.0f - 1e-5f && cosHO > 1e-5f) {
float cosNHdivHO = cosNH / cosHO;
cosNHdivHO = fmaxf(cosNHdivHO, 1e-5f);
float fac1 = 2 * fabsf(cosNHdivHO * cosNO);
float fac2 = 2 * fabsf(cosNHdivHO * cosNI);
float sinNH2 = 1 - cosNH * cosNH;
float sinNH4 = sinNH2 * sinNH2;
float cotangent2 = (cosNH * cosNH) / sinNH2;
float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * M_1_PI_F / sinNH4;
float G = fminf(1.0f, fminf(fac1, fac2)); // TODO: derive G from D analytically
float power = 0.25f * (D * G) / cosNO;
*eval = make_spectrum(power);
}
else {
*pdf = 0.0f;
*eval = zero_spectrum();
}
}
else {
if (!(dot(Ng, *omega_in) > 0)) {
*pdf = 0.0f;
*eval = zero_spectrum();
return LABEL_NONE;
}
float3 H = normalize(*omega_in + I);
float cosNI = dot(N, *omega_in);
float cosNO = dot(N, I);
float cosNH = dot(N, H);
float cosHO = fabsf(dot(I, H));
if (!(fabsf(cosNO) > 1e-5f && fabsf(cosNH) < 1.0f - 1e-5f && cosHO > 1e-5f)) {
*pdf = 0.0f;
*eval = zero_spectrum();
return LABEL_NONE;
}
float cosNHdivHO = cosNH / cosHO;
cosNHdivHO = fmaxf(cosNHdivHO, 1e-5f);
float fac1 = 2 * fabsf(cosNHdivHO * cosNO);
float fac2 = 2 * fabsf(cosNHdivHO * cosNI);
float sinNH2 = 1 - cosNH * cosNH;
float sinNH4 = sinNH2 * sinNH2;
float cotangent2 = (cosNH * cosNH) / sinNH2;
float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * M_1_PI_F / sinNH4;
float G = fminf(1.0f, fminf(fac1, fac2)); // TODO: derive G from D analytically
float power = 0.25f * (D * G) / cosNO;
*eval = make_spectrum(power);
return LABEL_REFLECT | LABEL_DIFFUSE;
}

View File

@ -26,10 +26,10 @@ ccl_device int bsdf_diffuse_setup(ccl_private DiffuseBsdf *bsdf)
return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device Spectrum bsdf_diffuse_eval_reflect(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
ccl_device Spectrum bsdf_diffuse_eval(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
{
ccl_private const DiffuseBsdf *bsdf = (ccl_private const DiffuseBsdf *)sc;
float3 N = bsdf->N;
@ -39,15 +39,6 @@ ccl_device Spectrum bsdf_diffuse_eval_reflect(ccl_private const ShaderClosure *s
return make_spectrum(cos_pi);
}
ccl_device Spectrum bsdf_diffuse_eval_transmit(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
{
*pdf = 0.0f;
return zero_spectrum();
}
ccl_device int bsdf_diffuse_sample(ccl_private const ShaderClosure *sc,
float3 Ng,
float3 I,
@ -81,19 +72,10 @@ ccl_device int bsdf_translucent_setup(ccl_private DiffuseBsdf *bsdf)
return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device Spectrum bsdf_translucent_eval_reflect(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
{
*pdf = 0.0f;
return zero_spectrum();
}
ccl_device Spectrum bsdf_translucent_eval_transmit(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
ccl_device Spectrum bsdf_translucent_eval(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
{
ccl_private const DiffuseBsdf *bsdf = (ccl_private const DiffuseBsdf *)sc;
float3 N = bsdf->N;

View File

@ -47,25 +47,23 @@ ccl_device void bsdf_diffuse_ramp_blur(ccl_private ShaderClosure *sc, float roug
{
}
ccl_device Spectrum bsdf_diffuse_ramp_eval_reflect(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
ccl_device Spectrum bsdf_diffuse_ramp_eval(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
{
const DiffuseRampBsdf *bsdf = (const DiffuseRampBsdf *)sc;
float3 N = bsdf->N;
float cos_pi = fmaxf(dot(N, omega_in), 0.0f);
*pdf = cos_pi * M_1_PI_F;
return rgb_to_spectrum(bsdf_diffuse_ramp_get_color(bsdf->colors, cos_pi) * M_1_PI_F);
}
ccl_device Spectrum bsdf_diffuse_ramp_eval_transmit(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
{
return zero_spectrum();
if (cos_pi >= 0.0f) {
*pdf = cos_pi * M_1_PI_F;
return rgb_to_spectrum(bsdf_diffuse_ramp_get_color(bsdf->colors, cos_pi) * M_1_PI_F);
}
else {
*pdf = 0.0f;
return zero_spectrum();
}
}
ccl_device int bsdf_diffuse_ramp_sample(ccl_private const ShaderClosure *sc,

View File

@ -37,12 +37,17 @@ ccl_device int bsdf_hair_transmission_setup(ccl_private HairBsdf *bsdf)
return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device Spectrum bsdf_hair_reflection_eval_reflect(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
ccl_device Spectrum bsdf_hair_reflection_eval(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
{
ccl_private const HairBsdf *bsdf = (ccl_private const HairBsdf *)sc;
if (dot(bsdf->N, omega_in) < 0.0f) {
*pdf = 0.0f;
return zero_spectrum();
}
float offset = bsdf->offset;
float3 Tg = bsdf->T;
float roughness1 = bsdf->roughness1;
@ -84,30 +89,17 @@ ccl_device Spectrum bsdf_hair_reflection_eval_reflect(ccl_private const ShaderCl
return make_spectrum(*pdf);
}
ccl_device Spectrum bsdf_hair_transmission_eval_reflect(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
{
*pdf = 0.0f;
return zero_spectrum();
}
ccl_device Spectrum bsdf_hair_reflection_eval_transmit(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
{
*pdf = 0.0f;
return zero_spectrum();
}
ccl_device Spectrum bsdf_hair_transmission_eval_transmit(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
ccl_device Spectrum bsdf_hair_transmission_eval(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
{
ccl_private const HairBsdf *bsdf = (ccl_private const HairBsdf *)sc;
if (dot(bsdf->N, omega_in) >= 0.0f) {
*pdf = 0.0f;
return zero_spectrum();
}
float offset = bsdf->offset;
float3 Tg = bsdf->T;
float roughness1 = bsdf->roughness1;

View File

@ -56,13 +56,7 @@ ccl_device_inline float delta_phi(int p, float gamma_o, float gamma_t)
/* Remaps the given angle to [-pi, pi]. */
ccl_device_inline float wrap_angle(float a)
{
while (a > M_PI_F) {
a -= M_2PI_F;
}
while (a < -M_PI_F) {
a += M_2PI_F;
}
return a;
return (a + M_PI_F) - M_2PI_F * floorf((a + M_PI_F) / M_2PI_F) - M_PI_F;
}
/* Logistic distribution function. */
@ -271,76 +265,72 @@ ccl_device Spectrum bsdf_principled_hair_eval(KernelGlobals kg,
kernel_assert(isfinite_safe(sd->P) && isfinite_safe(sd->ray_length));
ccl_private const PrincipledHairBSDF *bsdf = (ccl_private const PrincipledHairBSDF *)sc;
float3 Y = float4_to_float3(bsdf->extra->geom);
const float3 Y = float4_to_float3(bsdf->extra->geom);
float3 X = safe_normalize(sd->dPdu);
const float3 X = safe_normalize(sd->dPdu);
kernel_assert(fabsf(dot(X, Y)) < 1e-3f);
float3 Z = safe_normalize(cross(X, Y));
const float3 Z = safe_normalize(cross(X, Y));
float3 wo = make_float3(dot(sd->I, X), dot(sd->I, Y), dot(sd->I, Z));
float3 wi = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
const float3 wo = make_float3(dot(sd->I, X), dot(sd->I, Y), dot(sd->I, Z));
const float3 wi = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
float sin_theta_o = wo.x;
float cos_theta_o = cos_from_sin(sin_theta_o);
float phi_o = atan2f(wo.z, wo.y);
const float sin_theta_o = wo.x;
const float cos_theta_o = cos_from_sin(sin_theta_o);
const float phi_o = atan2f(wo.z, wo.y);
float sin_theta_t = sin_theta_o / bsdf->eta;
float cos_theta_t = cos_from_sin(sin_theta_t);
const float sin_theta_t = sin_theta_o / bsdf->eta;
const float cos_theta_t = cos_from_sin(sin_theta_t);
float sin_gamma_o = bsdf->extra->geom.w;
float cos_gamma_o = cos_from_sin(sin_gamma_o);
float gamma_o = safe_asinf(sin_gamma_o);
const float sin_gamma_o = bsdf->extra->geom.w;
const float cos_gamma_o = cos_from_sin(sin_gamma_o);
const float gamma_o = safe_asinf(sin_gamma_o);
float sin_gamma_t = sin_gamma_o * cos_theta_o / sqrtf(sqr(bsdf->eta) - sqr(sin_theta_o));
float cos_gamma_t = cos_from_sin(sin_gamma_t);
float gamma_t = safe_asinf(sin_gamma_t);
const float sin_gamma_t = sin_gamma_o * cos_theta_o / sqrtf(sqr(bsdf->eta) - sqr(sin_theta_o));
const float cos_gamma_t = cos_from_sin(sin_gamma_t);
const float gamma_t = safe_asinf(sin_gamma_t);
Spectrum T = exp(-bsdf->sigma * (2.0f * cos_gamma_t / cos_theta_t));
const Spectrum T = exp(-bsdf->sigma * (2.0f * cos_gamma_t / cos_theta_t));
Spectrum Ap[4];
float Ap_energy[4];
hair_attenuation(
kg, fresnel_dielectric_cos(cos_theta_o * cos_gamma_o, bsdf->eta), T, Ap, Ap_energy);
float sin_theta_i = wi.x;
float cos_theta_i = cos_from_sin(sin_theta_i);
float phi_i = atan2f(wi.z, wi.y);
const float sin_theta_i = wi.x;
const float cos_theta_i = cos_from_sin(sin_theta_i);
const float phi_i = atan2f(wi.z, wi.y);
float phi = phi_i - phi_o;
const float phi = phi_i - phi_o;
float angles[6];
hair_alpha_angles(sin_theta_i, cos_theta_i, bsdf->alpha, angles);
Spectrum F;
float F_energy;
float Mp, Np;
Spectrum F = zero_spectrum();
float F_energy = 0.0f;
/* Primary specular (R). */
Mp = longitudinal_scattering(angles[0], angles[1], sin_theta_o, cos_theta_o, bsdf->m0_roughness);
Np = azimuthal_scattering(phi, 0, bsdf->s, gamma_o, gamma_t);
F = Ap[0] * Mp * Np;
F_energy = Ap_energy[0] * Mp * Np;
kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy));
/* Transmission (TT). */
Mp = longitudinal_scattering(angles[2], angles[3], sin_theta_o, cos_theta_o, 0.25f * bsdf->v);
Np = azimuthal_scattering(phi, 1, bsdf->s, gamma_o, gamma_t);
F += Ap[1] * Mp * Np;
F_energy += Ap_energy[1] * Mp * Np;
kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy));
/* Secondary specular (TRT). */
Mp = longitudinal_scattering(angles[4], angles[5], sin_theta_o, cos_theta_o, 4.0f * bsdf->v);
Np = azimuthal_scattering(phi, 2, bsdf->s, gamma_o, gamma_t);
F += Ap[2] * Mp * Np;
F_energy += Ap_energy[2] * Mp * Np;
kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy));
/* Primary specular (R), Transmission (TT) and Secondary Specular (TRT). */
for (int i = 0; i < 3; i++) {
const float Mp = longitudinal_scattering(angles[2 * i],
angles[2 * i + 1],
sin_theta_o,
cos_theta_o,
(i == 0) ? bsdf->m0_roughness :
(i == 1) ? 0.25f * bsdf->v :
4.0f * bsdf->v);
const float Np = azimuthal_scattering(phi, i, bsdf->s, gamma_o, gamma_t);
F += Ap[i] * Mp * Np;
F_energy += Ap_energy[i] * Mp * Np;
kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy));
}
/* Residual component (TRRT+). */
Mp = longitudinal_scattering(sin_theta_i, cos_theta_i, sin_theta_o, cos_theta_o, 4.0f * bsdf->v);
Np = M_1_2PI_F;
F += Ap[3] * Mp * Np;
F_energy += Ap_energy[3] * Mp * Np;
kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy));
{
const float Mp = longitudinal_scattering(
sin_theta_i, cos_theta_i, sin_theta_o, cos_theta_o, 4.0f * bsdf->v);
const float Np = M_1_2PI_F;
F += Ap[3] * Mp * Np;
F_energy += Ap_energy[3] * Mp * Np;
kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy));
}
*pdf = F_energy;
return F;
@ -363,35 +353,35 @@ ccl_device int bsdf_principled_hair_sample(KernelGlobals kg,
*sampled_roughness = make_float2(bsdf->m0_roughness, bsdf->m0_roughness);
*eta = bsdf->eta;
float3 Y = float4_to_float3(bsdf->extra->geom);
const float3 Y = float4_to_float3(bsdf->extra->geom);
float3 X = safe_normalize(sd->dPdu);
const float3 X = safe_normalize(sd->dPdu);
kernel_assert(fabsf(dot(X, Y)) < 1e-3f);
float3 Z = safe_normalize(cross(X, Y));
const float3 Z = safe_normalize(cross(X, Y));
float3 wo = make_float3(dot(sd->I, X), dot(sd->I, Y), dot(sd->I, Z));
const float3 wo = make_float3(dot(sd->I, X), dot(sd->I, Y), dot(sd->I, Z));
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);
float sin_theta_o = wo.x;
float cos_theta_o = cos_from_sin(sin_theta_o);
float phi_o = atan2f(wo.z, wo.y);
const float sin_theta_o = wo.x;
const float cos_theta_o = cos_from_sin(sin_theta_o);
const float phi_o = atan2f(wo.z, wo.y);
float sin_theta_t = sin_theta_o / bsdf->eta;
float cos_theta_t = cos_from_sin(sin_theta_t);
const float sin_theta_t = sin_theta_o / bsdf->eta;
const float cos_theta_t = cos_from_sin(sin_theta_t);
float sin_gamma_o = bsdf->extra->geom.w;
float cos_gamma_o = cos_from_sin(sin_gamma_o);
float gamma_o = safe_asinf(sin_gamma_o);
const float sin_gamma_o = bsdf->extra->geom.w;
const float cos_gamma_o = cos_from_sin(sin_gamma_o);
const float gamma_o = safe_asinf(sin_gamma_o);
float sin_gamma_t = sin_gamma_o * cos_theta_o / sqrtf(sqr(bsdf->eta) - sqr(sin_theta_o));
float cos_gamma_t = cos_from_sin(sin_gamma_t);
float gamma_t = safe_asinf(sin_gamma_t);
const float sin_gamma_t = sin_gamma_o * cos_theta_o / sqrtf(sqr(bsdf->eta) - sqr(sin_theta_o));
const float cos_gamma_t = cos_from_sin(sin_gamma_t);
const float gamma_t = safe_asinf(sin_gamma_t);
Spectrum T = exp(-bsdf->sigma * (2.0f * cos_gamma_t / cos_theta_t));
const Spectrum T = exp(-bsdf->sigma * (2.0f * cos_gamma_t / cos_theta_t));
Spectrum Ap[4];
float Ap_energy[4];
hair_attenuation(
@ -414,7 +404,7 @@ ccl_device int bsdf_principled_hair_sample(KernelGlobals kg,
}
u[1].x = max(u[1].x, 1e-5f);
float fac = 1.0f + v * logf(u[1].x + (1.0f - u[1].x) * expf(-2.0f / v));
const float fac = 1.0f + v * logf(u[1].x + (1.0f - u[1].x) * expf(-2.0f / v));
float sin_theta_i = -fac * sin_theta_o +
cos_from_sin(fac) * cosf(M_2PI_F * u[1].y) * cos_theta_o;
float cos_theta_i = cos_from_sin(sin_theta_i);
@ -433,41 +423,37 @@ ccl_device int bsdf_principled_hair_sample(KernelGlobals kg,
else {
phi = M_2PI_F * u[0].y;
}
float phi_i = phi_o + phi;
const float phi_i = phi_o + phi;
hair_alpha_angles(sin_theta_i, cos_theta_i, bsdf->alpha, angles);
Spectrum F;
float F_energy;
float Mp, Np;
Spectrum F = zero_spectrum();
float F_energy = 0.0f;
/* Primary specular (R). */
Mp = longitudinal_scattering(angles[0], angles[1], sin_theta_o, cos_theta_o, bsdf->m0_roughness);
Np = azimuthal_scattering(phi, 0, bsdf->s, gamma_o, gamma_t);
F = Ap[0] * Mp * Np;
F_energy = Ap_energy[0] * Mp * Np;
kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy));
/* Transmission (TT). */
Mp = longitudinal_scattering(angles[2], angles[3], sin_theta_o, cos_theta_o, 0.25f * bsdf->v);
Np = azimuthal_scattering(phi, 1, bsdf->s, gamma_o, gamma_t);
F += Ap[1] * Mp * Np;
F_energy += Ap_energy[1] * Mp * Np;
kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy));
/* Secondary specular (TRT). */
Mp = longitudinal_scattering(angles[4], angles[5], sin_theta_o, cos_theta_o, 4.0f * bsdf->v);
Np = azimuthal_scattering(phi, 2, bsdf->s, gamma_o, gamma_t);
F += Ap[2] * Mp * Np;
F_energy += Ap_energy[2] * Mp * Np;
kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy));
/* Primary specular (R), Transmission (TT) and Secondary Specular (TRT). */
for (int i = 0; i < 3; i++) {
const float Mp = longitudinal_scattering(angles[2 * i],
angles[2 * i + 1],
sin_theta_o,
cos_theta_o,
(i == 0) ? bsdf->m0_roughness :
(i == 1) ? 0.25f * bsdf->v :
4.0f * bsdf->v);
const float Np = azimuthal_scattering(phi, i, bsdf->s, gamma_o, gamma_t);
F += Ap[i] * Mp * Np;
F_energy += Ap_energy[i] * Mp * Np;
kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy));
}
/* Residual component (TRRT+). */
Mp = longitudinal_scattering(sin_theta_i, cos_theta_i, sin_theta_o, cos_theta_o, 4.0f * bsdf->v);
Np = M_1_2PI_F;
F += Ap[3] * Mp * Np;
F_energy += Ap_energy[3] * Mp * Np;
kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy));
{
const float Mp = longitudinal_scattering(
sin_theta_i, cos_theta_i, sin_theta_o, cos_theta_o, 4.0f * bsdf->v);
const float Np = M_1_2PI_F;
F += Ap[3] * Mp * Np;
F_energy += Ap_energy[3] * Mp * Np;
kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy));
}
*eval = F;
*pdf = F_energy;

View File

@ -357,146 +357,129 @@ ccl_device void bsdf_microfacet_ggx_blur(ccl_private ShaderClosure *sc, float ro
bsdf->alpha_y = fmaxf(roughness, bsdf->alpha_y);
}
ccl_device Spectrum bsdf_microfacet_ggx_eval_reflect(ccl_private const ShaderClosure *sc,
ccl_device Spectrum bsdf_microfacet_ggx_eval_reflect(ccl_private const MicrofacetBsdf *bsdf,
const float3 N,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
ccl_private float *pdf,
const float alpha_x,
const float alpha_y,
const float cosNO,
const float cosNI)
{
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
float alpha_x = bsdf->alpha_x;
float alpha_y = bsdf->alpha_y;
bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
float3 N = bsdf->N;
if (m_refractive || alpha_x * alpha_y <= 1e-7f) {
if (!(cosNI > 0 && cosNO > 0)) {
*pdf = 0.0f;
return zero_spectrum();
}
float cosNO = dot(N, I);
float cosNI = dot(N, omega_in);
/* get half vector */
float3 m = normalize(omega_in + I);
float alpha2 = alpha_x * alpha_y;
float D, G1o, G1i;
if (cosNI > 0 && cosNO > 0) {
/* get half vector */
float3 m = normalize(omega_in + I);
float alpha2 = alpha_x * alpha_y;
float D, G1o, G1i;
if (alpha_x == alpha_y) {
/* isotropic
* eq. 20: (F*G*D)/(4*in*on)
* eq. 33: first we calculate D(m) */
float cosThetaM = dot(N, m);
float cosThetaM2 = cosThetaM * cosThetaM;
float cosThetaM4 = cosThetaM2 * cosThetaM2;
float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
if (alpha_x == alpha_y) {
/* isotropic
* eq. 20: (F*G*D)/(4*in*on)
* eq. 33: first we calculate D(m) */
float cosThetaM = dot(N, m);
float cosThetaM2 = cosThetaM * cosThetaM;
float cosThetaM4 = cosThetaM2 * cosThetaM2;
float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) {
/* use GTR1 for clearcoat */
D = D_GTR1(cosThetaM, bsdf->alpha_x);
if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) {
/* use GTR1 for clearcoat */
D = D_GTR1(cosThetaM, bsdf->alpha_x);
/* the alpha value for clearcoat is a fixed 0.25 => alpha2 = 0.25 * 0.25 */
alpha2 = 0.0625f;
}
else {
/* use GTR2 otherwise */
D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
}
/* eq. 34: now calculate G1(i,m) and G1(o,m) */
G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI)));
/* the alpha value for clearcoat is a fixed 0.25 => alpha2 = 0.25 * 0.25 */
alpha2 = 0.0625f;
}
else {
/* anisotropic */
float3 X, Y, Z = N;
make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
/* distribution */
float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m));
float slope_x = -local_m.x / (local_m.z * alpha_x);
float slope_y = -local_m.y / (local_m.z * alpha_y);
float slope_len = 1 + slope_x * slope_x + slope_y * slope_y;
float cosThetaM = local_m.z;
float cosThetaM2 = cosThetaM * cosThetaM;
float cosThetaM4 = cosThetaM2 * cosThetaM2;
D = 1 / ((slope_len * slope_len) * M_PI_F * alpha2 * cosThetaM4);
/* G1(i,m) and G1(o,m) */
float tanThetaO2 = (1 - cosNO * cosNO) / (cosNO * cosNO);
float cosPhiO = dot(I, X);
float sinPhiO = dot(I, Y);
float alphaO2 = (cosPhiO * cosPhiO) * (alpha_x * alpha_x) +
(sinPhiO * sinPhiO) * (alpha_y * alpha_y);
alphaO2 /= cosPhiO * cosPhiO + sinPhiO * sinPhiO;
G1o = 2 / (1 + safe_sqrtf(1 + alphaO2 * tanThetaO2));
float tanThetaI2 = (1 - cosNI * cosNI) / (cosNI * cosNI);
float cosPhiI = dot(omega_in, X);
float sinPhiI = dot(omega_in, Y);
float alphaI2 = (cosPhiI * cosPhiI) * (alpha_x * alpha_x) +
(sinPhiI * sinPhiI) * (alpha_y * alpha_y);
alphaI2 /= cosPhiI * cosPhiI + sinPhiI * sinPhiI;
G1i = 2 / (1 + safe_sqrtf(1 + alphaI2 * tanThetaI2));
/* use GTR2 otherwise */
D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
}
float G = G1o * G1i;
/* eq. 34: now calculate G1(i,m) and G1(o,m) */
G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI)));
}
else {
/* anisotropic */
float3 X, Y, Z = N;
make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
/* eq. 20 */
float common = D * 0.25f / cosNO;
/* distribution */
float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m));
float slope_x = -local_m.x / (local_m.z * alpha_x);
float slope_y = -local_m.y / (local_m.z * alpha_y);
float slope_len = 1 + slope_x * slope_x + slope_y * slope_y;
Spectrum F = reflection_color(bsdf, omega_in, m);
if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) {
F *= 0.25f * bsdf->extra->clearcoat;
}
float cosThetaM = local_m.z;
float cosThetaM2 = cosThetaM * cosThetaM;
float cosThetaM4 = cosThetaM2 * cosThetaM2;
Spectrum out = F * G * common;
D = 1 / ((slope_len * slope_len) * M_PI_F * alpha2 * cosThetaM4);
/* eq. 2 in distribution of visible normals sampling
* `pm = Dw = G1o * dot(m, I) * D / dot(N, I);` */
/* G1(i,m) and G1(o,m) */
float tanThetaO2 = (1 - cosNO * cosNO) / (cosNO * cosNO);
float cosPhiO = dot(I, X);
float sinPhiO = dot(I, Y);
/* eq. 38 - but see also:
* eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf
* `pdf = pm * 0.25 / dot(m, I);` */
*pdf = G1o * common;
float alphaO2 = (cosPhiO * cosPhiO) * (alpha_x * alpha_x) +
(sinPhiO * sinPhiO) * (alpha_y * alpha_y);
alphaO2 /= cosPhiO * cosPhiO + sinPhiO * sinPhiO;
return out;
G1o = 2 / (1 + safe_sqrtf(1 + alphaO2 * tanThetaO2));
float tanThetaI2 = (1 - cosNI * cosNI) / (cosNI * cosNI);
float cosPhiI = dot(omega_in, X);
float sinPhiI = dot(omega_in, Y);
float alphaI2 = (cosPhiI * cosPhiI) * (alpha_x * alpha_x) +
(sinPhiI * sinPhiI) * (alpha_y * alpha_y);
alphaI2 /= cosPhiI * cosPhiI + sinPhiI * sinPhiI;
G1i = 2 / (1 + safe_sqrtf(1 + alphaI2 * tanThetaI2));
}
return zero_spectrum();
float G = G1o * G1i;
/* eq. 20 */
float common = D * 0.25f / cosNO;
Spectrum F = reflection_color(bsdf, omega_in, m);
if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) {
F *= 0.25f * bsdf->extra->clearcoat;
}
Spectrum out = F * G * common;
/* eq. 2 in distribution of visible normals sampling
* `pm = Dw = G1o * dot(m, I) * D / dot(N, I);` */
/* eq. 38 - but see also:
* eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf
* `pdf = pm * 0.25 / dot(m, I);` */
*pdf = G1o * common;
return out;
}
ccl_device Spectrum bsdf_microfacet_ggx_eval_transmit(ccl_private const ShaderClosure *sc,
ccl_device Spectrum bsdf_microfacet_ggx_eval_transmit(ccl_private const MicrofacetBsdf *bsdf,
const float3 N,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
ccl_private float *pdf,
const float alpha_x,
const float alpha_y,
const float cosNO,
const float cosNI)
{
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
float alpha_x = bsdf->alpha_x;
float alpha_y = bsdf->alpha_y;
float m_eta = bsdf->ior;
bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
float3 N = bsdf->N;
if (!m_refractive || alpha_x * alpha_y <= 1e-7f) {
*pdf = 0.0f;
return zero_spectrum();
}
float cosNO = dot(N, I);
float cosNI = dot(N, omega_in);
if (cosNO <= 0 || cosNI >= 0) {
*pdf = 0.0f;
return zero_spectrum(); /* vectors on same side -- not possible */
}
/* compute half-vector of the refraction (eq. 16) */
float m_eta = bsdf->ior;
float3 ht = -(m_eta * omega_in + I);
float3 Ht = normalize(ht);
float cosHO = dot(Ht, I);
@ -533,6 +516,30 @@ ccl_device Spectrum bsdf_microfacet_ggx_eval_transmit(ccl_private const ShaderCl
return make_spectrum(out);
}
ccl_device Spectrum bsdf_microfacet_ggx_eval(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
{
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
const float alpha_x = bsdf->alpha_x;
const float alpha_y = bsdf->alpha_y;
const bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
const float3 N = bsdf->N;
const float cosNO = dot(N, I);
const float cosNI = dot(N, omega_in);
if (((cosNI < 0.0f) != m_refractive) || alpha_x * alpha_y <= 1e-7f) {
*pdf = 0.0f;
return zero_spectrum();
}
return (cosNI < 0.0f) ? bsdf_microfacet_ggx_eval_transmit(
bsdf, N, I, omega_in, pdf, alpha_x, alpha_y, cosNO, cosNI) :
bsdf_microfacet_ggx_eval_reflect(
bsdf, N, I, omega_in, pdf, alpha_x, alpha_y, cosNO, cosNI);
}
ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals kg,
ccl_private const ShaderClosure *sc,
float3 Ng,
@ -811,111 +818,95 @@ ccl_device_inline float bsdf_beckmann_aniso_G1(
return ((2.181f * a + 3.535f) * a) / ((2.577f * a + 2.276f) * a + 1.0f);
}
ccl_device Spectrum bsdf_microfacet_beckmann_eval_reflect(ccl_private const ShaderClosure *sc,
ccl_device Spectrum bsdf_microfacet_beckmann_eval_reflect(ccl_private const MicrofacetBsdf *bsdf,
const float3 N,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
ccl_private float *pdf,
const float alpha_x,
const float alpha_y,
const float cosNO,
const float cosNI)
{
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
float alpha_x = bsdf->alpha_x;
float alpha_y = bsdf->alpha_y;
bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
float3 N = bsdf->N;
if (m_refractive || alpha_x * alpha_y <= 1e-7f) {
if (!(cosNO > 0 && cosNI > 0)) {
*pdf = 0.0f;
return zero_spectrum();
}
float cosNO = dot(N, I);
float cosNI = dot(N, omega_in);
/* get half vector */
float3 m = normalize(omega_in + I);
if (cosNO > 0 && cosNI > 0) {
/* get half vector */
float3 m = normalize(omega_in + I);
float alpha2 = alpha_x * alpha_y;
float D, G1o, G1i;
float alpha2 = alpha_x * alpha_y;
float D, G1o, G1i;
if (alpha_x == alpha_y) {
/* isotropic
* eq. 20: (F*G*D)/(4*in*on)
* eq. 25: first we calculate D(m) */
float cosThetaM = dot(N, m);
float cosThetaM2 = cosThetaM * cosThetaM;
float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
float cosThetaM4 = cosThetaM2 * cosThetaM2;
D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 * cosThetaM4);
if (alpha_x == alpha_y) {
/* isotropic
* eq. 20: (F*G*D)/(4*in*on)
* eq. 25: first we calculate D(m) */
float cosThetaM = dot(N, m);
float cosThetaM2 = cosThetaM * cosThetaM;
float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
float cosThetaM4 = cosThetaM2 * cosThetaM2;
D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 * cosThetaM4);
/* eq. 26, 27: now calculate G1(i,m) and G1(o,m) */
G1o = bsdf_beckmann_G1(alpha_x, cosNO);
G1i = bsdf_beckmann_G1(alpha_x, cosNI);
}
else {
/* anisotropic */
float3 X, Y, Z = N;
make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
/* eq. 26, 27: now calculate G1(i,m) and G1(o,m) */
G1o = bsdf_beckmann_G1(alpha_x, cosNO);
G1i = bsdf_beckmann_G1(alpha_x, cosNI);
}
else {
/* anisotropic */
float3 X, Y, Z = N;
make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
/* distribution */
float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m));
float slope_x = -local_m.x / (local_m.z * alpha_x);
float slope_y = -local_m.y / (local_m.z * alpha_y);
/* distribution */
float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m));
float slope_x = -local_m.x / (local_m.z * alpha_x);
float slope_y = -local_m.y / (local_m.z * alpha_y);
float cosThetaM = local_m.z;
float cosThetaM2 = cosThetaM * cosThetaM;
float cosThetaM4 = cosThetaM2 * cosThetaM2;
float cosThetaM = local_m.z;
float cosThetaM2 = cosThetaM * cosThetaM;
float cosThetaM4 = cosThetaM2 * cosThetaM2;
D = expf(-slope_x * slope_x - slope_y * slope_y) / (M_PI_F * alpha2 * cosThetaM4);
D = expf(-slope_x * slope_x - slope_y * slope_y) / (M_PI_F * alpha2 * cosThetaM4);
/* G1(i,m) and G1(o,m) */
G1o = bsdf_beckmann_aniso_G1(alpha_x, alpha_y, cosNO, dot(I, X), dot(I, Y));
G1i = bsdf_beckmann_aniso_G1(alpha_x, alpha_y, cosNI, dot(omega_in, X), dot(omega_in, Y));
}
float G = G1o * G1i;
/* eq. 20 */
float common = D * 0.25f / cosNO;
float out = G * common;
/* eq. 2 in distribution of visible normals sampling
* pm = Dw = G1o * dot(m, I) * D / dot(N, I); */
/* eq. 38 - but see also:
* eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf
* pdf = pm * 0.25 / dot(m, I); */
*pdf = G1o * common;
return make_spectrum(out);
/* G1(i,m) and G1(o,m) */
G1o = bsdf_beckmann_aniso_G1(alpha_x, alpha_y, cosNO, dot(I, X), dot(I, Y));
G1i = bsdf_beckmann_aniso_G1(alpha_x, alpha_y, cosNI, dot(omega_in, X), dot(omega_in, Y));
}
return zero_spectrum();
float G = G1o * G1i;
/* eq. 20 */
float common = D * 0.25f / cosNO;
float out = G * common;
/* eq. 2 in distribution of visible normals sampling
* pm = Dw = G1o * dot(m, I) * D / dot(N, I); */
/* eq. 38 - but see also:
* eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf
* pdf = pm * 0.25 / dot(m, I); */
*pdf = G1o * common;
return make_spectrum(out);
}
ccl_device Spectrum bsdf_microfacet_beckmann_eval_transmit(ccl_private const ShaderClosure *sc,
ccl_device Spectrum bsdf_microfacet_beckmann_eval_transmit(ccl_private const MicrofacetBsdf *bsdf,
const float3 N,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
ccl_private float *pdf,
const float alpha_x,
const float alpha_y,
const float cosNO,
const float cosNI)
{
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
float alpha_x = bsdf->alpha_x;
float alpha_y = bsdf->alpha_y;
float m_eta = bsdf->ior;
bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
float3 N = bsdf->N;
if (!m_refractive || alpha_x * alpha_y <= 1e-7f) {
*pdf = 0.0f;
return zero_spectrum();
}
float cosNO = dot(N, I);
float cosNI = dot(N, omega_in);
if (cosNO <= 0 || cosNI >= 0) {
*pdf = 0.0f;
return zero_spectrum();
}
const float m_eta = bsdf->ior;
/* compute half-vector of the refraction (eq. 16) */
float3 ht = -(m_eta * omega_in + I);
float3 Ht = normalize(ht);
@ -950,6 +941,30 @@ ccl_device Spectrum bsdf_microfacet_beckmann_eval_transmit(ccl_private const Sha
return make_spectrum(out);
}
ccl_device Spectrum bsdf_microfacet_beckmann_eval(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
{
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
const float alpha_x = bsdf->alpha_x;
const float alpha_y = bsdf->alpha_y;
const bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
const float3 N = bsdf->N;
const float cosNO = dot(N, I);
const float cosNI = dot(N, omega_in);
if (((cosNI < 0.0f) != m_refractive) || alpha_x * alpha_y <= 1e-7f) {
*pdf = 0.0f;
return zero_spectrum();
}
return (cosNI < 0.0f) ? bsdf_microfacet_beckmann_eval_transmit(
bsdf, N, I, omega_in, pdf, alpha_x, alpha_y, cosNO, cosNI) :
bsdf_microfacet_beckmann_eval_reflect(
bsdf, N, I, omega_in, pdf, alpha_x, alpha_y, cosNO, cosNI);
}
ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals kg,
ccl_private const ShaderClosure *sc,
float3 Ng,

View File

@ -415,21 +415,11 @@ ccl_device int bsdf_microfacet_multi_ggx_refraction_setup(ccl_private Microfacet
return bsdf_microfacet_multi_ggx_common_setup(bsdf);
}
ccl_device Spectrum bsdf_microfacet_multi_ggx_eval_transmit(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf,
ccl_private uint *lcg_state)
{
*pdf = 0.0f;
return zero_spectrum();
}
ccl_device Spectrum bsdf_microfacet_multi_ggx_eval_reflect(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf,
ccl_private uint *lcg_state)
ccl_device Spectrum bsdf_microfacet_multi_ggx_eval(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf,
ccl_private uint *lcg_state)
{
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
@ -588,12 +578,11 @@ ccl_device int bsdf_microfacet_multi_ggx_glass_fresnel_setup(ccl_private Microfa
return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_NEEDS_LCG;
}
ccl_device Spectrum
bsdf_microfacet_multi_ggx_glass_eval_transmit(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf,
ccl_private uint *lcg_state)
ccl_device Spectrum bsdf_microfacet_multi_ggx_glass_eval(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf,
ccl_private uint *lcg_state)
{
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
@ -609,55 +598,22 @@ bsdf_microfacet_multi_ggx_glass_eval_transmit(ccl_private const ShaderClosure *s
float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
float3 localO = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
*pdf = mf_glass_pdf(localI, localO, bsdf->alpha_x, bsdf->ior);
kernel_assert(*pdf >= 0.f);
return mf_eval_glass(localI,
localO,
false,
bsdf->extra->color,
bsdf->alpha_x,
bsdf->alpha_y,
lcg_state,
bsdf->ior,
false,
bsdf->extra->color);
}
ccl_device Spectrum
bsdf_microfacet_multi_ggx_glass_eval_reflect(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf,
ccl_private uint *lcg_state)
{
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
if (bsdf->alpha_x * bsdf->alpha_y < 1e-7f) {
*pdf = 0.0f;
return zero_spectrum();
}
bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID);
float3 X, Y, Z;
Z = bsdf->N;
make_orthonormals(Z, &X, &Y);
float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
float3 localO = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
const bool is_transmission = localO.z < 0.0f;
const bool use_fresnel = !is_transmission &&
(bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID);
*pdf = mf_glass_pdf(localI, localO, bsdf->alpha_x, bsdf->ior);
kernel_assert(*pdf >= 0.f);
return mf_eval_glass(localI,
localO,
true,
!is_transmission,
bsdf->extra->color,
bsdf->alpha_x,
bsdf->alpha_y,
lcg_state,
bsdf->ior,
use_fresnel,
bsdf->extra->cspec0);
(is_transmission) ? bsdf->extra->color : bsdf->extra->cspec0);
}
ccl_device int bsdf_microfacet_multi_ggx_glass_sample(KernelGlobals kg,

View File

@ -47,10 +47,10 @@ ccl_device int bsdf_oren_nayar_setup(ccl_private OrenNayarBsdf *bsdf)
return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device Spectrum bsdf_oren_nayar_eval_reflect(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
ccl_device Spectrum bsdf_oren_nayar_eval(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
{
ccl_private const OrenNayarBsdf *bsdf = (ccl_private const OrenNayarBsdf *)sc;
if (dot(bsdf->N, omega_in) > 0.0f) {
@ -63,15 +63,6 @@ ccl_device Spectrum bsdf_oren_nayar_eval_reflect(ccl_private const ShaderClosure
}
}
ccl_device Spectrum bsdf_oren_nayar_eval_transmit(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
{
*pdf = 0.0f;
return zero_spectrum();
}
ccl_device int bsdf_oren_nayar_sample(ccl_private const ShaderClosure *sc,
float3 Ng,
float3 I,

View File

@ -44,10 +44,10 @@ ccl_device int bsdf_phong_ramp_setup(ccl_private PhongRampBsdf *bsdf)
return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device Spectrum bsdf_phong_ramp_eval_reflect(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
ccl_device Spectrum bsdf_phong_ramp_eval(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
{
ccl_private const PhongRampBsdf *bsdf = (ccl_private const PhongRampBsdf *)sc;
float m_exponent = bsdf->exponent;
@ -70,15 +70,6 @@ ccl_device Spectrum bsdf_phong_ramp_eval_reflect(ccl_private const ShaderClosure
return zero_spectrum();
}
ccl_device float3 bsdf_phong_ramp_eval_transmit(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
{
*pdf = 0.0f;
return make_float3(0.0f, 0.0f, 0.0f);
}
ccl_device_inline float phong_ramp_exponent_to_roughness(float exponent)
{
return sqrt(1.0f / ((exponent + 2.0f) / 2.0f));

View File

@ -109,18 +109,17 @@ ccl_device int bsdf_principled_diffuse_setup(ccl_private PrincipledDiffuseBsdf *
return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device Spectrum bsdf_principled_diffuse_eval_reflect(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
ccl_device Spectrum bsdf_principled_diffuse_eval(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
{
ccl_private const PrincipledDiffuseBsdf *bsdf = (ccl_private const PrincipledDiffuseBsdf *)sc;
float3 N = bsdf->N;
float3 V = I; // outgoing
float3 L = omega_in; // incoming
const float3 N = bsdf->N;
if (dot(N, omega_in) > 0.0f) {
const float3 V = I; // outgoing
const float3 L = omega_in; // incoming
*pdf = fmaxf(dot(N, omega_in), 0.0f) * M_1_PI_F;
return bsdf_principled_diffuse_compute_brdf(bsdf, N, V, L, pdf);
}
@ -130,15 +129,6 @@ ccl_device Spectrum bsdf_principled_diffuse_eval_reflect(ccl_private const Shade
}
}
ccl_device Spectrum bsdf_principled_diffuse_eval_transmit(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
{
*pdf = 0.0f;
return zero_spectrum();
}
ccl_device int bsdf_principled_diffuse_sample(ccl_private const ShaderClosure *sc,
float3 Ng,
float3 I,

View File

@ -59,19 +59,19 @@ ccl_device int bsdf_principled_sheen_setup(ccl_private const ShaderData *sd,
return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device Spectrum bsdf_principled_sheen_eval_reflect(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
ccl_device Spectrum bsdf_principled_sheen_eval(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
{
ccl_private const PrincipledSheenBsdf *bsdf = (ccl_private const PrincipledSheenBsdf *)sc;
float3 N = bsdf->N;
float3 V = I; // outgoing
float3 L = omega_in; // incoming
float3 H = normalize(L + V);
const float3 N = bsdf->N;
if (dot(N, omega_in) > 0.0f) {
const float3 V = I; // outgoing
const float3 L = omega_in; // incoming
const float3 H = normalize(L + V);
*pdf = fmaxf(dot(N, omega_in), 0.0f) * M_1_PI_F;
return calculate_principled_sheen_brdf(N, V, L, H, pdf);
}
@ -81,15 +81,6 @@ ccl_device Spectrum bsdf_principled_sheen_eval_reflect(ccl_private const ShaderC
}
}
ccl_device Spectrum bsdf_principled_sheen_eval_transmit(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
{
*pdf = 0.0f;
return zero_spectrum();
}
ccl_device int bsdf_principled_sheen_sample(ccl_private const ShaderClosure *sc,
float3 Ng,
float3 I,

View File

@ -18,19 +18,10 @@ ccl_device int bsdf_reflection_setup(ccl_private MicrofacetBsdf *bsdf)
return SD_BSDF;
}
ccl_device Spectrum bsdf_reflection_eval_reflect(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
{
*pdf = 0.0f;
return zero_spectrum();
}
ccl_device Spectrum bsdf_reflection_eval_transmit(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
ccl_device Spectrum bsdf_reflection_eval(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
{
*pdf = 0.0f;
return zero_spectrum();

View File

@ -18,19 +18,10 @@ ccl_device int bsdf_refraction_setup(ccl_private MicrofacetBsdf *bsdf)
return SD_BSDF;
}
ccl_device Spectrum bsdf_refraction_eval_reflect(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
{
*pdf = 0.0f;
return zero_spectrum();
}
ccl_device Spectrum bsdf_refraction_eval_transmit(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
ccl_device Spectrum bsdf_refraction_eval(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
{
*pdf = 0.0f;
return zero_spectrum();

View File

@ -49,33 +49,29 @@ ccl_device float bsdf_toon_get_sample_angle(float max_angle, float smooth)
return fminf(max_angle + smooth, M_PI_2_F);
}
ccl_device Spectrum bsdf_diffuse_toon_eval_reflect(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
ccl_device Spectrum bsdf_diffuse_toon_eval(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
{
ccl_private const ToonBsdf *bsdf = (ccl_private const ToonBsdf *)sc;
float max_angle = bsdf->size * M_PI_2_F;
float smooth = bsdf->smooth * M_PI_2_F;
float angle = safe_acosf(fmaxf(dot(bsdf->N, omega_in), 0.0f));
float cosNI = dot(bsdf->N, omega_in);
float eval = bsdf_toon_get_intensity(max_angle, smooth, angle);
if (cosNI >= 0.0f) {
float max_angle = bsdf->size * M_PI_2_F;
float smooth = bsdf->smooth * M_PI_2_F;
float angle = safe_acosf(fmaxf(cosNI, 0.0f));
if (eval > 0.0f) {
float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
float eval = bsdf_toon_get_intensity(max_angle, smooth, angle);
*pdf = 0.5f * M_1_PI_F / (1.0f - cosf(sample_angle));
return make_spectrum(*pdf * eval);
if (eval > 0.0f) {
float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
*pdf = 0.5f * M_1_PI_F / (1.0f - cosf(sample_angle));
return make_spectrum(*pdf * eval);
}
}
*pdf = 0.0f;
return zero_spectrum();
}
ccl_device Spectrum bsdf_diffuse_toon_eval_transmit(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
{
*pdf = 0.0f;
return zero_spectrum();
}
@ -125,10 +121,10 @@ ccl_device int bsdf_glossy_toon_setup(ccl_private ToonBsdf *bsdf)
return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device Spectrum bsdf_glossy_toon_eval_reflect(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
ccl_device Spectrum bsdf_glossy_toon_eval(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
{
ccl_private const ToonBsdf *bsdf = (ccl_private const ToonBsdf *)sc;
float max_angle = bsdf->size * M_PI_2_F;
@ -153,15 +149,6 @@ ccl_device Spectrum bsdf_glossy_toon_eval_reflect(ccl_private const ShaderClosur
return zero_spectrum();
}
ccl_device Spectrum bsdf_glossy_toon_eval_transmit(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
{
*pdf = 0.0f;
return zero_spectrum();
}
ccl_device int bsdf_glossy_toon_sample(ccl_private const ShaderClosure *sc,
float3 Ng,
float3 I,

View File

@ -59,19 +59,10 @@ ccl_device void bsdf_transparent_setup(ccl_private ShaderData *sd,
}
}
ccl_device Spectrum bsdf_transparent_eval_reflect(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
{
*pdf = 0.0f;
return zero_spectrum();
}
ccl_device Spectrum bsdf_transparent_eval_transmit(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
ccl_device Spectrum bsdf_transparent_eval(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
{
*pdf = 0.0f;
return zero_spectrum();

View File

@ -807,7 +807,7 @@ ccl_device_forceinline bool mnee_path_contribution(KernelGlobals kg,
float3 wo = normalize_len(vertices[0].p - sd->P, &wo_len);
/* Initialize throughput and evaluate receiver bsdf * |n.wo|. */
surface_shader_bsdf_eval(kg, sd, wo, false, throughput, ls->shader);
surface_shader_bsdf_eval(kg, sd, wo, throughput, ls->shader);
/* Update light sample with new position / direct.ion
* and keep pdf in vertex area measure */

View File

@ -171,7 +171,8 @@ ccl_device_forceinline void integrate_surface_direct_light(KernelGlobals kg,
Ray ray ccl_optional_struct_init;
BsdfEval bsdf_eval ccl_optional_struct_init;
const bool is_transmission = surface_shader_is_transmission(sd, ls.D);
const bool is_transmission = dot(ls.D, sd->N) < 0.0f;
#ifdef __MNEE__
int mnee_vertex_count = 0;
@ -182,13 +183,15 @@ ccl_device_forceinline void integrate_surface_direct_light(KernelGlobals kg,
const bool use_caustics = kernel_data_fetch(lights, ls.lamp).use_caustics;
if (use_caustics) {
/* Are we on a caustic caster? */
if (is_transmission && (sd->object_flag & SD_OBJECT_CAUSTICS_CASTER))
if (is_transmission && (sd->object_flag & SD_OBJECT_CAUSTICS_CASTER)) {
return;
}
/* Are we on a caustic receiver? */
if (!is_transmission && (sd->object_flag & SD_OBJECT_CAUSTICS_RECEIVER))
if (!is_transmission && (sd->object_flag & SD_OBJECT_CAUSTICS_RECEIVER)) {
mnee_vertex_count = kernel_path_mnee_sample(
kg, state, sd, emission_sd, rng_state, &ls, &bsdf_eval);
}
}
}
}
@ -207,8 +210,7 @@ ccl_device_forceinline void integrate_surface_direct_light(KernelGlobals kg,
}
/* Evaluate BSDF. */
const float bsdf_pdf = surface_shader_bsdf_eval(
kg, sd, ls.D, is_transmission, &bsdf_eval, ls.shader);
const float bsdf_pdf = surface_shader_bsdf_eval(kg, sd, ls.D, &bsdf_eval, ls.shader);
bsdf_eval_mul(&bsdf_eval, light_eval / ls.pdf);
if (ls.shader & SHADER_USE_MIS) {

View File

@ -108,13 +108,6 @@ ccl_device_inline void surface_shader_prepare_closures(KernelGlobals kg,
}
/* BSDF */
ccl_device_inline bool surface_shader_is_transmission(ccl_private const ShaderData *sd,
const float3 omega_in)
{
return dot(sd->N, omega_in) < 0.0f;
}
ccl_device_forceinline bool _surface_shader_exclude(ClosureType type, uint light_shader_flags)
{
if (!(light_shader_flags & SHADER_EXCLUDE_ANY)) {
@ -141,7 +134,6 @@ ccl_device_forceinline bool _surface_shader_exclude(ClosureType type, uint light
ccl_device_inline float _surface_shader_bsdf_eval_mis(KernelGlobals kg,
ccl_private ShaderData *sd,
const float3 omega_in,
const bool is_transmission,
ccl_private const ShaderClosure *skip_sc,
ccl_private BsdfEval *result_eval,
float sum_pdf,
@ -160,7 +152,7 @@ ccl_device_inline float _surface_shader_bsdf_eval_mis(KernelGlobals kg,
if (CLOSURE_IS_BSDF_OR_BSSRDF(sc->type)) {
if (CLOSURE_IS_BSDF(sc->type) && !_surface_shader_exclude(sc->type, light_shader_flags)) {
float bsdf_pdf = 0.0f;
Spectrum eval = bsdf_eval(kg, sd, sc, omega_in, is_transmission, &bsdf_pdf);
Spectrum eval = bsdf_eval(kg, sd, sc, omega_in, &bsdf_pdf);
if (bsdf_pdf != 0.0f) {
bsdf_eval_accum(result_eval, sc->type, eval * sc->weight);
@ -184,14 +176,13 @@ ccl_device_inline
surface_shader_bsdf_eval(KernelGlobals kg,
ccl_private ShaderData *sd,
const float3 omega_in,
const bool is_transmission,
ccl_private BsdfEval *bsdf_eval,
const uint light_shader_flags)
{
bsdf_eval_init(bsdf_eval, CLOSURE_NONE_ID, zero_spectrum());
return _surface_shader_bsdf_eval_mis(
kg, sd, omega_in, is_transmission, NULL, bsdf_eval, 0.0f, 0.0f, light_shader_flags);
kg, sd, omega_in, NULL, bsdf_eval, 0.0f, 0.0f, light_shader_flags);
}
/* Randomly sample a BSSRDF or BSDF proportional to ShaderClosure.sample_weight. */
@ -285,10 +276,9 @@ ccl_device int surface_shader_bsdf_sample_closure(KernelGlobals kg,
bsdf_eval_init(bsdf_eval, sc->type, eval * sc->weight);
if (sd->num_closure > 1) {
const bool is_transmission = surface_shader_is_transmission(sd, *omega_in);
float sweight = sc->sample_weight;
*pdf = _surface_shader_bsdf_eval_mis(
kg, sd, *omega_in, is_transmission, sc, bsdf_eval, *pdf * sweight, sweight, 0);
kg, sd, *omega_in, sc, bsdf_eval, *pdf * sweight, sweight, 0);
}
}