forked from bartvdbraak/blender
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:
parent
bd249eb4f3
commit
6d19da0b2d
@ -69,7 +69,11 @@ ccl_device_inline float bsdf_get_roughness_squared(ccl_private const ShaderClosu
|
|||||||
* Yining Karl Li and Brent Burley. */
|
* Yining Karl Li and Brent Burley. */
|
||||||
ccl_device_inline float bump_shadowing_term(float3 Ng, float3 N, float3 I)
|
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 the incoming light is on the unshadowed side, return full brightness. */
|
||||||
if (g >= 1.0f) {
|
if (g >= 1.0f) {
|
||||||
@ -98,6 +102,12 @@ ccl_device_inline float shift_cos_in(float cos_in, const float frequency_multipl
|
|||||||
return val;
|
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_device_inline int bsdf_sample(KernelGlobals kg,
|
||||||
ccl_private ShaderData *sd,
|
ccl_private ShaderData *sd,
|
||||||
ccl_private const ShaderClosure *sc,
|
ccl_private const ShaderClosure *sc,
|
||||||
@ -264,11 +274,12 @@ ccl_device_inline int bsdf_sample(KernelGlobals kg,
|
|||||||
const float frequency_multiplier =
|
const float frequency_multiplier =
|
||||||
kernel_data_fetch(objects, sd->object).shadow_terminator_shading_offset;
|
kernel_data_fetch(objects, sd->object).shadow_terminator_shading_offset;
|
||||||
if (frequency_multiplier > 1.0f) {
|
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 (label & LABEL_DIFFUSE) {
|
||||||
if (!isequal(sc->N, sd->N)) {
|
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;
|
label = LABEL_TRANSMIT | LABEL_GLOSSY;
|
||||||
break;
|
break;
|
||||||
case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
|
case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
|
||||||
if (is_transmission)
|
if (bsdf_is_transmission(sc, omega_in))
|
||||||
label = LABEL_TRANSMIT | LABEL_GLOSSY;
|
label = LABEL_TRANSMIT | LABEL_GLOSSY;
|
||||||
else
|
else
|
||||||
label = LABEL_REFLECT | LABEL_GLOSSY;
|
label = LABEL_REFLECT | LABEL_GLOSSY;
|
||||||
@ -531,179 +542,104 @@ ccl_device_inline
|
|||||||
ccl_private ShaderData *sd,
|
ccl_private ShaderData *sd,
|
||||||
ccl_private const ShaderClosure *sc,
|
ccl_private const ShaderClosure *sc,
|
||||||
const float3 omega_in,
|
const float3 omega_in,
|
||||||
const bool is_transmission,
|
|
||||||
ccl_private float *pdf)
|
ccl_private float *pdf)
|
||||||
{
|
{
|
||||||
Spectrum eval = zero_spectrum();
|
Spectrum eval = zero_spectrum();
|
||||||
|
|
||||||
if (!is_transmission) {
|
switch (sc->type) {
|
||||||
switch (sc->type) {
|
case CLOSURE_BSDF_DIFFUSE_ID:
|
||||||
case CLOSURE_BSDF_DIFFUSE_ID:
|
eval = bsdf_diffuse_eval(sc, sd->I, omega_in, pdf);
|
||||||
eval = bsdf_diffuse_eval_reflect(sc, sd->I, omega_in, pdf);
|
break;
|
||||||
break;
|
|
||||||
#if defined(__SVM__) || defined(__OSL__)
|
#if defined(__SVM__) || defined(__OSL__)
|
||||||
case CLOSURE_BSDF_OREN_NAYAR_ID:
|
case CLOSURE_BSDF_OREN_NAYAR_ID:
|
||||||
eval = bsdf_oren_nayar_eval_reflect(sc, sd->I, omega_in, pdf);
|
eval = bsdf_oren_nayar_eval(sc, sd->I, omega_in, pdf);
|
||||||
break;
|
break;
|
||||||
# ifdef __OSL__
|
# ifdef __OSL__
|
||||||
case CLOSURE_BSDF_PHONG_RAMP_ID:
|
case CLOSURE_BSDF_PHONG_RAMP_ID:
|
||||||
eval = bsdf_phong_ramp_eval_reflect(sc, sd->I, omega_in, pdf);
|
eval = bsdf_phong_ramp_eval(sc, sd->I, omega_in, pdf);
|
||||||
break;
|
break;
|
||||||
case CLOSURE_BSDF_DIFFUSE_RAMP_ID:
|
case CLOSURE_BSDF_DIFFUSE_RAMP_ID:
|
||||||
eval = bsdf_diffuse_ramp_eval_reflect(sc, sd->I, omega_in, pdf);
|
eval = bsdf_diffuse_ramp_eval(sc, sd->I, omega_in, pdf);
|
||||||
break;
|
break;
|
||||||
# endif
|
# endif
|
||||||
case CLOSURE_BSDF_TRANSLUCENT_ID:
|
case CLOSURE_BSDF_TRANSLUCENT_ID:
|
||||||
eval = bsdf_translucent_eval_reflect(sc, sd->I, omega_in, pdf);
|
eval = bsdf_translucent_eval(sc, sd->I, omega_in, pdf);
|
||||||
break;
|
break;
|
||||||
case CLOSURE_BSDF_REFLECTION_ID:
|
case CLOSURE_BSDF_REFLECTION_ID:
|
||||||
eval = bsdf_reflection_eval_reflect(sc, sd->I, omega_in, pdf);
|
eval = bsdf_reflection_eval(sc, sd->I, omega_in, pdf);
|
||||||
break;
|
break;
|
||||||
case CLOSURE_BSDF_REFRACTION_ID:
|
case CLOSURE_BSDF_REFRACTION_ID:
|
||||||
eval = bsdf_refraction_eval_reflect(sc, sd->I, omega_in, pdf);
|
eval = bsdf_refraction_eval(sc, sd->I, omega_in, pdf);
|
||||||
break;
|
break;
|
||||||
case CLOSURE_BSDF_TRANSPARENT_ID:
|
case CLOSURE_BSDF_TRANSPARENT_ID:
|
||||||
eval = bsdf_transparent_eval_reflect(sc, sd->I, omega_in, pdf);
|
eval = bsdf_transparent_eval(sc, sd->I, omega_in, pdf);
|
||||||
break;
|
break;
|
||||||
case CLOSURE_BSDF_MICROFACET_GGX_ID:
|
case CLOSURE_BSDF_MICROFACET_GGX_ID:
|
||||||
case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
|
case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
|
||||||
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
|
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
|
||||||
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
|
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
|
||||||
eval = bsdf_microfacet_ggx_eval_reflect(sc, sd->I, omega_in, pdf);
|
eval = bsdf_microfacet_ggx_eval(sc, sd->I, omega_in, pdf);
|
||||||
break;
|
break;
|
||||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
|
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
|
||||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_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);
|
eval = bsdf_microfacet_multi_ggx_eval(sc, sd->I, omega_in, pdf, &sd->lcg_state);
|
||||||
break;
|
break;
|
||||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
|
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
|
||||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
|
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
|
||||||
eval = bsdf_microfacet_multi_ggx_glass_eval_reflect(
|
eval = bsdf_microfacet_multi_ggx_glass_eval(sc, sd->I, omega_in, pdf, &sd->lcg_state);
|
||||||
sc, sd->I, omega_in, pdf, &sd->lcg_state);
|
break;
|
||||||
break;
|
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
|
||||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
|
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
|
||||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
|
eval = bsdf_microfacet_beckmann_eval(sc, sd->I, omega_in, pdf);
|
||||||
eval = bsdf_microfacet_beckmann_eval_reflect(sc, sd->I, omega_in, pdf);
|
break;
|
||||||
break;
|
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
|
||||||
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
|
eval = bsdf_ashikhmin_shirley_eval(sc, sd->I, omega_in, pdf);
|
||||||
eval = bsdf_ashikhmin_shirley_eval_reflect(sc, sd->I, omega_in, pdf);
|
break;
|
||||||
break;
|
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
|
||||||
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
|
eval = bsdf_ashikhmin_velvet_eval(sc, sd->I, omega_in, pdf);
|
||||||
eval = bsdf_ashikhmin_velvet_eval_reflect(sc, sd->I, omega_in, pdf);
|
break;
|
||||||
break;
|
case CLOSURE_BSDF_DIFFUSE_TOON_ID:
|
||||||
case CLOSURE_BSDF_DIFFUSE_TOON_ID:
|
eval = bsdf_diffuse_toon_eval(sc, sd->I, omega_in, pdf);
|
||||||
eval = bsdf_diffuse_toon_eval_reflect(sc, sd->I, omega_in, pdf);
|
break;
|
||||||
break;
|
case CLOSURE_BSDF_GLOSSY_TOON_ID:
|
||||||
case CLOSURE_BSDF_GLOSSY_TOON_ID:
|
eval = bsdf_glossy_toon_eval(sc, sd->I, omega_in, pdf);
|
||||||
eval = bsdf_glossy_toon_eval_reflect(sc, sd->I, omega_in, pdf);
|
break;
|
||||||
break;
|
case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
|
||||||
case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
|
eval = bsdf_principled_hair_eval(kg, sd, sc, omega_in, pdf);
|
||||||
eval = bsdf_principled_hair_eval(kg, sd, sc, omega_in, pdf);
|
break;
|
||||||
break;
|
case CLOSURE_BSDF_HAIR_REFLECTION_ID:
|
||||||
case CLOSURE_BSDF_HAIR_REFLECTION_ID:
|
eval = bsdf_hair_reflection_eval(sc, sd->I, omega_in, pdf);
|
||||||
eval = bsdf_hair_reflection_eval_reflect(sc, sd->I, omega_in, pdf);
|
break;
|
||||||
break;
|
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
|
||||||
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
|
eval = bsdf_hair_transmission_eval(sc, sd->I, omega_in, pdf);
|
||||||
eval = bsdf_hair_transmission_eval_reflect(sc, sd->I, omega_in, pdf);
|
break;
|
||||||
break;
|
case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
|
||||||
case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
|
eval = bsdf_principled_diffuse_eval(sc, sd->I, omega_in, pdf);
|
||||||
eval = bsdf_principled_diffuse_eval_reflect(sc, sd->I, omega_in, pdf);
|
break;
|
||||||
break;
|
case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
|
||||||
case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
|
eval = bsdf_principled_sheen_eval(sc, sd->I, omega_in, pdf);
|
||||||
eval = bsdf_principled_sheen_eval_reflect(sc, sd->I, omega_in, pdf);
|
break;
|
||||||
break;
|
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (CLOSURE_IS_BSDF_DIFFUSE(sc->type)) {
|
|
||||||
if (!isequal(sc->N, sd->N)) {
|
if (CLOSURE_IS_BSDF_DIFFUSE(sc->type)) {
|
||||||
eval *= bump_shadowing_term(sd->N, sc->N, omega_in);
|
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
switch (sc->type) {
|
/* Shadow terminator offset. */
|
||||||
case CLOSURE_BSDF_DIFFUSE_ID:
|
const float frequency_multiplier =
|
||||||
eval = bsdf_diffuse_eval_transmit(sc, sd->I, omega_in, pdf);
|
kernel_data_fetch(objects, sd->object).shadow_terminator_shading_offset;
|
||||||
break;
|
if (frequency_multiplier > 1.0f) {
|
||||||
#if defined(__SVM__) || defined(__OSL__)
|
const float cosNI = dot(omega_in, sc->N);
|
||||||
case CLOSURE_BSDF_OREN_NAYAR_ID:
|
if (cosNI >= 0.0f) {
|
||||||
eval = bsdf_oren_nayar_eval_transmit(sc, sd->I, omega_in, pdf);
|
eval *= shift_cos_in(cosNI, frequency_multiplier);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WITH_CYCLES_DEBUG
|
#ifdef WITH_CYCLES_DEBUG
|
||||||
kernel_assert(*pdf >= 0.0f);
|
kernel_assert(*pdf >= 0.0f);
|
||||||
kernel_assert(eval.x >= 0.0f && eval.y >= 0.0f && eval.z >= 0.0f);
|
kernel_assert(eval.x >= 0.0f && eval.y >= 0.0f && eval.z >= 0.0f);
|
||||||
|
@ -39,11 +39,10 @@ ccl_device_inline float bsdf_ashikhmin_shirley_roughness_to_exponent(float rough
|
|||||||
return 2.0f / (roughness * roughness) - 2.0f;
|
return 2.0f / (roughness * roughness) - 2.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
ccl_device_forceinline Spectrum
|
ccl_device_forceinline Spectrum bsdf_ashikhmin_shirley_eval(ccl_private const ShaderClosure *sc,
|
||||||
bsdf_ashikhmin_shirley_eval_reflect(ccl_private const ShaderClosure *sc,
|
const float3 I,
|
||||||
const float3 I,
|
const float3 omega_in,
|
||||||
const float3 omega_in,
|
ccl_private float *pdf)
|
||||||
ccl_private float *pdf)
|
|
||||||
{
|
{
|
||||||
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
||||||
float3 N = bsdf->N;
|
float3 N = bsdf->N;
|
||||||
@ -53,70 +52,60 @@ bsdf_ashikhmin_shirley_eval_reflect(ccl_private const ShaderClosure *sc,
|
|||||||
|
|
||||||
float out = 0.0f;
|
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;
|
*pdf = 0.0f;
|
||||||
return zero_spectrum();
|
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
|
NdotI = fmaxf(NdotI, 1e-6f);
|
||||||
* (first derivative disc., but cancels the HdotI in the pdf nicely) */
|
NdotO = fmaxf(NdotO, 1e-6f);
|
||||||
float pump = 1.0f / fmaxf(1e-6f, (HdotI * fmaxf(NdotO, NdotI)));
|
float3 H = normalize(omega_in + I);
|
||||||
/* pump from d-brdf paper */
|
float HdotI = fmaxf(fabsf(dot(H, I)), 1e-6f);
|
||||||
/*float pump = 1.0f / fmaxf(1e-4f, ((NdotO + NdotI) * (NdotO*NdotI))); */
|
float HdotN = fmaxf(dot(H, N), 1e-6f);
|
||||||
|
|
||||||
float n_x = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_x);
|
/* pump from original paper
|
||||||
float n_y = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_y);
|
* (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) {
|
float n_x = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_x);
|
||||||
/* isotropic */
|
float n_y = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_y);
|
||||||
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;
|
if (n_x == n_y) {
|
||||||
/* this is p_h / 4(H.I) (conversion from 'wh measure' to 'wi measure', eq. 8 in paper). */
|
/* isotropic */
|
||||||
*pdf = norm * lobe / HdotI;
|
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 {
|
else {
|
||||||
/* anisotropic */
|
lobe = 1.0f;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
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);
|
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,
|
ccl_device_inline void bsdf_ashikhmin_shirley_sample_first_quadrant(float n_x,
|
||||||
float n_y,
|
float n_y,
|
||||||
float randu,
|
float randu,
|
||||||
@ -146,81 +135,84 @@ ccl_device int bsdf_ashikhmin_shirley_sample(ccl_private const ShaderClosure *sc
|
|||||||
int label = LABEL_REFLECT | LABEL_GLOSSY;
|
int label = LABEL_REFLECT | LABEL_GLOSSY;
|
||||||
|
|
||||||
float NdotI = dot(N, I);
|
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_x = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_x);
|
||||||
float n_y = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_y);
|
float n_y = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_y);
|
||||||
|
|
||||||
/* get x,y basis on the surface for anisotropy */
|
/* get x,y basis on the surface for anisotropy */
|
||||||
float3 X, Y;
|
float3 X, Y;
|
||||||
|
|
||||||
if (n_x == n_y)
|
if (n_x == n_y)
|
||||||
make_orthonormals(N, &X, &Y);
|
make_orthonormals(N, &X, &Y);
|
||||||
else
|
else
|
||||||
make_orthonormals_tangent(N, bsdf->T, &X, &Y);
|
make_orthonormals_tangent(N, bsdf->T, &X, &Y);
|
||||||
|
|
||||||
/* sample spherical coords for h in tangent space */
|
/* sample spherical coords for h in tangent space */
|
||||||
float phi;
|
float phi;
|
||||||
float cos_theta;
|
float cos_theta;
|
||||||
if (n_x == n_y) {
|
if (n_x == n_y) {
|
||||||
/* isotropic sampling */
|
/* isotropic sampling */
|
||||||
phi = M_2PI_F * randu;
|
phi = M_2PI_F * randu;
|
||||||
cos_theta = powf(randv, 1.0f / (n_x + 1.0f));
|
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 {
|
else if (randu < 0.5f) { /* second quadrant */
|
||||||
/* anisotropic sampling */
|
float remapped_randu = 4.0f * (.5f - randu);
|
||||||
if (randu < 0.25f) { /* first quadrant */
|
bsdf_ashikhmin_shirley_sample_first_quadrant(
|
||||||
float remapped_randu = 4.0f * randu;
|
n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
|
||||||
bsdf_ashikhmin_shirley_sample_first_quadrant(
|
phi = M_PI_F - phi;
|
||||||
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.75f) { /* third quadrant */
|
||||||
/* get half vector in tangent space */
|
float remapped_randu = 4.0f * (randu - 0.5f);
|
||||||
float sin_theta = sqrtf(fmaxf(0.0f, 1.0f - cos_theta * cos_theta));
|
bsdf_ashikhmin_shirley_sample_first_quadrant(
|
||||||
float cos_phi = cosf(phi);
|
n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
|
||||||
float sin_phi = sinf(phi); /* no sqrt(1-cos^2) here b/c it causes artifacts */
|
phi = M_PI_F + phi;
|
||||||
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 {
|
else { /* fourth quadrant */
|
||||||
/* leave the rest to eval_reflect */
|
float remapped_randu = 4.0f * (1.0f - randu);
|
||||||
*eval = bsdf_ashikhmin_shirley_eval_reflect(sc, I, *omega_in, pdf);
|
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;
|
return label;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,10 +31,10 @@ ccl_device int bsdf_ashikhmin_velvet_setup(ccl_private VelvetBsdf *bsdf)
|
|||||||
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ccl_device Spectrum bsdf_ashikhmin_velvet_eval_reflect(ccl_private const ShaderClosure *sc,
|
ccl_device Spectrum bsdf_ashikhmin_velvet_eval(ccl_private const ShaderClosure *sc,
|
||||||
const float3 I,
|
const float3 I,
|
||||||
const float3 omega_in,
|
const float3 omega_in,
|
||||||
ccl_private float *pdf)
|
ccl_private float *pdf)
|
||||||
{
|
{
|
||||||
ccl_private const VelvetBsdf *bsdf = (ccl_private const VelvetBsdf *)sc;
|
ccl_private const VelvetBsdf *bsdf = (ccl_private const VelvetBsdf *)sc;
|
||||||
float m_invsigma2 = bsdf->invsigma2;
|
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 cosNO = dot(N, I);
|
||||||
float cosNI = dot(N, omega_in);
|
float cosNI = dot(N, omega_in);
|
||||||
if (cosNO > 0 && cosNI > 0) {
|
if (!(cosNO > 0 && cosNI > 0)) {
|
||||||
float3 H = normalize(omega_in + I);
|
*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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*pdf = 0.0f;
|
float3 H = normalize(omega_in + I);
|
||||||
return zero_spectrum();
|
|
||||||
}
|
|
||||||
|
|
||||||
ccl_device Spectrum bsdf_ashikhmin_velvet_eval_transmit(ccl_private const ShaderClosure *sc,
|
float cosNH = dot(N, H);
|
||||||
const float3 I,
|
float cosHO = fabsf(dot(I, H));
|
||||||
const float3 omega_in,
|
|
||||||
ccl_private float *pdf)
|
if (!(fabsf(cosNH) < 1.0f - 1e-5f && cosHO > 1e-5f)) {
|
||||||
{
|
*pdf = 0.0f;
|
||||||
*pdf = 0.0f;
|
return zero_spectrum();
|
||||||
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,
|
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
|
// distribution over the hemisphere
|
||||||
sample_uniform_hemisphere(N, randu, randv, omega_in, pdf);
|
sample_uniform_hemisphere(N, randu, randv, omega_in, pdf);
|
||||||
|
|
||||||
if (dot(Ng, *omega_in) > 0) {
|
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 {
|
|
||||||
*pdf = 0.0f;
|
*pdf = 0.0f;
|
||||||
*eval = zero_spectrum();
|
*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;
|
return LABEL_REFLECT | LABEL_DIFFUSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,10 +26,10 @@ ccl_device int bsdf_diffuse_setup(ccl_private DiffuseBsdf *bsdf)
|
|||||||
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ccl_device Spectrum bsdf_diffuse_eval_reflect(ccl_private const ShaderClosure *sc,
|
ccl_device Spectrum bsdf_diffuse_eval(ccl_private const ShaderClosure *sc,
|
||||||
const float3 I,
|
const float3 I,
|
||||||
const float3 omega_in,
|
const float3 omega_in,
|
||||||
ccl_private float *pdf)
|
ccl_private float *pdf)
|
||||||
{
|
{
|
||||||
ccl_private const DiffuseBsdf *bsdf = (ccl_private const DiffuseBsdf *)sc;
|
ccl_private const DiffuseBsdf *bsdf = (ccl_private const DiffuseBsdf *)sc;
|
||||||
float3 N = bsdf->N;
|
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);
|
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,
|
ccl_device int bsdf_diffuse_sample(ccl_private const ShaderClosure *sc,
|
||||||
float3 Ng,
|
float3 Ng,
|
||||||
float3 I,
|
float3 I,
|
||||||
@ -81,19 +72,10 @@ ccl_device int bsdf_translucent_setup(ccl_private DiffuseBsdf *bsdf)
|
|||||||
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ccl_device Spectrum bsdf_translucent_eval_reflect(ccl_private const ShaderClosure *sc,
|
ccl_device Spectrum bsdf_translucent_eval(ccl_private const ShaderClosure *sc,
|
||||||
const float3 I,
|
const float3 I,
|
||||||
const float3 omega_in,
|
const float3 omega_in,
|
||||||
ccl_private float *pdf)
|
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_private const DiffuseBsdf *bsdf = (ccl_private const DiffuseBsdf *)sc;
|
ccl_private const DiffuseBsdf *bsdf = (ccl_private const DiffuseBsdf *)sc;
|
||||||
float3 N = bsdf->N;
|
float3 N = bsdf->N;
|
||||||
|
@ -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,
|
ccl_device Spectrum bsdf_diffuse_ramp_eval(ccl_private const ShaderClosure *sc,
|
||||||
const float3 I,
|
const float3 I,
|
||||||
const float3 omega_in,
|
const float3 omega_in,
|
||||||
ccl_private float *pdf)
|
ccl_private float *pdf)
|
||||||
{
|
{
|
||||||
const DiffuseRampBsdf *bsdf = (const DiffuseRampBsdf *)sc;
|
const DiffuseRampBsdf *bsdf = (const DiffuseRampBsdf *)sc;
|
||||||
float3 N = bsdf->N;
|
float3 N = bsdf->N;
|
||||||
|
|
||||||
float cos_pi = fmaxf(dot(N, omega_in), 0.0f);
|
float cos_pi = fmaxf(dot(N, omega_in), 0.0f);
|
||||||
*pdf = cos_pi * M_1_PI_F;
|
if (cos_pi >= 0.0f) {
|
||||||
return rgb_to_spectrum(bsdf_diffuse_ramp_get_color(bsdf->colors, cos_pi) * M_1_PI_F);
|
*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,
|
else {
|
||||||
const float3 I,
|
*pdf = 0.0f;
|
||||||
const float3 omega_in,
|
return zero_spectrum();
|
||||||
ccl_private float *pdf)
|
}
|
||||||
{
|
|
||||||
return zero_spectrum();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ccl_device int bsdf_diffuse_ramp_sample(ccl_private const ShaderClosure *sc,
|
ccl_device int bsdf_diffuse_ramp_sample(ccl_private const ShaderClosure *sc,
|
||||||
|
@ -37,12 +37,17 @@ ccl_device int bsdf_hair_transmission_setup(ccl_private HairBsdf *bsdf)
|
|||||||
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ccl_device Spectrum bsdf_hair_reflection_eval_reflect(ccl_private const ShaderClosure *sc,
|
ccl_device Spectrum bsdf_hair_reflection_eval(ccl_private const ShaderClosure *sc,
|
||||||
const float3 I,
|
const float3 I,
|
||||||
const float3 omega_in,
|
const float3 omega_in,
|
||||||
ccl_private float *pdf)
|
ccl_private float *pdf)
|
||||||
{
|
{
|
||||||
ccl_private const HairBsdf *bsdf = (ccl_private const HairBsdf *)sc;
|
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;
|
float offset = bsdf->offset;
|
||||||
float3 Tg = bsdf->T;
|
float3 Tg = bsdf->T;
|
||||||
float roughness1 = bsdf->roughness1;
|
float roughness1 = bsdf->roughness1;
|
||||||
@ -84,30 +89,17 @@ ccl_device Spectrum bsdf_hair_reflection_eval_reflect(ccl_private const ShaderCl
|
|||||||
return make_spectrum(*pdf);
|
return make_spectrum(*pdf);
|
||||||
}
|
}
|
||||||
|
|
||||||
ccl_device Spectrum bsdf_hair_transmission_eval_reflect(ccl_private const ShaderClosure *sc,
|
ccl_device Spectrum bsdf_hair_transmission_eval(ccl_private const ShaderClosure *sc,
|
||||||
const float3 I,
|
const float3 I,
|
||||||
const float3 omega_in,
|
const float3 omega_in,
|
||||||
ccl_private float *pdf)
|
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_private const HairBsdf *bsdf = (ccl_private const HairBsdf *)sc;
|
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;
|
float offset = bsdf->offset;
|
||||||
float3 Tg = bsdf->T;
|
float3 Tg = bsdf->T;
|
||||||
float roughness1 = bsdf->roughness1;
|
float roughness1 = bsdf->roughness1;
|
||||||
|
@ -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]. */
|
/* Remaps the given angle to [-pi, pi]. */
|
||||||
ccl_device_inline float wrap_angle(float a)
|
ccl_device_inline float wrap_angle(float a)
|
||||||
{
|
{
|
||||||
while (a > M_PI_F) {
|
return (a + M_PI_F) - M_2PI_F * floorf((a + M_PI_F) / M_2PI_F) - M_PI_F;
|
||||||
a -= M_2PI_F;
|
|
||||||
}
|
|
||||||
while (a < -M_PI_F) {
|
|
||||||
a += M_2PI_F;
|
|
||||||
}
|
|
||||||
return a;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Logistic distribution function. */
|
/* 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));
|
kernel_assert(isfinite_safe(sd->P) && isfinite_safe(sd->ray_length));
|
||||||
|
|
||||||
ccl_private const PrincipledHairBSDF *bsdf = (ccl_private const PrincipledHairBSDF *)sc;
|
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);
|
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));
|
||||||
float3 wi = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
|
const float3 wi = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
|
||||||
|
|
||||||
float sin_theta_o = wo.x;
|
const float sin_theta_o = wo.x;
|
||||||
float cos_theta_o = cos_from_sin(sin_theta_o);
|
const float cos_theta_o = cos_from_sin(sin_theta_o);
|
||||||
float phi_o = atan2f(wo.z, wo.y);
|
const float phi_o = atan2f(wo.z, wo.y);
|
||||||
|
|
||||||
float sin_theta_t = sin_theta_o / bsdf->eta;
|
const float sin_theta_t = sin_theta_o / bsdf->eta;
|
||||||
float cos_theta_t = cos_from_sin(sin_theta_t);
|
const float cos_theta_t = cos_from_sin(sin_theta_t);
|
||||||
|
|
||||||
float sin_gamma_o = bsdf->extra->geom.w;
|
const float sin_gamma_o = bsdf->extra->geom.w;
|
||||||
float cos_gamma_o = cos_from_sin(sin_gamma_o);
|
const float cos_gamma_o = cos_from_sin(sin_gamma_o);
|
||||||
float gamma_o = safe_asinf(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));
|
const 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);
|
const float cos_gamma_t = cos_from_sin(sin_gamma_t);
|
||||||
float gamma_t = safe_asinf(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];
|
Spectrum Ap[4];
|
||||||
float Ap_energy[4];
|
float Ap_energy[4];
|
||||||
hair_attenuation(
|
hair_attenuation(
|
||||||
kg, fresnel_dielectric_cos(cos_theta_o * cos_gamma_o, bsdf->eta), T, Ap, Ap_energy);
|
kg, fresnel_dielectric_cos(cos_theta_o * cos_gamma_o, bsdf->eta), T, Ap, Ap_energy);
|
||||||
|
|
||||||
float sin_theta_i = wi.x;
|
const float sin_theta_i = wi.x;
|
||||||
float cos_theta_i = cos_from_sin(sin_theta_i);
|
const float cos_theta_i = cos_from_sin(sin_theta_i);
|
||||||
float phi_i = atan2f(wi.z, wi.y);
|
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];
|
float angles[6];
|
||||||
hair_alpha_angles(sin_theta_i, cos_theta_i, bsdf->alpha, angles);
|
hair_alpha_angles(sin_theta_i, cos_theta_i, bsdf->alpha, angles);
|
||||||
|
|
||||||
Spectrum F;
|
Spectrum F = zero_spectrum();
|
||||||
float F_energy;
|
float F_energy = 0.0f;
|
||||||
float Mp, Np;
|
|
||||||
|
|
||||||
/* Primary specular (R). */
|
/* Primary specular (R), Transmission (TT) and Secondary Specular (TRT). */
|
||||||
Mp = longitudinal_scattering(angles[0], angles[1], sin_theta_o, cos_theta_o, bsdf->m0_roughness);
|
for (int i = 0; i < 3; i++) {
|
||||||
Np = azimuthal_scattering(phi, 0, bsdf->s, gamma_o, gamma_t);
|
const float Mp = longitudinal_scattering(angles[2 * i],
|
||||||
F = Ap[0] * Mp * Np;
|
angles[2 * i + 1],
|
||||||
F_energy = Ap_energy[0] * Mp * Np;
|
sin_theta_o,
|
||||||
kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy));
|
cos_theta_o,
|
||||||
|
(i == 0) ? bsdf->m0_roughness :
|
||||||
/* Transmission (TT). */
|
(i == 1) ? 0.25f * bsdf->v :
|
||||||
Mp = longitudinal_scattering(angles[2], angles[3], sin_theta_o, cos_theta_o, 0.25f * bsdf->v);
|
4.0f * bsdf->v);
|
||||||
Np = azimuthal_scattering(phi, 1, bsdf->s, gamma_o, gamma_t);
|
const float Np = azimuthal_scattering(phi, i, bsdf->s, gamma_o, gamma_t);
|
||||||
F += Ap[1] * Mp * Np;
|
F += Ap[i] * Mp * Np;
|
||||||
F_energy += Ap_energy[1] * Mp * Np;
|
F_energy += Ap_energy[i] * Mp * Np;
|
||||||
kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy));
|
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));
|
|
||||||
|
|
||||||
/* Residual component (TRRT+). */
|
/* 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;
|
const float Mp = longitudinal_scattering(
|
||||||
F += Ap[3] * Mp * Np;
|
sin_theta_i, cos_theta_i, sin_theta_o, cos_theta_o, 4.0f * bsdf->v);
|
||||||
F_energy += Ap_energy[3] * Mp * Np;
|
const float Np = M_1_2PI_F;
|
||||||
kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy));
|
F += Ap[3] * Mp * Np;
|
||||||
|
F_energy += Ap_energy[3] * Mp * Np;
|
||||||
|
kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy));
|
||||||
|
}
|
||||||
|
|
||||||
*pdf = F_energy;
|
*pdf = F_energy;
|
||||||
return F;
|
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);
|
*sampled_roughness = make_float2(bsdf->m0_roughness, bsdf->m0_roughness);
|
||||||
*eta = bsdf->eta;
|
*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);
|
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];
|
float2 u[2];
|
||||||
u[0] = make_float2(randu, randv);
|
u[0] = make_float2(randu, randv);
|
||||||
u[1].x = lcg_step_float(&sd->lcg_state);
|
u[1].x = lcg_step_float(&sd->lcg_state);
|
||||||
u[1].y = lcg_step_float(&sd->lcg_state);
|
u[1].y = lcg_step_float(&sd->lcg_state);
|
||||||
|
|
||||||
float sin_theta_o = wo.x;
|
const float sin_theta_o = wo.x;
|
||||||
float cos_theta_o = cos_from_sin(sin_theta_o);
|
const float cos_theta_o = cos_from_sin(sin_theta_o);
|
||||||
float phi_o = atan2f(wo.z, wo.y);
|
const float phi_o = atan2f(wo.z, wo.y);
|
||||||
|
|
||||||
float sin_theta_t = sin_theta_o / bsdf->eta;
|
const float sin_theta_t = sin_theta_o / bsdf->eta;
|
||||||
float cos_theta_t = cos_from_sin(sin_theta_t);
|
const float cos_theta_t = cos_from_sin(sin_theta_t);
|
||||||
|
|
||||||
float sin_gamma_o = bsdf->extra->geom.w;
|
const float sin_gamma_o = bsdf->extra->geom.w;
|
||||||
float cos_gamma_o = cos_from_sin(sin_gamma_o);
|
const float cos_gamma_o = cos_from_sin(sin_gamma_o);
|
||||||
float gamma_o = safe_asinf(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));
|
const 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);
|
const float cos_gamma_t = cos_from_sin(sin_gamma_t);
|
||||||
float gamma_t = safe_asinf(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];
|
Spectrum Ap[4];
|
||||||
float Ap_energy[4];
|
float Ap_energy[4];
|
||||||
hair_attenuation(
|
hair_attenuation(
|
||||||
@ -414,7 +404,7 @@ ccl_device int bsdf_principled_hair_sample(KernelGlobals kg,
|
|||||||
}
|
}
|
||||||
|
|
||||||
u[1].x = max(u[1].x, 1e-5f);
|
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 +
|
float sin_theta_i = -fac * sin_theta_o +
|
||||||
cos_from_sin(fac) * cosf(M_2PI_F * u[1].y) * cos_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);
|
float cos_theta_i = cos_from_sin(sin_theta_i);
|
||||||
@ -433,41 +423,37 @@ ccl_device int bsdf_principled_hair_sample(KernelGlobals kg,
|
|||||||
else {
|
else {
|
||||||
phi = M_2PI_F * u[0].y;
|
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);
|
hair_alpha_angles(sin_theta_i, cos_theta_i, bsdf->alpha, angles);
|
||||||
|
|
||||||
Spectrum F;
|
Spectrum F = zero_spectrum();
|
||||||
float F_energy;
|
float F_energy = 0.0f;
|
||||||
float Mp, Np;
|
|
||||||
|
|
||||||
/* Primary specular (R). */
|
/* Primary specular (R), Transmission (TT) and Secondary Specular (TRT). */
|
||||||
Mp = longitudinal_scattering(angles[0], angles[1], sin_theta_o, cos_theta_o, bsdf->m0_roughness);
|
for (int i = 0; i < 3; i++) {
|
||||||
Np = azimuthal_scattering(phi, 0, bsdf->s, gamma_o, gamma_t);
|
const float Mp = longitudinal_scattering(angles[2 * i],
|
||||||
F = Ap[0] * Mp * Np;
|
angles[2 * i + 1],
|
||||||
F_energy = Ap_energy[0] * Mp * Np;
|
sin_theta_o,
|
||||||
kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy));
|
cos_theta_o,
|
||||||
|
(i == 0) ? bsdf->m0_roughness :
|
||||||
/* Transmission (TT). */
|
(i == 1) ? 0.25f * bsdf->v :
|
||||||
Mp = longitudinal_scattering(angles[2], angles[3], sin_theta_o, cos_theta_o, 0.25f * bsdf->v);
|
4.0f * bsdf->v);
|
||||||
Np = azimuthal_scattering(phi, 1, bsdf->s, gamma_o, gamma_t);
|
const float Np = azimuthal_scattering(phi, i, bsdf->s, gamma_o, gamma_t);
|
||||||
F += Ap[1] * Mp * Np;
|
F += Ap[i] * Mp * Np;
|
||||||
F_energy += Ap_energy[1] * Mp * Np;
|
F_energy += Ap_energy[i] * Mp * Np;
|
||||||
kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy));
|
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));
|
|
||||||
|
|
||||||
/* Residual component (TRRT+). */
|
/* 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;
|
const float Mp = longitudinal_scattering(
|
||||||
F += Ap[3] * Mp * Np;
|
sin_theta_i, cos_theta_i, sin_theta_o, cos_theta_o, 4.0f * bsdf->v);
|
||||||
F_energy += Ap_energy[3] * Mp * Np;
|
const float Np = M_1_2PI_F;
|
||||||
kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy));
|
F += Ap[3] * Mp * Np;
|
||||||
|
F_energy += Ap_energy[3] * Mp * Np;
|
||||||
|
kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy));
|
||||||
|
}
|
||||||
|
|
||||||
*eval = F;
|
*eval = F;
|
||||||
*pdf = F_energy;
|
*pdf = F_energy;
|
||||||
|
@ -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);
|
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 I,
|
||||||
const float3 omega_in,
|
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;
|
if (!(cosNI > 0 && cosNO > 0)) {
|
||||||
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) {
|
|
||||||
*pdf = 0.0f;
|
*pdf = 0.0f;
|
||||||
return zero_spectrum();
|
return zero_spectrum();
|
||||||
}
|
}
|
||||||
|
|
||||||
float cosNO = dot(N, I);
|
/* get half vector */
|
||||||
float cosNI = dot(N, omega_in);
|
float3 m = normalize(omega_in + I);
|
||||||
|
float alpha2 = alpha_x * alpha_y;
|
||||||
|
float D, G1o, G1i;
|
||||||
|
|
||||||
if (cosNI > 0 && cosNO > 0) {
|
if (alpha_x == alpha_y) {
|
||||||
/* get half vector */
|
/* isotropic
|
||||||
float3 m = normalize(omega_in + I);
|
* eq. 20: (F*G*D)/(4*in*on)
|
||||||
float alpha2 = alpha_x * alpha_y;
|
* eq. 33: first we calculate D(m) */
|
||||||
float D, G1o, G1i;
|
float cosThetaM = dot(N, m);
|
||||||
|
float cosThetaM2 = cosThetaM * cosThetaM;
|
||||||
|
float cosThetaM4 = cosThetaM2 * cosThetaM2;
|
||||||
|
float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
|
||||||
|
|
||||||
if (alpha_x == alpha_y) {
|
if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) {
|
||||||
/* isotropic
|
/* use GTR1 for clearcoat */
|
||||||
* eq. 20: (F*G*D)/(4*in*on)
|
D = D_GTR1(cosThetaM, bsdf->alpha_x);
|
||||||
* 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) {
|
/* the alpha value for clearcoat is a fixed 0.25 => alpha2 = 0.25 * 0.25 */
|
||||||
/* use GTR1 for clearcoat */
|
alpha2 = 0.0625f;
|
||||||
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)));
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* anisotropic */
|
/* use GTR2 otherwise */
|
||||||
float3 X, Y, Z = N;
|
D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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 */
|
/* distribution */
|
||||||
float common = D * 0.25f / cosNO;
|
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);
|
float cosThetaM = local_m.z;
|
||||||
if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) {
|
float cosThetaM2 = cosThetaM * cosThetaM;
|
||||||
F *= 0.25f * bsdf->extra->clearcoat;
|
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
|
/* G1(i,m) and G1(o,m) */
|
||||||
* `pm = Dw = G1o * dot(m, I) * D / dot(N, I);` */
|
float tanThetaO2 = (1 - cosNO * cosNO) / (cosNO * cosNO);
|
||||||
|
float cosPhiO = dot(I, X);
|
||||||
|
float sinPhiO = dot(I, Y);
|
||||||
|
|
||||||
/* eq. 38 - but see also:
|
float alphaO2 = (cosPhiO * cosPhiO) * (alpha_x * alpha_x) +
|
||||||
* eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf
|
(sinPhiO * sinPhiO) * (alpha_y * alpha_y);
|
||||||
* `pdf = pm * 0.25 / dot(m, I);` */
|
alphaO2 /= cosPhiO * cosPhiO + sinPhiO * sinPhiO;
|
||||||
*pdf = G1o * common;
|
|
||||||
|
|
||||||
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 I,
|
||||||
const float3 omega_in,
|
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) {
|
if (cosNO <= 0 || cosNI >= 0) {
|
||||||
*pdf = 0.0f;
|
*pdf = 0.0f;
|
||||||
return zero_spectrum(); /* vectors on same side -- not possible */
|
return zero_spectrum(); /* vectors on same side -- not possible */
|
||||||
}
|
}
|
||||||
/* compute half-vector of the refraction (eq. 16) */
|
/* compute half-vector of the refraction (eq. 16) */
|
||||||
|
float m_eta = bsdf->ior;
|
||||||
float3 ht = -(m_eta * omega_in + I);
|
float3 ht = -(m_eta * omega_in + I);
|
||||||
float3 Ht = normalize(ht);
|
float3 Ht = normalize(ht);
|
||||||
float cosHO = dot(Ht, I);
|
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);
|
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_device int bsdf_microfacet_ggx_sample(KernelGlobals kg,
|
||||||
ccl_private const ShaderClosure *sc,
|
ccl_private const ShaderClosure *sc,
|
||||||
float3 Ng,
|
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);
|
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 I,
|
||||||
const float3 omega_in,
|
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;
|
if (!(cosNO > 0 && cosNI > 0)) {
|
||||||
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) {
|
|
||||||
*pdf = 0.0f;
|
*pdf = 0.0f;
|
||||||
return zero_spectrum();
|
return zero_spectrum();
|
||||||
}
|
}
|
||||||
|
|
||||||
float cosNO = dot(N, I);
|
/* get half vector */
|
||||||
float cosNI = dot(N, omega_in);
|
float3 m = normalize(omega_in + I);
|
||||||
|
|
||||||
if (cosNO > 0 && cosNI > 0) {
|
float alpha2 = alpha_x * alpha_y;
|
||||||
/* get half vector */
|
float D, G1o, G1i;
|
||||||
float3 m = normalize(omega_in + I);
|
|
||||||
|
|
||||||
float alpha2 = alpha_x * alpha_y;
|
if (alpha_x == alpha_y) {
|
||||||
float D, G1o, G1i;
|
/* 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) {
|
/* eq. 26, 27: now calculate G1(i,m) and G1(o,m) */
|
||||||
/* isotropic
|
G1o = bsdf_beckmann_G1(alpha_x, cosNO);
|
||||||
* eq. 20: (F*G*D)/(4*in*on)
|
G1i = bsdf_beckmann_G1(alpha_x, cosNI);
|
||||||
* eq. 25: first we calculate D(m) */
|
}
|
||||||
float cosThetaM = dot(N, m);
|
else {
|
||||||
float cosThetaM2 = cosThetaM * cosThetaM;
|
/* anisotropic */
|
||||||
float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
|
float3 X, Y, Z = N;
|
||||||
float cosThetaM4 = cosThetaM2 * cosThetaM2;
|
make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
|
||||||
D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 * cosThetaM4);
|
|
||||||
|
|
||||||
/* eq. 26, 27: now calculate G1(i,m) and G1(o,m) */
|
/* distribution */
|
||||||
G1o = bsdf_beckmann_G1(alpha_x, cosNO);
|
float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m));
|
||||||
G1i = bsdf_beckmann_G1(alpha_x, cosNI);
|
float slope_x = -local_m.x / (local_m.z * alpha_x);
|
||||||
}
|
float slope_y = -local_m.y / (local_m.z * alpha_y);
|
||||||
else {
|
|
||||||
/* anisotropic */
|
|
||||||
float3 X, Y, Z = N;
|
|
||||||
make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
|
|
||||||
|
|
||||||
/* distribution */
|
float cosThetaM = local_m.z;
|
||||||
float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m));
|
float cosThetaM2 = cosThetaM * cosThetaM;
|
||||||
float slope_x = -local_m.x / (local_m.z * alpha_x);
|
float cosThetaM4 = cosThetaM2 * cosThetaM2;
|
||||||
float slope_y = -local_m.y / (local_m.z * alpha_y);
|
|
||||||
|
|
||||||
float cosThetaM = local_m.z;
|
D = expf(-slope_x * slope_x - slope_y * slope_y) / (M_PI_F * alpha2 * cosThetaM4);
|
||||||
float cosThetaM2 = cosThetaM * cosThetaM;
|
|
||||||
float cosThetaM4 = cosThetaM2 * cosThetaM2;
|
|
||||||
|
|
||||||
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));
|
||||||
/* G1(i,m) and G1(o,m) */
|
G1i = bsdf_beckmann_aniso_G1(alpha_x, alpha_y, cosNI, dot(omega_in, X), dot(omega_in, Y));
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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 I,
|
||||||
const float3 omega_in,
|
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) {
|
if (cosNO <= 0 || cosNI >= 0) {
|
||||||
*pdf = 0.0f;
|
*pdf = 0.0f;
|
||||||
return zero_spectrum();
|
return zero_spectrum();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const float m_eta = bsdf->ior;
|
||||||
/* compute half-vector of the refraction (eq. 16) */
|
/* compute half-vector of the refraction (eq. 16) */
|
||||||
float3 ht = -(m_eta * omega_in + I);
|
float3 ht = -(m_eta * omega_in + I);
|
||||||
float3 Ht = normalize(ht);
|
float3 Ht = normalize(ht);
|
||||||
@ -950,6 +941,30 @@ ccl_device Spectrum bsdf_microfacet_beckmann_eval_transmit(ccl_private const Sha
|
|||||||
return make_spectrum(out);
|
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_device int bsdf_microfacet_beckmann_sample(KernelGlobals kg,
|
||||||
ccl_private const ShaderClosure *sc,
|
ccl_private const ShaderClosure *sc,
|
||||||
float3 Ng,
|
float3 Ng,
|
||||||
|
@ -415,21 +415,11 @@ ccl_device int bsdf_microfacet_multi_ggx_refraction_setup(ccl_private Microfacet
|
|||||||
return bsdf_microfacet_multi_ggx_common_setup(bsdf);
|
return bsdf_microfacet_multi_ggx_common_setup(bsdf);
|
||||||
}
|
}
|
||||||
|
|
||||||
ccl_device Spectrum bsdf_microfacet_multi_ggx_eval_transmit(ccl_private const ShaderClosure *sc,
|
ccl_device Spectrum bsdf_microfacet_multi_ggx_eval(ccl_private const ShaderClosure *sc,
|
||||||
const float3 I,
|
const float3 I,
|
||||||
const float3 omega_in,
|
const float3 omega_in,
|
||||||
ccl_private float *pdf,
|
ccl_private float *pdf,
|
||||||
ccl_private uint *lcg_state)
|
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_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
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;
|
return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_NEEDS_LCG;
|
||||||
}
|
}
|
||||||
|
|
||||||
ccl_device Spectrum
|
ccl_device Spectrum bsdf_microfacet_multi_ggx_glass_eval(ccl_private const ShaderClosure *sc,
|
||||||
bsdf_microfacet_multi_ggx_glass_eval_transmit(ccl_private const ShaderClosure *sc,
|
const float3 I,
|
||||||
const float3 I,
|
const float3 omega_in,
|
||||||
const float3 omega_in,
|
ccl_private float *pdf,
|
||||||
ccl_private float *pdf,
|
ccl_private uint *lcg_state)
|
||||||
ccl_private uint *lcg_state)
|
|
||||||
{
|
{
|
||||||
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
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 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));
|
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);
|
const bool is_transmission = localO.z < 0.0f;
|
||||||
kernel_assert(*pdf >= 0.f);
|
const bool use_fresnel = !is_transmission &&
|
||||||
return mf_eval_glass(localI,
|
(bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID);
|
||||||
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));
|
|
||||||
|
|
||||||
*pdf = mf_glass_pdf(localI, localO, bsdf->alpha_x, bsdf->ior);
|
*pdf = mf_glass_pdf(localI, localO, bsdf->alpha_x, bsdf->ior);
|
||||||
kernel_assert(*pdf >= 0.f);
|
kernel_assert(*pdf >= 0.f);
|
||||||
return mf_eval_glass(localI,
|
return mf_eval_glass(localI,
|
||||||
localO,
|
localO,
|
||||||
true,
|
!is_transmission,
|
||||||
bsdf->extra->color,
|
bsdf->extra->color,
|
||||||
bsdf->alpha_x,
|
bsdf->alpha_x,
|
||||||
bsdf->alpha_y,
|
bsdf->alpha_y,
|
||||||
lcg_state,
|
lcg_state,
|
||||||
bsdf->ior,
|
bsdf->ior,
|
||||||
use_fresnel,
|
use_fresnel,
|
||||||
bsdf->extra->cspec0);
|
(is_transmission) ? bsdf->extra->color : bsdf->extra->cspec0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ccl_device int bsdf_microfacet_multi_ggx_glass_sample(KernelGlobals kg,
|
ccl_device int bsdf_microfacet_multi_ggx_glass_sample(KernelGlobals kg,
|
||||||
|
@ -47,10 +47,10 @@ ccl_device int bsdf_oren_nayar_setup(ccl_private OrenNayarBsdf *bsdf)
|
|||||||
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ccl_device Spectrum bsdf_oren_nayar_eval_reflect(ccl_private const ShaderClosure *sc,
|
ccl_device Spectrum bsdf_oren_nayar_eval(ccl_private const ShaderClosure *sc,
|
||||||
const float3 I,
|
const float3 I,
|
||||||
const float3 omega_in,
|
const float3 omega_in,
|
||||||
ccl_private float *pdf)
|
ccl_private float *pdf)
|
||||||
{
|
{
|
||||||
ccl_private const OrenNayarBsdf *bsdf = (ccl_private const OrenNayarBsdf *)sc;
|
ccl_private const OrenNayarBsdf *bsdf = (ccl_private const OrenNayarBsdf *)sc;
|
||||||
if (dot(bsdf->N, omega_in) > 0.0f) {
|
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,
|
ccl_device int bsdf_oren_nayar_sample(ccl_private const ShaderClosure *sc,
|
||||||
float3 Ng,
|
float3 Ng,
|
||||||
float3 I,
|
float3 I,
|
||||||
|
@ -44,10 +44,10 @@ ccl_device int bsdf_phong_ramp_setup(ccl_private PhongRampBsdf *bsdf)
|
|||||||
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ccl_device Spectrum bsdf_phong_ramp_eval_reflect(ccl_private const ShaderClosure *sc,
|
ccl_device Spectrum bsdf_phong_ramp_eval(ccl_private const ShaderClosure *sc,
|
||||||
const float3 I,
|
const float3 I,
|
||||||
const float3 omega_in,
|
const float3 omega_in,
|
||||||
ccl_private float *pdf)
|
ccl_private float *pdf)
|
||||||
{
|
{
|
||||||
ccl_private const PhongRampBsdf *bsdf = (ccl_private const PhongRampBsdf *)sc;
|
ccl_private const PhongRampBsdf *bsdf = (ccl_private const PhongRampBsdf *)sc;
|
||||||
float m_exponent = bsdf->exponent;
|
float m_exponent = bsdf->exponent;
|
||||||
@ -70,15 +70,6 @@ ccl_device Spectrum bsdf_phong_ramp_eval_reflect(ccl_private const ShaderClosure
|
|||||||
return zero_spectrum();
|
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)
|
ccl_device_inline float phong_ramp_exponent_to_roughness(float exponent)
|
||||||
{
|
{
|
||||||
return sqrt(1.0f / ((exponent + 2.0f) / 2.0f));
|
return sqrt(1.0f / ((exponent + 2.0f) / 2.0f));
|
||||||
|
@ -109,18 +109,17 @@ ccl_device int bsdf_principled_diffuse_setup(ccl_private PrincipledDiffuseBsdf *
|
|||||||
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ccl_device Spectrum bsdf_principled_diffuse_eval_reflect(ccl_private const ShaderClosure *sc,
|
ccl_device Spectrum bsdf_principled_diffuse_eval(ccl_private const ShaderClosure *sc,
|
||||||
const float3 I,
|
const float3 I,
|
||||||
const float3 omega_in,
|
const float3 omega_in,
|
||||||
ccl_private float *pdf)
|
ccl_private float *pdf)
|
||||||
{
|
{
|
||||||
ccl_private const PrincipledDiffuseBsdf *bsdf = (ccl_private const PrincipledDiffuseBsdf *)sc;
|
ccl_private const PrincipledDiffuseBsdf *bsdf = (ccl_private const PrincipledDiffuseBsdf *)sc;
|
||||||
|
const float3 N = bsdf->N;
|
||||||
float3 N = bsdf->N;
|
|
||||||
float3 V = I; // outgoing
|
|
||||||
float3 L = omega_in; // incoming
|
|
||||||
|
|
||||||
if (dot(N, omega_in) > 0.0f) {
|
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;
|
*pdf = fmaxf(dot(N, omega_in), 0.0f) * M_1_PI_F;
|
||||||
return bsdf_principled_diffuse_compute_brdf(bsdf, N, V, L, pdf);
|
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,
|
ccl_device int bsdf_principled_diffuse_sample(ccl_private const ShaderClosure *sc,
|
||||||
float3 Ng,
|
float3 Ng,
|
||||||
float3 I,
|
float3 I,
|
||||||
|
@ -59,19 +59,19 @@ ccl_device int bsdf_principled_sheen_setup(ccl_private const ShaderData *sd,
|
|||||||
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ccl_device Spectrum bsdf_principled_sheen_eval_reflect(ccl_private const ShaderClosure *sc,
|
ccl_device Spectrum bsdf_principled_sheen_eval(ccl_private const ShaderClosure *sc,
|
||||||
const float3 I,
|
const float3 I,
|
||||||
const float3 omega_in,
|
const float3 omega_in,
|
||||||
ccl_private float *pdf)
|
ccl_private float *pdf)
|
||||||
{
|
{
|
||||||
ccl_private const PrincipledSheenBsdf *bsdf = (ccl_private const PrincipledSheenBsdf *)sc;
|
ccl_private const PrincipledSheenBsdf *bsdf = (ccl_private const PrincipledSheenBsdf *)sc;
|
||||||
|
const float3 N = bsdf->N;
|
||||||
float3 N = bsdf->N;
|
|
||||||
float3 V = I; // outgoing
|
|
||||||
float3 L = omega_in; // incoming
|
|
||||||
float3 H = normalize(L + V);
|
|
||||||
|
|
||||||
if (dot(N, omega_in) > 0.0f) {
|
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;
|
*pdf = fmaxf(dot(N, omega_in), 0.0f) * M_1_PI_F;
|
||||||
return calculate_principled_sheen_brdf(N, V, L, H, pdf);
|
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,
|
ccl_device int bsdf_principled_sheen_sample(ccl_private const ShaderClosure *sc,
|
||||||
float3 Ng,
|
float3 Ng,
|
||||||
float3 I,
|
float3 I,
|
||||||
|
@ -18,19 +18,10 @@ ccl_device int bsdf_reflection_setup(ccl_private MicrofacetBsdf *bsdf)
|
|||||||
return SD_BSDF;
|
return SD_BSDF;
|
||||||
}
|
}
|
||||||
|
|
||||||
ccl_device Spectrum bsdf_reflection_eval_reflect(ccl_private const ShaderClosure *sc,
|
ccl_device Spectrum bsdf_reflection_eval(ccl_private const ShaderClosure *sc,
|
||||||
const float3 I,
|
const float3 I,
|
||||||
const float3 omega_in,
|
const float3 omega_in,
|
||||||
ccl_private float *pdf)
|
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)
|
|
||||||
{
|
{
|
||||||
*pdf = 0.0f;
|
*pdf = 0.0f;
|
||||||
return zero_spectrum();
|
return zero_spectrum();
|
||||||
|
@ -18,19 +18,10 @@ ccl_device int bsdf_refraction_setup(ccl_private MicrofacetBsdf *bsdf)
|
|||||||
return SD_BSDF;
|
return SD_BSDF;
|
||||||
}
|
}
|
||||||
|
|
||||||
ccl_device Spectrum bsdf_refraction_eval_reflect(ccl_private const ShaderClosure *sc,
|
ccl_device Spectrum bsdf_refraction_eval(ccl_private const ShaderClosure *sc,
|
||||||
const float3 I,
|
const float3 I,
|
||||||
const float3 omega_in,
|
const float3 omega_in,
|
||||||
ccl_private float *pdf)
|
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)
|
|
||||||
{
|
{
|
||||||
*pdf = 0.0f;
|
*pdf = 0.0f;
|
||||||
return zero_spectrum();
|
return zero_spectrum();
|
||||||
|
@ -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);
|
return fminf(max_angle + smooth, M_PI_2_F);
|
||||||
}
|
}
|
||||||
|
|
||||||
ccl_device Spectrum bsdf_diffuse_toon_eval_reflect(ccl_private const ShaderClosure *sc,
|
ccl_device Spectrum bsdf_diffuse_toon_eval(ccl_private const ShaderClosure *sc,
|
||||||
const float3 I,
|
const float3 I,
|
||||||
const float3 omega_in,
|
const float3 omega_in,
|
||||||
ccl_private float *pdf)
|
ccl_private float *pdf)
|
||||||
{
|
{
|
||||||
ccl_private const ToonBsdf *bsdf = (ccl_private const ToonBsdf *)sc;
|
ccl_private const ToonBsdf *bsdf = (ccl_private const ToonBsdf *)sc;
|
||||||
float max_angle = bsdf->size * M_PI_2_F;
|
float cosNI = dot(bsdf->N, omega_in);
|
||||||
float smooth = bsdf->smooth * M_PI_2_F;
|
|
||||||
float angle = safe_acosf(fmaxf(dot(bsdf->N, omega_in), 0.0f));
|
|
||||||
|
|
||||||
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 eval = bsdf_toon_get_intensity(max_angle, smooth, angle);
|
||||||
float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
|
|
||||||
|
|
||||||
*pdf = 0.5f * M_1_PI_F / (1.0f - cosf(sample_angle));
|
if (eval > 0.0f) {
|
||||||
return make_spectrum(*pdf * eval);
|
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;
|
*pdf = 0.0f;
|
||||||
return zero_spectrum();
|
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;
|
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ccl_device Spectrum bsdf_glossy_toon_eval_reflect(ccl_private const ShaderClosure *sc,
|
ccl_device Spectrum bsdf_glossy_toon_eval(ccl_private const ShaderClosure *sc,
|
||||||
const float3 I,
|
const float3 I,
|
||||||
const float3 omega_in,
|
const float3 omega_in,
|
||||||
ccl_private float *pdf)
|
ccl_private float *pdf)
|
||||||
{
|
{
|
||||||
ccl_private const ToonBsdf *bsdf = (ccl_private const ToonBsdf *)sc;
|
ccl_private const ToonBsdf *bsdf = (ccl_private const ToonBsdf *)sc;
|
||||||
float max_angle = bsdf->size * M_PI_2_F;
|
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();
|
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,
|
ccl_device int bsdf_glossy_toon_sample(ccl_private const ShaderClosure *sc,
|
||||||
float3 Ng,
|
float3 Ng,
|
||||||
float3 I,
|
float3 I,
|
||||||
|
@ -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,
|
ccl_device Spectrum bsdf_transparent_eval(ccl_private const ShaderClosure *sc,
|
||||||
const float3 I,
|
const float3 I,
|
||||||
const float3 omega_in,
|
const float3 omega_in,
|
||||||
ccl_private float *pdf)
|
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)
|
|
||||||
{
|
{
|
||||||
*pdf = 0.0f;
|
*pdf = 0.0f;
|
||||||
return zero_spectrum();
|
return zero_spectrum();
|
||||||
|
@ -807,7 +807,7 @@ ccl_device_forceinline bool mnee_path_contribution(KernelGlobals kg,
|
|||||||
float3 wo = normalize_len(vertices[0].p - sd->P, &wo_len);
|
float3 wo = normalize_len(vertices[0].p - sd->P, &wo_len);
|
||||||
|
|
||||||
/* Initialize throughput and evaluate receiver bsdf * |n.wo|. */
|
/* 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
|
/* Update light sample with new position / direct.ion
|
||||||
* and keep pdf in vertex area measure */
|
* and keep pdf in vertex area measure */
|
||||||
|
@ -171,7 +171,8 @@ ccl_device_forceinline void integrate_surface_direct_light(KernelGlobals kg,
|
|||||||
|
|
||||||
Ray ray ccl_optional_struct_init;
|
Ray ray ccl_optional_struct_init;
|
||||||
BsdfEval bsdf_eval 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__
|
#ifdef __MNEE__
|
||||||
int mnee_vertex_count = 0;
|
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;
|
const bool use_caustics = kernel_data_fetch(lights, ls.lamp).use_caustics;
|
||||||
if (use_caustics) {
|
if (use_caustics) {
|
||||||
/* Are we on a caustic caster? */
|
/* 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;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Are we on a caustic receiver? */
|
/* 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(
|
mnee_vertex_count = kernel_path_mnee_sample(
|
||||||
kg, state, sd, emission_sd, rng_state, &ls, &bsdf_eval);
|
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. */
|
/* Evaluate BSDF. */
|
||||||
const float bsdf_pdf = surface_shader_bsdf_eval(
|
const float bsdf_pdf = surface_shader_bsdf_eval(kg, sd, ls.D, &bsdf_eval, ls.shader);
|
||||||
kg, sd, ls.D, is_transmission, &bsdf_eval, ls.shader);
|
|
||||||
bsdf_eval_mul(&bsdf_eval, light_eval / ls.pdf);
|
bsdf_eval_mul(&bsdf_eval, light_eval / ls.pdf);
|
||||||
|
|
||||||
if (ls.shader & SHADER_USE_MIS) {
|
if (ls.shader & SHADER_USE_MIS) {
|
||||||
|
@ -108,13 +108,6 @@ ccl_device_inline void surface_shader_prepare_closures(KernelGlobals kg,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* BSDF */
|
/* 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)
|
ccl_device_forceinline bool _surface_shader_exclude(ClosureType type, uint light_shader_flags)
|
||||||
{
|
{
|
||||||
if (!(light_shader_flags & SHADER_EXCLUDE_ANY)) {
|
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_device_inline float _surface_shader_bsdf_eval_mis(KernelGlobals kg,
|
||||||
ccl_private ShaderData *sd,
|
ccl_private ShaderData *sd,
|
||||||
const float3 omega_in,
|
const float3 omega_in,
|
||||||
const bool is_transmission,
|
|
||||||
ccl_private const ShaderClosure *skip_sc,
|
ccl_private const ShaderClosure *skip_sc,
|
||||||
ccl_private BsdfEval *result_eval,
|
ccl_private BsdfEval *result_eval,
|
||||||
float sum_pdf,
|
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_OR_BSSRDF(sc->type)) {
|
||||||
if (CLOSURE_IS_BSDF(sc->type) && !_surface_shader_exclude(sc->type, light_shader_flags)) {
|
if (CLOSURE_IS_BSDF(sc->type) && !_surface_shader_exclude(sc->type, light_shader_flags)) {
|
||||||
float bsdf_pdf = 0.0f;
|
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) {
|
if (bsdf_pdf != 0.0f) {
|
||||||
bsdf_eval_accum(result_eval, sc->type, eval * sc->weight);
|
bsdf_eval_accum(result_eval, sc->type, eval * sc->weight);
|
||||||
@ -184,14 +176,13 @@ ccl_device_inline
|
|||||||
surface_shader_bsdf_eval(KernelGlobals kg,
|
surface_shader_bsdf_eval(KernelGlobals kg,
|
||||||
ccl_private ShaderData *sd,
|
ccl_private ShaderData *sd,
|
||||||
const float3 omega_in,
|
const float3 omega_in,
|
||||||
const bool is_transmission,
|
|
||||||
ccl_private BsdfEval *bsdf_eval,
|
ccl_private BsdfEval *bsdf_eval,
|
||||||
const uint light_shader_flags)
|
const uint light_shader_flags)
|
||||||
{
|
{
|
||||||
bsdf_eval_init(bsdf_eval, CLOSURE_NONE_ID, zero_spectrum());
|
bsdf_eval_init(bsdf_eval, CLOSURE_NONE_ID, zero_spectrum());
|
||||||
|
|
||||||
return _surface_shader_bsdf_eval_mis(
|
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. */
|
/* 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);
|
bsdf_eval_init(bsdf_eval, sc->type, eval * sc->weight);
|
||||||
|
|
||||||
if (sd->num_closure > 1) {
|
if (sd->num_closure > 1) {
|
||||||
const bool is_transmission = surface_shader_is_transmission(sd, *omega_in);
|
|
||||||
float sweight = sc->sample_weight;
|
float sweight = sc->sample_weight;
|
||||||
*pdf = _surface_shader_bsdf_eval_mis(
|
*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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user