diff options
22 files changed, 436 insertions, 93 deletions
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index cb50b741567..6f6a4d0b434 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -528,6 +528,14 @@ static ShaderNode *add_node(Scene *scene, disney->distribution = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID; break; } + switch (b_disney_node.surface_type()) { + case BL::ShaderNodeBsdfDisney::surface_type_THIN_SURFACE: + disney->surface_type = THIN_SURFACE; + break; + case BL::ShaderNodeBsdfDisney::surface_type_SOLID_SURFACE: + disney->surface_type = SOLID_SURFACE; + break; + } node = disney; } else if(b_node.is_a(&RNA_ShaderNodeBsdfTranslucent)) { diff --git a/intern/cycles/kernel/closure/bsdf.h b/intern/cycles/kernel/closure/bsdf.h index b46f6a7f1c5..41ea7864d1c 100644 --- a/intern/cycles/kernel/closure/bsdf.h +++ b/intern/cycles/kernel/closure/bsdf.h @@ -93,6 +93,7 @@ ccl_device_forceinline int bsdf_sample(KernelGlobals *kg, case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID: case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID: case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID: + case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_THIN_ID: label = bsdf_microfacet_ggx_sample(kg, sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; @@ -138,10 +139,15 @@ ccl_device_forceinline int bsdf_sample(KernelGlobals *kg, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; case CLOSURE_BSDF_DISNEY_DIFFUSE_ID: + case CLOSURE_BSDF_DISNEY_DIFFUSE_TRANSMIT_ID: case CLOSURE_BSDF_BSSRDF_DISNEY_ID: label = bsdf_disney_diffuse_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; + case CLOSURE_BSDF_DISNEY_RETRO_REFLECTION_ID: + label = bsdf_disney_retro_reflection_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv, + eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + break; case CLOSURE_BSDF_DISNEY_SHEEN_ID: label = bsdf_disney_sheen_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); @@ -209,6 +215,7 @@ float3 bsdf_eval(KernelGlobals *kg, case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID: case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID: case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID: + case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_THIN_ID: eval = bsdf_microfacet_ggx_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf); break; case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID: @@ -244,9 +251,13 @@ float3 bsdf_eval(KernelGlobals *kg, eval = bsdf_hair_transmission_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf); break; case CLOSURE_BSDF_DISNEY_DIFFUSE_ID: + case CLOSURE_BSDF_DISNEY_DIFFUSE_TRANSMIT_ID: case CLOSURE_BSDF_BSSRDF_DISNEY_ID: eval = bsdf_disney_diffuse_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf); break; + case CLOSURE_BSDF_DISNEY_RETRO_REFLECTION_ID: + eval = bsdf_disney_retro_reflection_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf); + break; case CLOSURE_BSDF_DISNEY_SHEEN_ID: eval = bsdf_disney_sheen_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf); break; @@ -289,6 +300,7 @@ float3 bsdf_eval(KernelGlobals *kg, case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID: case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID: case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID: + case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_THIN_ID: eval = bsdf_microfacet_ggx_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf); break; case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID: @@ -324,9 +336,13 @@ float3 bsdf_eval(KernelGlobals *kg, eval = bsdf_hair_transmission_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf); break; case CLOSURE_BSDF_DISNEY_DIFFUSE_ID: + case CLOSURE_BSDF_DISNEY_DIFFUSE_TRANSMIT_ID: case CLOSURE_BSDF_BSSRDF_DISNEY_ID: eval = bsdf_disney_diffuse_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf); break; + case CLOSURE_BSDF_DISNEY_RETRO_REFLECTION_ID: + eval = bsdf_disney_retro_reflection_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf); + break; case CLOSURE_BSDF_DISNEY_SHEEN_ID: eval = bsdf_disney_sheen_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf); break; @@ -362,6 +378,7 @@ ccl_device void bsdf_blur(KernelGlobals *kg, ShaderClosure *sc, float roughness) case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID: case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID: case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID: + case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_THIN_ID: bsdf_microfacet_ggx_blur(sc, roughness); break; case CLOSURE_BSDF_MICROFACET_BECKMANN_ID: @@ -399,6 +416,7 @@ ccl_device bool bsdf_merge(ShaderClosure *a, ShaderClosure *b) case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID: case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID: case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID: + case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_THIN_ID: case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID: case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID: case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID: diff --git a/intern/cycles/kernel/closure/bsdf_disney_diffuse.h b/intern/cycles/kernel/closure/bsdf_disney_diffuse.h index ccb5966db1a..a76be38758a 100644 --- a/intern/cycles/kernel/closure/bsdf_disney_diffuse.h +++ b/intern/cycles/kernel/closure/bsdf_disney_diffuse.h @@ -27,51 +27,174 @@ CCL_NAMESPACE_BEGIN typedef ccl_addr_space struct DisneyDiffuseBsdf { SHADER_CLOSURE_BASE; - float roughness; + float roughness, flatness; float3 N; } DisneyDiffuseBsdf; + +/* DIFFUSE */ + ccl_device float3 calculate_disney_diffuse_brdf(const DisneyDiffuseBsdf *bsdf, - float3 N, float3 V, float3 L, float3 H, float *pdf) + float NdotL, float NdotV, float LdotH) +{ + float FL = schlick_fresnel(NdotL), FV = schlick_fresnel(NdotV); + float Fd = (1.0f - 0.5f * FL) * (1.0f - 0.5f * FV); + + float ss = 0.0f; + if(bsdf->flatness > 0.0f) { + // Based on Hanrahan-Krueger BRDF approximation of isotropic BSSRDF + // 1.25 scale is used to (roughly) preserve albedo + // Fss90 used to "flatten" retro-reflection based on roughness + float Fss90 = LdotH*LdotH * bsdf->roughness; + float Fss = (1.0f + (Fss90 - 1.0f) * FL) * (1.0f + (Fss90 - 1.0f) * FV); + ss = 1.25f * (Fss * (1.0f / (NdotL + NdotV) - 0.5f) + 0.5f); + } + + float value = Fd + (ss - Fd) * bsdf->flatness; + value *= M_1_PI_F * NdotL; + + return make_float3(value, value, value); +} + +ccl_device int bsdf_disney_diffuse_setup(DisneyDiffuseBsdf *bsdf) +{ + bsdf->type = CLOSURE_BSDF_DISNEY_DIFFUSE_ID; + return SD_BSDF|SD_BSDF_HAS_EVAL; +} + +ccl_device int bsdf_disney_diffuse_transmit_setup(DisneyDiffuseBsdf *bsdf) +{ + bsdf->type = CLOSURE_BSDF_DISNEY_DIFFUSE_TRANSMIT_ID; + return SD_BSDF|SD_BSDF_HAS_EVAL; +} + +ccl_device float3 bsdf_disney_diffuse_eval_reflect(const ShaderClosure *sc, const float3 I, + const float3 omega_in, float *pdf) +{ + const DisneyDiffuseBsdf *bsdf = (const DisneyDiffuseBsdf *)sc; + bool m_transmittance = bsdf->type == CLOSURE_BSDF_DISNEY_DIFFUSE_TRANSMIT_ID; + + if(m_transmittance) + return make_float3(0.0f, 0.0f, 0.0f); + + float3 N = bsdf->N; + + if(dot(N, omega_in) > 0.0f) { + float3 H = normalize(I + omega_in); + + *pdf = fmaxf(dot(N, omega_in), 0.0f) * M_1_PI_F; + return calculate_disney_diffuse_brdf(bsdf, fmaxf(dot(N, omega_in), 0.0f), fmaxf(dot(N, I), 0.0f), dot(omega_in, H)); + } + else { + *pdf = 0.0f; + return make_float3(0.0f, 0.0f, 0.0f); + } +} + +ccl_device float3 bsdf_disney_diffuse_eval_transmit(const ShaderClosure *sc, const float3 I, + const float3 omega_in, float *pdf) { - float NdotL = max(dot(N, L), 0.0f); - float NdotV = max(dot(N, V), 0.0f); + const DisneyDiffuseBsdf *bsdf = (const DisneyDiffuseBsdf *)sc; + bool m_transmittance = bsdf->type == CLOSURE_BSDF_DISNEY_DIFFUSE_TRANSMIT_ID; - if(NdotL < 0 || NdotV < 0) { + if(!m_transmittance) + return make_float3(0.0f, 0.0f, 0.0f); + + float3 N = bsdf->N; + + if(dot(-N, omega_in) > 0.0f) { + float3 H = normalize(I + omega_in); + + *pdf = fmaxf(dot(-N, omega_in), 0.0f) * M_1_PI_F; + return calculate_disney_diffuse_brdf(bsdf, fmaxf(dot(-N, omega_in), 0.0f), fmaxf(dot(N, I), 0.0f), dot(omega_in, H)); + } + else { *pdf = 0.0f; return make_float3(0.0f, 0.0f, 0.0f); } +} + +ccl_device int bsdf_disney_diffuse_sample(const ShaderClosure *sc, + float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, + float3 *eval, float3 *omega_in, float3 *domega_in_dx, + float3 *domega_in_dy, float *pdf) +{ + const DisneyDiffuseBsdf *bsdf = (const DisneyDiffuseBsdf *)sc; + bool m_transmittance = bsdf->type == CLOSURE_BSDF_DISNEY_DIFFUSE_TRANSMIT_ID; + + float3 N = bsdf->N; + + if(m_transmittance) { + sample_uniform_hemisphere(-N, randu, randv, omega_in, pdf); + } + else { + sample_cos_hemisphere(N, randu, randv, omega_in, pdf); + } + + if(m_transmittance && dot(-Ng, *omega_in) > 0) { + float3 I_t = -((2 * dot(N, I)) * N - I); + float3 H = normalize(I_t + *omega_in); + + *eval = calculate_disney_diffuse_brdf(bsdf, fmaxf(dot(-N, *omega_in), 0.0f), fmaxf(dot(N, I), 0.0f), dot(*omega_in, H)); + +#ifdef __RAY_DIFFERENTIALS__ + // TODO: find a better approximation for the diffuse bounce + *domega_in_dx = -((2 * dot(N, dIdx)) * N - dIdx); + *domega_in_dy = -((2 * dot(N, dIdy)) * N - dIdy); +#endif + } + else if(!m_transmittance && dot(Ng, *omega_in) > 0) { + float3 H = normalize(I + *omega_in); + + *eval = calculate_disney_diffuse_brdf(bsdf, fmaxf(dot(N, *omega_in), 0.0f), fmaxf(dot(N, I), 0.0f), dot(*omega_in, H)); + +#ifdef __RAY_DIFFERENTIALS__ + // TODO: find a better approximation for the diffuse bounce + *domega_in_dx = -((2 * dot(N, dIdx)) * N - dIdx); + *domega_in_dy = -((2 * dot(N, dIdy)) * N - dIdy); +#endif + } + else { + *pdf = 0.0f; + } - float LdotH = dot(L, H); + return (m_transmittance) ? LABEL_TRANSMIT|LABEL_DIFFUSE : LABEL_REFLECT|LABEL_DIFFUSE; +} + + +/* RETRO-REFLECTION */ +ccl_device float3 calculate_retro_reflection(const DisneyDiffuseBsdf *bsdf, + float NdotL, float NdotV, float LdotH) +{ float FL = schlick_fresnel(NdotL), FV = schlick_fresnel(NdotV); - const float Fd90 = 0.5f + 2.0f * LdotH*LdotH * bsdf->roughness; - float Fd = (1.0f * (1.0f - FL) + Fd90 * FL) * (1.0f * (1.0f - FV) + Fd90 * FV); + float RR = 2.0f * bsdf->roughness * LdotH*LdotH; + + float FRR = RR * (FL + FV + FL * FV * (RR - 1.0f)); - float value = M_1_PI_F * NdotL * Fd; + float value = M_1_PI_F * FRR * NdotL; return make_float3(value, value, value); } -ccl_device int bsdf_disney_diffuse_setup(DisneyDiffuseBsdf *bsdf) +ccl_device int bsdf_disney_retro_reflection_setup(DisneyDiffuseBsdf *bsdf) { - bsdf->type = CLOSURE_BSDF_DISNEY_DIFFUSE_ID; + bsdf->type = CLOSURE_BSDF_DISNEY_RETRO_REFLECTION_ID; return SD_BSDF|SD_BSDF_HAS_EVAL; } -ccl_device float3 bsdf_disney_diffuse_eval_reflect(const ShaderClosure *sc, const float3 I, +ccl_device float3 bsdf_disney_retro_reflection_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { const DisneyDiffuseBsdf *bsdf = (const DisneyDiffuseBsdf *)sc; 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) { + float3 H = normalize(I + omega_in); + *pdf = fmaxf(dot(N, omega_in), 0.0f) * M_1_PI_F; - return calculate_disney_diffuse_brdf(bsdf, N, V, L, H, pdf); + return calculate_retro_reflection(bsdf, fmaxf(dot(N, omega_in), 0.0f), fmaxf(dot(N, I), 0.0f), dot(omega_in, H)); } else { *pdf = 0.0f; @@ -79,13 +202,13 @@ ccl_device float3 bsdf_disney_diffuse_eval_reflect(const ShaderClosure *sc, cons } } -ccl_device float3 bsdf_disney_diffuse_eval_transmit(const ShaderClosure *sc, const float3 I, +ccl_device float3 bsdf_disney_retro_reflection_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { return make_float3(0.0f, 0.0f, 0.0f); } -ccl_device int bsdf_disney_diffuse_sample(const ShaderClosure *sc, +ccl_device int bsdf_disney_retro_reflection_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) @@ -94,12 +217,12 @@ ccl_device int bsdf_disney_diffuse_sample(const ShaderClosure *sc, float3 N = bsdf->N; - sample_cos_hemisphere(N, randu, randv, omega_in, pdf); + sample_uniform_hemisphere(N, randu, randv, omega_in, pdf); if(dot(Ng, *omega_in) > 0) { float3 H = normalize(I + *omega_in); - *eval = calculate_disney_diffuse_brdf(bsdf, N, I, *omega_in, H, pdf); + *eval = calculate_retro_reflection(bsdf, fmaxf(dot(N, *omega_in), 0.0f), fmaxf(dot(N, I), 0.0f), dot(*omega_in, H)); #ifdef __RAY_DIFFERENTIALS__ // TODO: find a better approximation for the diffuse bounce @@ -110,6 +233,7 @@ ccl_device int bsdf_disney_diffuse_sample(const ShaderClosure *sc, else { *pdf = 0.0f; } + return LABEL_REFLECT|LABEL_DIFFUSE; } diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h index 38364bb1026..81ecfd0ebd3 100644 --- a/intern/cycles/kernel/closure/bsdf_microfacet.h +++ b/intern/cycles/kernel/closure/bsdf_microfacet.h @@ -370,6 +370,18 @@ ccl_device int bsdf_microfacet_ggx_refraction_setup(MicrofacetBsdf *bsdf) return SD_BSDF|SD_BSDF_HAS_EVAL; } +ccl_device int bsdf_microfacet_ggx_refraction_thin_setup(MicrofacetBsdf *bsdf) +{ + bsdf->extra = NULL; + + bsdf->alpha_x = saturate(bsdf->alpha_x); + bsdf->alpha_y = bsdf->alpha_x; + + bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_THIN_ID; + + return SD_BSDF|SD_BSDF_HAS_EVAL; +} + ccl_device void bsdf_microfacet_ggx_blur(ShaderClosure *sc, float roughness) { MicrofacetBsdf *bsdf = (MicrofacetBsdf*)sc; @@ -383,7 +395,7 @@ ccl_device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderClosure *sc, cons const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc; float alpha_x = bsdf->alpha_x; float alpha_y = bsdf->alpha_y; - bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID; + bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID || bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_THIN_ID; float3 N = bsdf->N; if(m_refractive || alpha_x*alpha_y <= 1e-7f) @@ -494,7 +506,7 @@ ccl_device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderClosure *sc, con 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; + bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID || bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_THIN_ID; float3 N = bsdf->N; if(!m_refractive || alpha_x*alpha_y <= 1e-7f) @@ -507,7 +519,15 @@ ccl_device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderClosure *sc, con return make_float3(0.0f, 0.0f, 0.0f); /* vectors on same side -- not possible */ /* compute half-vector of the refraction (eq. 16) */ - float3 ht = -(m_eta * omega_in + I); + float3 ht; + if(bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_THIN_ID) { + /* for thin surfaces refraction approximately cancels and thus specular transmission is modelled + * using a microfacet distribution which is simply reflected to the other side */ + ht = -(omega_in + I); + } + else { + ht = -(m_eta * omega_in + I); + } float3 Ht = normalize(ht); float cosHO = dot(Ht, I); float cosHI = dot(Ht, omega_in); @@ -536,7 +556,13 @@ ccl_device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderClosure *sc, con /* out = fabsf(cosHI * cosHO) * (m_eta * m_eta) * G * D / (cosNO * Ht2) * pdf = pm * (m_eta * m_eta) * fabsf(cosHI) / Ht2 */ - float common = D * (m_eta * m_eta) / (cosNO * Ht2); + float common; + if(bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_THIN_ID) { + common = D * 0.25f / cosNO; + } + else { + common = D * (m_eta * m_eta) / (cosNO * Ht2); + } float out = G * fabsf(cosHI * cosHO) * common; *pdf = G1o * fabsf(cosHO * cosHI) * common; @@ -548,7 +574,7 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg, const ShaderClosure const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc; float alpha_x = bsdf->alpha_x; float alpha_y = bsdf->alpha_y; - bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID; + bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID || bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_THIN_ID; float3 N = bsdf->N; float cosNO = dot(N, I); @@ -686,6 +712,10 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg, const ShaderClosure float m_eta = bsdf->ior, fresnel; bool inside; + if(bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_THIN_ID) { + m_eta = 1.0f; + } + fresnel = fresnel_dielectric(m_eta, m, I, &R, &T, #ifdef __RAY_DIFFERENTIALS__ dIdx, dIdy, &dRdx, &dRdy, &dTdx, &dTdy, @@ -1055,7 +1085,7 @@ ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals *kg, const ShaderCl *domega_in_dy = dTdy; #endif - if(alpha_x*alpha_y <= 1e-7f || fabsf(m_eta - 1.0f) < 1e-4f) { + if(alpha_x*alpha_y <= 1e-7f || (fabsf(m_eta - 1.0f) < 1e-4f && bsdf->type != CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_THIN_ID)) { /* some high number for MIS */ *pdf = 1e6f; *eval = make_float3(1e6f, 1e6f, 1e6f); @@ -1082,7 +1112,13 @@ ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals *kg, const ShaderCl Ht2 *= Ht2; /* see eval function for derivation */ - float common = D * (m_eta * m_eta) / (cosNO * Ht2); + float common; + if(bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_THIN_ID) { + common = D * 0.25f / cosNO; + } + else { + common = D * (m_eta * m_eta) / (cosNO * Ht2); + } float out = G * fabsf(cosHI * cosHO) * common; *pdf = G1o * cosHO * fabsf(cosHI) * common; diff --git a/intern/cycles/kernel/closure/bssrdf.h b/intern/cycles/kernel/closure/bssrdf.h index a5a578375dc..3f8192f588e 100644 --- a/intern/cycles/kernel/closure/bssrdf.h +++ b/intern/cycles/kernel/closure/bssrdf.h @@ -27,7 +27,6 @@ typedef ccl_addr_space struct Bssrdf { float d; float texture_blur; float albedo; - float roughness; float3 N; float3 base_color; } Bssrdf; @@ -364,7 +363,6 @@ ccl_device int bssrdf_setup(Bssrdf *bssrdf, ClosureType type) /* revert to diffuse BSDF if radius too small */ int flag; if(type == CLOSURE_BSSRDF_DISNEY_ID) { - float roughness = bssrdf->roughness; float3 N = bssrdf->N; float3 weight = bssrdf->weight * bssrdf->base_color; float sample_weight = bssrdf->sample_weight; @@ -372,7 +370,7 @@ ccl_device int bssrdf_setup(Bssrdf *bssrdf, ClosureType type) DisneyDiffuseBsdf *bsdf = (DisneyDiffuseBsdf*)bssrdf; bsdf->N = N; - bsdf->roughness = roughness; + bsdf->flatness = 0.0f; bsdf->weight = weight; bsdf->sample_weight = sample_weight; flag = bsdf_disney_diffuse_setup(bsdf); diff --git a/intern/cycles/kernel/kernel_subsurface.h b/intern/cycles/kernel/kernel_subsurface.h index 908c2d0b17d..1a831ad3b20 100644 --- a/intern/cycles/kernel/kernel_subsurface.h +++ b/intern/cycles/kernel/kernel_subsurface.h @@ -154,7 +154,7 @@ ccl_device void subsurface_scatter_setup_diffuse_bsdf(ShaderData *sd, ShaderClos if(bsdf) { bsdf->N = N; - bsdf->roughness = bssrdf->roughness; + bsdf->flatness = 0.0f; sd->flag |= bsdf_disney_diffuse_setup(bsdf); /* replace CLOSURE_BSDF_DISNEY_DIFFUSE_ID with this special ID so render passes diff --git a/intern/cycles/kernel/osl/osl_bssrdf.cpp b/intern/cycles/kernel/osl/osl_bssrdf.cpp index 790dd3a2d46..b552f3af131 100644 --- a/intern/cycles/kernel/osl/osl_bssrdf.cpp +++ b/intern/cycles/kernel/osl/osl_bssrdf.cpp @@ -81,7 +81,6 @@ public: bssrdf->sharpness = sharpness; bssrdf->N = params.N; bssrdf->base_color = params.base_color; - bssrdf->roughness = params.roughness; ccl_fetch(sd, flag) |= bssrdf_setup(bssrdf, (ClosureType)type); } @@ -94,7 +93,6 @@ public: bssrdf->sharpness = sharpness; bssrdf->N = params.N; bssrdf->base_color = params.base_color; - bssrdf->roughness = params.roughness; ccl_fetch(sd, flag) |= bssrdf_setup(bssrdf, (ClosureType)type); } @@ -107,7 +105,6 @@ public: bssrdf->sharpness = sharpness; bssrdf->N = params.N; bssrdf->base_color = params.base_color; - bssrdf->roughness = params.roughness; ccl_fetch(sd, flag) |= bssrdf_setup(bssrdf, (ClosureType)type); } } @@ -206,7 +203,6 @@ ClosureParam *closure_bssrdf_disney_params() CLOSURE_FLOAT_PARAM(DisneyBSSRDFClosure, params.texture_blur), CLOSURE_FLOAT3_PARAM(DisneyBSSRDFClosure, params.base_color), CLOSURE_FLOAT3_PARAM(DisneyBSSRDFClosure, albedo), - CLOSURE_FLOAT_PARAM(DisneyBSSRDFClosure, params.roughness), CLOSURE_STRING_KEYPARAM(DisneyBSSRDFClosure, label, "label"), CLOSURE_FINISH_PARAM(DisneyBSSRDFClosure) }; diff --git a/intern/cycles/kernel/osl/osl_closures.cpp b/intern/cycles/kernel/osl/osl_closures.cpp index 4d51dda7197..923ea908f1d 100644 --- a/intern/cycles/kernel/osl/osl_closures.cpp +++ b/intern/cycles/kernel/osl/osl_closures.cpp @@ -180,8 +180,20 @@ VOLUME_CLOSURE_CLASS_END(VolumeAbsorption, absorption) BSDF_CLOSURE_CLASS_BEGIN(DisneyDiffuse, disney_diffuse, DisneyDiffuseBsdf, LABEL_DIFFUSE) CLOSURE_FLOAT3_PARAM(DisneyDiffuseClosure, params.N), CLOSURE_FLOAT_PARAM(DisneyDiffuseClosure, params.roughness), + CLOSURE_FLOAT_PARAM(DisneyDiffuseClosure, params.flatness), BSDF_CLOSURE_CLASS_END(DisneyDiffuse, disney_diffuse) +BSDF_CLOSURE_CLASS_BEGIN(DisneyDiffuseTransmit, disney_diffuse_transmit, DisneyDiffuseBsdf, LABEL_DIFFUSE|LABEL_TRANSMIT) + CLOSURE_FLOAT3_PARAM(DisneyDiffuseTransmitClosure, params.N), + CLOSURE_FLOAT_PARAM(DisneyDiffuseTransmitClosure, params.roughness), + CLOSURE_FLOAT_PARAM(DisneyDiffuseTransmitClosure, params.flatness), +BSDF_CLOSURE_CLASS_END(DisneyDiffuseTransmit, disney_diffuse_transmit) + +BSDF_CLOSURE_CLASS_BEGIN(DisneyRetroReflection, disney_retro_reflection, DisneyDiffuseBsdf, LABEL_DIFFUSE) + CLOSURE_FLOAT3_PARAM(DisneyRetroReflectionClosure, params.N), + CLOSURE_FLOAT_PARAM(DisneyRetroReflectionClosure, params.roughness), +BSDF_CLOSURE_CLASS_END(DisneyRetroReflection, disney_retro_reflection) + BSDF_CLOSURE_CLASS_BEGIN(DisneySheen, disney_sheen, DisneySheenBsdf, LABEL_DIFFUSE) CLOSURE_FLOAT3_PARAM(DisneySheenClosure, params.N), BSDF_CLOSURE_CLASS_END(DisneySheen, disney_sheen) @@ -299,6 +311,10 @@ void OSLShader::register_closures(OSLShadingSystem *ss_) bsdf_glossy_toon_params(), bsdf_glossy_toon_prepare); register_closure(ss, "disney_diffuse", id++, bsdf_disney_diffuse_params(), bsdf_disney_diffuse_prepare); + register_closure(ss, "disney_diffuse_transmit", id++, + bsdf_disney_diffuse_transmit_params(), bsdf_disney_diffuse_transmit_prepare); + register_closure(ss, "disney_retro_reflection", id++, + bsdf_disney_retro_reflection_params(), bsdf_disney_retro_reflection_prepare); register_closure(ss, "disney_sheen", id++, bsdf_disney_sheen_params(), bsdf_disney_sheen_prepare); register_closure(ss, "disney_clearcoat", id++, diff --git a/intern/cycles/kernel/shaders/node_disney_bsdf.osl b/intern/cycles/kernel/shaders/node_disney_bsdf.osl index 313f4bdb8e4..8b5bacb64f4 100644 --- a/intern/cycles/kernel/shaders/node_disney_bsdf.osl +++ b/intern/cycles/kernel/shaders/node_disney_bsdf.osl @@ -19,6 +19,7 @@ shader node_disney_bsdf( string distribution = "Multiscatter GGX", + string surface_type = "Solid Surface", color BaseColor = color(0.8, 0.8, 0.8), float Subsurface = 0.0, vector SubsurfaceRadius = vector(1.0, 1.0, 1.0), @@ -33,8 +34,10 @@ shader node_disney_bsdf( float SheenTint = 0.5, float Clearcoat = 0.0, float ClearcoatGloss = 1.0, + float SpecularTransmission = 0.0, float IOR = 1.45, - float Transparency = 0.0, + float Flatness = 0.0, + float DiffuseTransmission = 0.0, float RefractionRoughness = 0.0, normal Normal = N, normal ClearcoatNormal = N, @@ -42,8 +45,8 @@ shader node_disney_bsdf( output closure color BSDF = 0) { float f = max(IOR, 1e-5); - float diffuse_weight = (1.0 - clamp(Metallic, 0.0, 1.0)) * (1.0 - clamp(Transparency, 0.0, 1.0)); - float transp = clamp(Transparency, 0.0, 1.0) * (1.0 - clamp(Metallic, 0.0, 1.0)); + float diffuse_weight = (1.0 - clamp(Metallic, 0.0, 1.0)) * (1.0 - clamp(SpecularTransmission, 0.0, 1.0)); + float transp = clamp(SpecularTransmission, 0.0, 1.0) * (1.0 - clamp(Metallic, 0.0, 1.0)); float specular_weight = (1.0 - transp); vector T = Tangent; @@ -56,10 +59,24 @@ shader node_disney_bsdf( T = rotate(T, AnisotropicRotation * M_2PI, point(0.0, 0.0, 0.0), Normal); if (diffuse_weight > 1e-5) { - if (Subsurface > 1e-5) { - BSDF = bssrdf_disney(Normal, Subsurface * SubsurfaceRadius, 0.0, BaseColor, SubsurfaceColor, Roughness); + float flat = Flatness; + float diff_trans = clamp(DiffuseTransmission, 0.0, 2.0); + if (surface_type == "Solid Surface") { + flat = 0.0; + diff_trans = 0.0; + } + + if (Subsurface > 1e-5 && surface_type == "Solid Surface") { + BSDF = bssrdf_disney(Normal, Subsurface * SubsurfaceRadius, 0.0, BaseColor, SubsurfaceColor); } else { - BSDF = BaseColor * disney_diffuse(Normal, Roughness); + BSDF = BaseColor * disney_diffuse(Normal, Roughness, flat) * ((2.0 - diff_trans) / 2.0); + } + + /* diffuse retro-reflection */ + BSDF = BSDF + BaseColor * disney_retro_reflection(Normal, Roughness); + + if (diff_trans > 1e-5) { + BSDF = BSDF + BaseColor * disney_diffuse_transmit(Normal, Roughness, flat) * (diff_trans / 2.0); } if (Sheen > 1e-5) { @@ -91,20 +108,23 @@ shader node_disney_bsdf( if (transp > 1e-5) { color Cspec0 = BaseColor * SpecularTint + color(1.0, 1.0, 1.0) * (1.0 - SpecularTint); - float eta = backfacing() ? 1.0 / f : f; + float eta = (backfacing() && (surface_type == "Solid Surface")) ? 1.0 / f : f; - if (distribution == "GGX" || Roughness <= 5e-2) { + if (distribution == "GGX" || Roughness <= 5e-2 || surface_type == "Thin Surface") { float cosNO = dot(Normal, I); float Fr = fresnel_dielectric_cos(cosNO, eta); - float refl_roughness = Roughness; - if (Roughness <= 1e-2) - refl_roughness = 0.0; + float refl_roughness = Roughness; + if (Roughness <= 1e-2) + refl_roughness = 0.0; float refraction_roughness = refl_roughness; if (distribution == "GGX") refraction_roughness = 1.0 - (1.0 - refl_roughness) * (1.0 - RefractionRoughness); + if (surface_type == "Thin Surface") + refraction_roughness = refraction_roughness * (0.65 * eta - 0.35); + BSDF = BSDF + transp * (Fr * microfacet_ggx_fresnel(Normal, refl_roughness * refl_roughness, eta, BaseColor, Cspec0) + (1.0 - Fr) * BaseColor * microfacet_ggx_refraction(Normal, refraction_roughness * refraction_roughness, eta)); } else { diff --git a/intern/cycles/kernel/shaders/stdosl.h b/intern/cycles/kernel/shaders/stdosl.h index 7991b19d8b5..7a98722e82c 100644 --- a/intern/cycles/kernel/shaders/stdosl.h +++ b/intern/cycles/kernel/shaders/stdosl.h @@ -544,7 +544,9 @@ closure color emission() BUILTIN; closure color background() BUILTIN; closure color holdout() BUILTIN; closure color ambient_occlusion() BUILTIN; -closure color disney_diffuse(normal N, float roughness) BUILTIN; +closure color disney_diffuse(normal N, float roughness, float flatness) BUILTIN; +closure color disney_diffuse_transmit(normal N, float roughness, float flatness) BUILTIN; +closure color disney_retro_reflection(normal N, float roughness) BUILTIN; closure color disney_sheen(normal N) BUILTIN; closure color disney_clearcoat(normal N, float clearcoat, float clearcoat_gloss) BUILTIN; @@ -552,7 +554,7 @@ closure color disney_clearcoat(normal N, float clearcoat, float clearcoat_gloss) closure color bssrdf_cubic(normal N, vector radius, float texture_blur, float sharpness) BUILTIN; closure color bssrdf_gaussian(normal N, vector radius, float texture_blur) BUILTIN; closure color bssrdf_burley(normal N, vector radius, float texture_blur, color albedo) BUILTIN; -closure color bssrdf_disney(normal N, vector radius, float texture_blur, color base_color, color subsurface_color, float roughness) BUILTIN; +closure color bssrdf_disney(normal N, vector radius, float texture_blur, color base_color, color subsurface_color) BUILTIN; // Hair closure color hair_reflection(normal N, float roughnessu, float roughnessv, vector T, float offset) BUILTIN; diff --git a/intern/cycles/kernel/svm/svm_closure.h b/intern/cycles/kernel/svm/svm_closure.h index bfcd2a290a8..7e6471458ef 100644 --- a/intern/cycles/kernel/svm/svm_closure.h +++ b/intern/cycles/kernel/svm/svm_closure.h @@ -78,14 +78,16 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * switch(type) { case CLOSURE_BSDF_DISNEY_ID: { uint specular_offset, roughness_offset, specular_tint_offset, anisotropic_offset, sheen_offset, - sheen_tint_offset, clearcoat_offset, clearcoat_gloss_offset, eta_offset, transparency_offset, - anisotropic_rotation_offset, refraction_roughness_offset; + sheen_tint_offset, clearcoat_offset, clearcoat_gloss_offset, eta_offset, spec_trans_offset, + anisotropic_rotation_offset, refraction_roughness_offset, flatness_offset, diff_trans_offset, invalid0, invalid1; + uint4 data_node2 = read_node(kg, offset); float3 T = stack_load_float3(stack, data_node.y); decode_node_uchar4(data_node.z, &specular_offset, &roughness_offset, &specular_tint_offset, &anisotropic_offset); decode_node_uchar4(data_node.w, &sheen_offset, &sheen_tint_offset, &clearcoat_offset, &clearcoat_gloss_offset); - decode_node_uchar4(data_node2.x, &eta_offset, &transparency_offset, &anisotropic_rotation_offset, &refraction_roughness_offset); + decode_node_uchar4(data_node2.x, &eta_offset, &spec_trans_offset, &anisotropic_rotation_offset, &refraction_roughness_offset); + decode_node_uchar4(data_node2.y, &flatness_offset, &diff_trans_offset, &invalid0, &invalid1); // get disney parameters float metallic = param1; @@ -98,29 +100,32 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * float sheen_tint = stack_load_float(stack, sheen_tint_offset); float clearcoat = stack_load_float(stack, clearcoat_offset); float clearcoat_gloss = stack_load_float(stack, clearcoat_gloss_offset); - float transparency = stack_load_float(stack, transparency_offset); + float spec_trans = stack_load_float(stack, spec_trans_offset); float anisotropic_rotation = stack_load_float(stack, anisotropic_rotation_offset); float refraction_roughness = stack_load_float(stack, refraction_roughness_offset); float eta = fmaxf(stack_load_float(stack, eta_offset), 1e-5f); + float flatness = stack_load_float(stack, flatness_offset); + float diff_trans = clamp(stack_load_float(stack, diff_trans_offset), 0.0f, 2.0f); - ClosureType distribution = stack_valid(data_node2.y) ? (ClosureType) data_node2.y : CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID; + ClosureType distribution = stack_valid(data_node2.z) ? (ClosureType) data_node2.z : CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID; + SurfaceType surface_type = stack_valid(data_node2.w) ? (SurfaceType) data_node2.w : SOLID_SURFACE; /* rotate tangent */ if(anisotropic_rotation != 0.0f) T = rotate_around_axis(T, N, anisotropic_rotation * M_2PI_F); /* calculate ior */ - float ior = (ccl_fetch(sd, flag) & SD_BACKFACING) ? 1.0f / eta : eta; + float ior = ((ccl_fetch(sd, flag) & SD_BACKFACING) && (surface_type == SOLID_SURFACE)) ? 1.0f / eta : eta; // calculate fresnel for refraction float cosNO = dot(N, ccl_fetch(sd, I)); float fresnel = fresnel_dielectric_cos(cosNO, ior); // calculate weights of the diffuse and specular part - float diffuse_weight = (1.0f - saturate(metallic)) * (1.0f - saturate(transparency)); // lerp(1.0f - clamp(metallic, 0.0f, 1.0f), 0.0f, lerp(clamp(transparency, 0.0f, 1.0f), 0.0f, clamp(metallic, 0.0f, 1.0f))); - - float transp = saturate(transparency) * (1.0f - saturate(metallic)); // lerp(clamp(transparency, 0.0f, 1.0f), 0.0f, clamp(metallic, 0.0f, 1.0f)); - float specular_weight = (1.0f - transp); // + fresnel * transp; // lerp(1.0f, fresnel, transp); + float diffuse_weight = (1.0f - saturate(metallic)) * (1.0f - saturate(spec_trans)); // lerp(1.0f - clamp(metallic, 0.0f, 1.0f), 0.0f, lerp(clamp(spec_trans, 0.0f, 1.0f), 0.0f, clamp(metallic, 0.0f, 1.0f))); + + float spec_transp = saturate(spec_trans) * (1.0f - saturate(metallic)); // lerp(clamp(spec_trans, 0.0f, 1.0f), 0.0f, clamp(metallic, 0.0f, 1.0f)); + float specular_weight = (1.0f - spec_transp); // + fresnel * spec_transp; // lerp(1.0f, fresnel, spec_transp); // get the base color uint4 data_base_color = read_node(kg, offset); @@ -139,6 +144,11 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * float3 weight = ccl_fetch(sd, svm_closure_weight) * mix_weight; + if(surface_type == SOLID_SURFACE) { + flatness = 0.0f; + diff_trans = 0.0f; + } + #ifdef __SUBSURFACE__ float3 albedo = subsurface_color; float3 subsurf_weight = weight * diffuse_weight; @@ -152,20 +162,21 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * } /* diffuse */ - if(subsurface < CLOSURE_WEIGHT_CUTOFF && diffuse_weight > CLOSURE_WEIGHT_CUTOFF && fabsf(average(base_color)) > CLOSURE_WEIGHT_CUTOFF) { - float3 diff_weight = weight * base_color * diffuse_weight; + if((surface_type == THIN_SURFACE || subsurface < CLOSURE_WEIGHT_CUTOFF) && diffuse_weight > CLOSURE_WEIGHT_CUTOFF && fabsf(average(base_color)) > CLOSURE_WEIGHT_CUTOFF) { + float3 diff_weight = weight * base_color * diffuse_weight * ((2.0f - diff_trans) / 2.0f); DisneyDiffuseBsdf *bsdf = (DisneyDiffuseBsdf*)bsdf_alloc(sd, sizeof(DisneyDiffuseBsdf), diff_weight); if(bsdf) { bsdf->N = N; + bsdf->flatness = flatness; bsdf->roughness = roughness; /* setup bsdf */ ccl_fetch(sd, flag) |= bsdf_disney_diffuse_setup(bsdf); } } - else if(subsurf_sample_weight > CLOSURE_WEIGHT_CUTOFF) { + else if(surface_type == SOLID_SURFACE && subsurf_sample_weight > CLOSURE_WEIGHT_CUTOFF) { /* radius * scale */ float3 radius = subsurface_radius * subsurface; /* sharpness */ @@ -183,7 +194,6 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * bssrdf->sharpness = sharpness; bssrdf->N = N; bssrdf->base_color = base_color; - bssrdf->roughness = roughness; /* setup bsdf */ ccl_fetch(sd, flag) |= bssrdf_setup(bssrdf, (ClosureType)CLOSURE_BSSRDF_DISNEY_ID); @@ -198,7 +208,6 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * bssrdf->sharpness = sharpness; bssrdf->N = N; bssrdf->base_color = base_color; - bssrdf->roughness = roughness; /* setup bsdf */ ccl_fetch(sd, flag) |= bssrdf_setup(bssrdf, (ClosureType)CLOSURE_BSSRDF_DISNEY_ID); @@ -213,7 +222,6 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * bssrdf->sharpness = sharpness; bssrdf->N = N; bssrdf->base_color = base_color; - bssrdf->roughness = roughness; /* setup bsdf */ ccl_fetch(sd, flag) |= bssrdf_setup(bssrdf, (ClosureType)CLOSURE_BSSRDF_DISNEY_ID); @@ -228,6 +236,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * if(bsdf) { bsdf->N = N; + bsdf->flatness = flatness; bsdf->roughness = roughness; /* setup bsdf */ @@ -236,6 +245,21 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * } #endif + /* retro reflection */ + if(diffuse_weight > CLOSURE_WEIGHT_CUTOFF && fabsf(average(base_color)) > CLOSURE_WEIGHT_CUTOFF) { + float3 diff_weight = weight * base_color * diffuse_weight; + + DisneyDiffuseBsdf *bsdf = (DisneyDiffuseBsdf*)bsdf_alloc(sd, sizeof(DisneyDiffuseBsdf), diff_weight); + + if(bsdf) { + bsdf->N = N; + bsdf->roughness = roughness; + + /* setup bsdf */ + ccl_fetch(sd, flag) |= bsdf_disney_retro_reflection_setup(bsdf); + } + } + /* sheen */ if(diffuse_weight > CLOSURE_WEIGHT_CUTOFF && sheen > CLOSURE_WEIGHT_CUTOFF) { float m_cdlum = linear_rgb_to_gray(base_color); @@ -256,6 +280,20 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * } } + /* diffuse transmission */ + if(surface_type == THIN_SURFACE && diff_trans > CLOSURE_WEIGHT_CUTOFF && diffuse_weight > CLOSURE_WEIGHT_CUTOFF) { + float3 diff_weight = weight * base_color * diffuse_weight * (diff_trans / 2.0f); + + DisneyDiffuseBsdf *bsdf = (DisneyDiffuseBsdf*)bsdf_alloc(sd, sizeof(DisneyDiffuseBsdf), diff_weight); + + if(bsdf) { + bsdf->N = N; + + /* setup bsdf */ + ccl_fetch(sd, flag) |= bsdf_disney_diffuse_transmit_setup(bsdf); + } + } + /* specular reflection */ #ifdef __CAUSTICS_TRICKS__ if(kernel_data.integrator.caustics_reflective || (path_flag & PATH_RAY_DIFFUSE) == 0) { @@ -327,11 +365,11 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * #ifdef __CAUSTICS_TRICKS__ if(kernel_data.integrator.caustics_reflective || kernel_data.integrator.caustics_refractive || (path_flag & PATH_RAY_DIFFUSE) == 0) { #endif - if(transp > CLOSURE_WEIGHT_CUTOFF) { - float3 glass_weight = weight * transp; + if(spec_transp > CLOSURE_WEIGHT_CUTOFF) { + float3 glass_weight = weight * spec_transp; float3 cspec0 = base_color * specular_tint + make_float3(1.0f, 1.0f, 1.0f) * (1.0f - specular_tint); - if(roughness <= 5e-2f || distribution == CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID) { /* use single-scatter GGX */ + if(roughness <= 5e-2f || distribution == CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID || surface_type == THIN_SURFACE) { /* use single-scatter GGX */ float refl_roughness = roughness; /* reflection */ @@ -393,8 +431,20 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * else refraction_roughness = refl_roughness; - bsdf->alpha_x = refraction_roughness * refraction_roughness; - bsdf->alpha_y = refraction_roughness * refraction_roughness; + /* Remap the roughness for thin surfaces as introduced in the 2015 Disney paper: + * + * Extending the Disney BRDF to a BSDF with Integrated Subsurface Scattering + * Burley, Brent (Walt Disney Animation Studios) */ + if(surface_type == THIN_SURFACE) { + refraction_roughness *= 0.65f * ior - 0.35f; + //refraction_roughness = safe_sqrtf(refraction_roughness); + } + else { + refraction_roughness *= refraction_roughness; + } + + bsdf->alpha_x = refraction_roughness; + bsdf->alpha_y = refraction_roughness; bsdf->ior = ior; /* setup bsdf */ diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index ae75a9f4bf6..f3df5d7bf6d 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -396,6 +396,8 @@ typedef enum ClosureType { CLOSURE_BSDF_OREN_NAYAR_ID, CLOSURE_BSDF_DIFFUSE_RAMP_ID, CLOSURE_BSDF_DISNEY_DIFFUSE_ID, + CLOSURE_BSDF_DISNEY_DIFFUSE_TRANSMIT_ID, + CLOSURE_BSDF_DISNEY_RETRO_REFLECTION_ID, CLOSURE_BSDF_DISNEY_SHEEN_ID, CLOSURE_BSDF_DIFFUSE_TOON_ID, @@ -426,6 +428,7 @@ typedef enum ClosureType { CLOSURE_BSDF_REFRACTION_ID, CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID, CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID, + CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_THIN_ID, CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID, CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID, CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID, @@ -483,6 +486,11 @@ typedef enum ClosureType { #define CLOSURE_WEIGHT_CUTOFF 1e-5f +typedef enum SurfaceType { + SOLID_SURFACE, + THIN_SURFACE +} SurfaceType; + CCL_NAMESPACE_END #endif /* __SVM_TYPES_H__ */ diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp index 3d91ce08d13..1dece5408b2 100644 --- a/intern/cycles/render/graph.cpp +++ b/intern/cycles/render/graph.cpp @@ -980,7 +980,7 @@ int ShaderGraph::get_num_closures() num_closures += 2; } else if(CLOSURE_IS_DISNEY(closure_type)) { - num_closures += 8; + num_closures += 10; } else { ++num_closures; diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 848076cf818..21db1be706e 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -2229,6 +2229,10 @@ NODE_DEFINE(DisneyBsdfNode) distribution_enum.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID); distribution_enum.insert("Multiscatter GGX", CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID); SOCKET_ENUM(distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID); + static NodeEnum surface_type_enum; + surface_type_enum.insert("Solid Surface", SOLID_SURFACE); + surface_type_enum.insert("Thin Surface", THIN_SURFACE); + SOCKET_ENUM(surface_type, "Surface Type", surface_type_enum, SOLID_SURFACE); SOCKET_IN_COLOR(base_color, "Base Color", make_float3(0.8f, 0.8f, 0.8f)); SOCKET_IN_COLOR(subsurface_color, "Subsurface Color", make_float3(0.8f, 0.8f, 0.8f)); SOCKET_IN_FLOAT(metallic, "Metallic", 0.0f); @@ -2238,14 +2242,16 @@ NODE_DEFINE(DisneyBsdfNode) SOCKET_IN_FLOAT(roughness, "Roughness", 0.0f); SOCKET_IN_FLOAT(specular_tint, "Specular Tint", 0.0f); SOCKET_IN_FLOAT(anisotropic, "Anisotropic", 0.0f); + SOCKET_IN_FLOAT(anisotropic_rotation, "Anisotropic Rotation", 0.0f); SOCKET_IN_FLOAT(sheen, "Sheen", 0.0f); SOCKET_IN_FLOAT(sheen_tint, "Sheen Tint", 0.0f); SOCKET_IN_FLOAT(clearcoat, "Clearcoat", 0.0f); SOCKET_IN_FLOAT(clearcoat_gloss, "Clearcoat Gloss", 0.0f); + SOCKET_IN_FLOAT(spec_trans, "Specular Transmission", 0.0f); SOCKET_IN_FLOAT(ior, "IOR", 0.0f); - SOCKET_IN_FLOAT(transparency, "Transparency", 0.0f); + SOCKET_IN_FLOAT(flatness, "Flatness", 0.0f); + SOCKET_IN_FLOAT(diff_trans, "Diffuse Transmission", 0.0f); SOCKET_IN_FLOAT(refraction_roughness, "Refraction Roughness", 0.0f); - SOCKET_IN_FLOAT(anisotropic_rotation, "Anisotropic Rotation", 0.0f); SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL); SOCKET_IN_NORMAL(clearcoat_normal, "Clearcoat Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL); SOCKET_IN_NORMAL(tangent, "Tangent", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TANGENT); @@ -2278,9 +2284,9 @@ void DisneyBsdfNode::attributes(Shader *shader, AttributeRequestSet *attributes) } void DisneyBsdfNode::compile(SVMCompiler& compiler, ShaderInput *p_metallic, ShaderInput *p_subsurface, ShaderInput *p_subsurface_radius, - ShaderInput *p_specular, ShaderInput *p_roughness, ShaderInput *p_specular_tint, ShaderInput *p_anisotropic, - ShaderInput *p_sheen, ShaderInput *p_sheen_tint, ShaderInput *p_clearcoat, ShaderInput *p_clearcoat_gloss, - ShaderInput *p_ior, ShaderInput *p_transparency, ShaderInput *p_anisotropic_rotation, ShaderInput *p_refraction_roughness) + ShaderInput *p_specular, ShaderInput *p_specular_tint, ShaderInput *p_roughness, ShaderInput *p_anisotropic, ShaderInput *p_anisotropic_rotation, + ShaderInput *p_sheen, ShaderInput *p_sheen_tint, ShaderInput *p_clearcoat, ShaderInput *p_clearcoat_gloss, ShaderInput *p_spec_trans, + ShaderInput *p_ior, ShaderInput *p_flatness, ShaderInput *p_diff_trans, ShaderInput *p_refraction_roughness) { ShaderInput *base_color_in = input("Base Color"); ShaderInput *subsurface_color_in = input("Subsurface Color"); @@ -2299,14 +2305,16 @@ void DisneyBsdfNode::compile(SVMCompiler& compiler, ShaderInput *p_metallic, Sha int roughness_offset = compiler.stack_assign(p_roughness); int specular_tint_offset = compiler.stack_assign(p_specular_tint); int anisotropic_offset = compiler.stack_assign(p_anisotropic); + int anisotropic_rotation_offset = compiler.stack_assign(p_anisotropic_rotation); int sheen_offset = compiler.stack_assign(p_sheen); int sheen_tint_offset = compiler.stack_assign(p_sheen_tint); int clearcoat_offset = compiler.stack_assign(p_clearcoat); int clearcoat_gloss_offset = compiler.stack_assign(p_clearcoat_gloss); + int spec_trans_offset = compiler.stack_assign(p_spec_trans); int ior_offset = compiler.stack_assign(p_ior); - int transparency_offset = compiler.stack_assign(p_transparency); + int flatness_offset = compiler.stack_assign(p_flatness); + int diff_trans_offset = compiler.stack_assign(p_diff_trans); int refraction_roughness_offset = compiler.stack_assign(p_refraction_roughness); - int anisotropic_rotation_offset = compiler.stack_assign(p_anisotropic_rotation); int subsurface_radius_offset = compiler.stack_assign(p_subsurface_radius); compiler.add_node(NODE_CLOSURE_BSDF, @@ -2321,8 +2329,8 @@ void DisneyBsdfNode::compile(SVMCompiler& compiler, ShaderInput *p_metallic, Sha compiler.encode_uchar4(specular_offset, roughness_offset, specular_tint_offset, anisotropic_offset), compiler.encode_uchar4(sheen_offset, sheen_tint_offset, clearcoat_offset, clearcoat_gloss_offset)); - compiler.add_node(compiler.encode_uchar4(ior_offset, transparency_offset, anisotropic_rotation_offset, refraction_roughness_offset), - distribution, SVM_STACK_INVALID, SVM_STACK_INVALID); + compiler.add_node(compiler.encode_uchar4(ior_offset, spec_trans_offset, anisotropic_rotation_offset, refraction_roughness_offset), + compiler.encode_uchar4(flatness_offset, diff_trans_offset, SVM_STACK_INVALID, SVM_STACK_INVALID), distribution, surface_type); float3 bc_default = get_float3(base_color_in->socket_type); @@ -2346,14 +2354,15 @@ bool DisneyBsdfNode::has_integrator_dependency() void DisneyBsdfNode::compile(SVMCompiler& compiler) { compile(compiler, input("Metallic"), input("Subsurface"), input("Subsurface Radius"), input("Specular"), - input("Roughness"), input("Specular Tint"), input("Anisotropic"), input("Sheen"), input("Sheen Tint"), - input("Clearcoat"), input("Clearcoat Gloss"), input("IOR"), input("Transparency"), - input("Anisotropic Rotation"), input("Refraction Roughness")); + input("Specular Tint"), input("Roughness"), input("Anisotropic"), input("Anisotropic Rotation"), + input("Sheen"), input("Sheen Tint"), input("Clearcoat"), input("Clearcoat Gloss"), input("Specular Transmission"), + input("IOR"), input("Flatness"), input("Diffuse Transmission"), input("Refraction Roughness")); } void DisneyBsdfNode::compile(OSLCompiler& compiler) { compiler.parameter(this, "distribution"); + compiler.parameter(this, "surface_type"); compiler.add(this, "node_disney_bsdf"); } diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index c3e93143259..b19109b43a7 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -370,18 +370,19 @@ public: bool has_surface_bssrdf() { return true; } bool has_bssrdf_bump(); void compile(SVMCompiler& compiler, ShaderInput *metallic, ShaderInput *subsurface, ShaderInput *subsurface_radius, - ShaderInput *specular, ShaderInput *roughness, ShaderInput *specular_tint, ShaderInput *anisotropic, - ShaderInput *sheen, ShaderInput *sheen_tint, ShaderInput *clearcoat, ShaderInput *clearcoat_gloss, - ShaderInput *ior, ShaderInput *transparency, ShaderInput *anisotropic_rotation, ShaderInput *refraction_roughness); + ShaderInput *specular, ShaderInput *specular_tint, ShaderInput *roughness, ShaderInput *anisotropic, ShaderInput *anisotropic_rotation, + ShaderInput *sheen, ShaderInput *sheen_tint, ShaderInput *clearcoat, ShaderInput *clearcoat_gloss, ShaderInput *spec_trans, + ShaderInput *ior, ShaderInput *flatness, ShaderInput *diff_trans, ShaderInput *refraction_roughness); float3 base_color; float3 subsurface_color, subsurface_radius; float metallic, subsurface, specular, roughness, specular_tint, anisotropic, - sheen, sheen_tint, clearcoat, clearcoat_gloss, ior, transparency, - anisotropic_rotation, refraction_roughness; + sheen, sheen_tint, clearcoat, clearcoat_gloss, ior, spec_trans, diff_trans, + anisotropic_rotation, refraction_roughness, flatness; float3 normal, clearcoat_normal, tangent; float surface_mix_weight; ClosureType closure, distribution, distribution_orig; + SurfaceType surface_type; virtual bool equals(const ShaderNode * /*other*/) { diff --git a/release/datafiles/locale b/release/datafiles/locale -Subproject dc166057192ea882b5cc70484d4c8bacd7cb41b +Subproject 2b3c19f5f61fc72dba56a7edfdc4e55e2327dc1 diff --git a/release/scripts/addons b/release/scripts/addons -Subproject 06dad53c80801e0e0919f086040e3d9c31bbd0a +Subproject 3d8df6195de4062b60783c6c7791904a5f0087a diff --git a/release/scripts/addons_contrib b/release/scripts/addons_contrib -Subproject 04af69be141a5757fc60b44cc1a5b72db524af3 +Subproject a52733b58d95ce60ecde95a9eca242e7319c285 diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index c3e222cb726..cdf6ca70621 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -1071,6 +1071,12 @@ static void node_shader_buts_glossy(uiLayout *layout, bContext *UNUSED(C), Point uiItemR(layout, ptr, "distribution", 0, "", ICON_NONE); } +static void node_shader_buts_disney(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "distribution", 0, "", ICON_NONE); + uiItemR(layout, ptr, "surface_type", 0, "", ICON_NONE); +} + static void node_shader_buts_anisotropic(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { uiItemR(layout, ptr, "distribution", 0, "", ICON_NONE); @@ -1234,9 +1240,11 @@ static void node_shader_set_butfunc(bNodeType *ntype) case SH_NODE_BSDF_GLOSSY: case SH_NODE_BSDF_GLASS: case SH_NODE_BSDF_REFRACTION: - case SH_NODE_BSDF_DISNEY: ntype->draw_buttons = node_shader_buts_glossy; break; + case SH_NODE_BSDF_DISNEY: + ntype->draw_buttons = node_shader_buts_disney; + break; case SH_NODE_BSDF_ANISOTROPIC: ntype->draw_buttons = node_shader_buts_anisotropic; break; diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 46b30f41f5b..1ef2ba4cbe4 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -915,6 +915,10 @@ typedef struct NodeSunBeams { #define SHD_GLOSSY_ASHIKHMIN_SHIRLEY 3 #define SHD_GLOSSY_MULTI_GGX 4 +/* surface type */ +#define SHD_THIN_SURFACE 0 +#define SHD_SOLID_SURFACE 1 + /* vector transform */ #define SHD_VECT_TRANSFORM_TYPE_VECTOR 0 #define SHD_VECT_TRANSFORM_TYPE_POINT 1 diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 14e46e15343..b7752f17b89 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -4205,6 +4205,18 @@ static void def_disney(StructRNA *srna) RNA_def_property_enum_items(prop, prop_disney_distribution_items); RNA_def_property_ui_text(prop, "Distribution", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNodeDisney_update"); + + static EnumPropertyItem prop_disney_surface_type_items[] = { + { SHD_THIN_SURFACE, "THIN_SURFACE", 0, "Thin Surface", "" }, + { SHD_SOLID_SURFACE, "SOLID_SURFACE", 0, "Solid Surface", "" }, + { 0, NULL, 0, NULL, NULL } + }; + + prop = RNA_def_property(srna, "surface_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "custom2"); + RNA_def_property_enum_items(prop, prop_disney_surface_type_items); + RNA_def_property_ui_text(prop, "Surface Type", ""); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNodeDisney_update"); } static void def_refraction(StructRNA *srna) diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_disney.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_disney.c index 54af18a64a7..6c3884c3366 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_disney.c +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_disney.c @@ -44,8 +44,10 @@ static bNodeSocketTemplate sh_node_bsdf_disney_in[] = { { SOCK_FLOAT, 1, N_("Sheen Tint"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, { SOCK_FLOAT, 1, N_("Clearcoat"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, { SOCK_FLOAT, 1, N_("Clearcoat Gloss"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_FLOAT, 1, N_("Specular Transmission"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, { SOCK_FLOAT, 1, N_("IOR"), 1.45f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f}, - { SOCK_FLOAT, 1, N_("Transparency"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_FLOAT, 1, N_("Flatness"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_FLOAT, 1, N_("Diffuse Transmission"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f, PROP_FACTOR}, { SOCK_FLOAT, 1, N_("Refraction Roughness"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, { SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, { SOCK_VECTOR, 1, N_("Clearcoat Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, @@ -61,14 +63,15 @@ static bNodeSocketTemplate sh_node_bsdf_disney_out[] = { static void node_shader_init_disney(bNodeTree *UNUSED(ntree), bNode *node) { node->custom1 = SHD_GLOSSY_MULTI_GGX; + node->custom2 = SHD_SOLID_SURFACE; } static int node_shader_gpu_bsdf_disney(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { - if (!in[16].link) - in[16].link = GPU_builtin(GPU_VIEW_NORMAL); + if (!in[18].link) + in[18].link = GPU_builtin(GPU_VIEW_NORMAL); else - GPU_link(mat, "direction_transform_m4v3", in[16].link, GPU_builtin(GPU_VIEW_MATRIX), &in[16].link); + GPU_link(mat, "direction_transform_m4v3", in[18].link, GPU_builtin(GPU_VIEW_MATRIX), &in[18].link); return GPU_stack_link(mat, "node_bsdf_disney", in, out); } @@ -77,6 +80,7 @@ static void node_shader_update_disney(bNodeTree *UNUSED(ntree), bNode *node) { bNodeSocket *sock; int distribution = node->custom1; + int surface_type = node->custom2; for (sock = node->inputs.first; sock; sock = sock->next) { if (STREQ(sock->name, "Refraction Roughness")) { @@ -84,7 +88,36 @@ static void node_shader_update_disney(bNodeTree *UNUSED(ntree), bNode *node) sock->flag &= ~SOCK_UNAVAIL; else sock->flag |= SOCK_UNAVAIL; - + } + else if (STREQ(sock->name, "Diffuse Transmission")) { + if (surface_type == SHD_THIN_SURFACE) + sock->flag &= ~SOCK_UNAVAIL; + else + sock->flag |= SOCK_UNAVAIL; + } + else if (STREQ(sock->name, "Subsurface")) { + if (surface_type == SHD_SOLID_SURFACE) + sock->flag &= ~SOCK_UNAVAIL; + else + sock->flag |= SOCK_UNAVAIL; + } + else if (STREQ(sock->name, "Subsurface Radius")) { + if (surface_type == SHD_SOLID_SURFACE) + sock->flag &= ~SOCK_UNAVAIL; + else + sock->flag |= SOCK_UNAVAIL; + } + else if (STREQ(sock->name, "Subsurface Color")) { + if (surface_type == SHD_SOLID_SURFACE) + sock->flag &= ~SOCK_UNAVAIL; + else + sock->flag |= SOCK_UNAVAIL; + } + else if (STREQ(sock->name, "Flatness")) { + if (surface_type == SHD_THIN_SURFACE) + sock->flag &= ~SOCK_UNAVAIL; + else + sock->flag |= SOCK_UNAVAIL; } } } |