From cc267e52f20d036a66aeeff127ee1c856f7c651b Mon Sep 17 00:00:00 2001 From: Pascal Schoen Date: Wed, 3 Aug 2016 15:00:25 +0200 Subject: Implemented the Disney clearcoat as a variation of the microfacet bsdf, removed the transparency roughness again and added an input for anisotropic rotations --- intern/cycles/kernel/closure/bsdf_microfacet.h | 18 ++++++++++-- intern/cycles/kernel/shaders/node_disney_bsdf.osl | 9 ++---- intern/cycles/kernel/svm/svm_closure.h | 34 +++++++++++++++-------- intern/cycles/render/nodes.cpp | 10 +++---- intern/cycles/render/nodes.h | 4 +-- 5 files changed, 48 insertions(+), 27 deletions(-) (limited to 'intern') diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h index 7173ecd64de..7ccb29c619a 100644 --- a/intern/cycles/kernel/closure/bsdf_microfacet.h +++ b/intern/cycles/kernel/closure/bsdf_microfacet.h @@ -37,7 +37,7 @@ CCL_NAMESPACE_BEGIN typedef ccl_addr_space struct MicrofacetExtra { float3 color, cspec0; - bool use_fresnel; + bool use_fresnel, is_disney_clearcoat; } MicrofacetExtra; typedef ccl_addr_space struct MicrofacetBsdf { @@ -247,10 +247,11 @@ ccl_device_inline float3 microfacet_sample_stretched( * Anisotropy is only supported for reflection currently, but adding it for * transmission is just a matter of copying code from reflection if needed. */ -ccl_device int bsdf_microfacet_ggx_setup(MicrofacetBsdf *bsdf, bool use_fresnel = false) +ccl_device int bsdf_microfacet_ggx_setup(MicrofacetBsdf *bsdf, bool use_fresnel = false, bool is_disney_clearcoat = false) { if (bsdf->extra) { bsdf->extra->use_fresnel = use_fresnel; + bsdf->extra->is_disney_clearcoat = is_disney_clearcoat; bsdf->extra->cspec0.x = saturate(bsdf->extra->cspec0.x); bsdf->extra->cspec0.y = saturate(bsdf->extra->cspec0.y); @@ -284,6 +285,7 @@ ccl_device int bsdf_microfacet_ggx_aniso_setup(MicrofacetBsdf *bsdf, bool use_fr { if (bsdf->extra) { bsdf->extra->use_fresnel = use_fresnel; + bsdf->extra->is_disney_clearcoat = false; bsdf->extra->cspec0.x = saturate(bsdf->extra->cspec0.x); bsdf->extra->cspec0.y = saturate(bsdf->extra->cspec0.y); @@ -302,6 +304,7 @@ ccl_device int bsdf_microfacet_ggx_refraction_setup(MicrofacetBsdf *bsdf, bool u { if (bsdf->extra) { bsdf->extra->use_fresnel = use_fresnel; + bsdf->extra->is_disney_clearcoat = false; bsdf->extra->cspec0.x = saturate(bsdf->extra->cspec0.x); bsdf->extra->cspec0.y = saturate(bsdf->extra->cspec0.y); @@ -355,6 +358,10 @@ ccl_device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderClosure *sc, cons D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2)); /* eq. 34: now calculate G1(i,m) and G1(o,m) */ + if (bsdf->extra) + if (bsdf->extra->is_disney_clearcoat) + alpha2 = 0.0625f; + G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO))); G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI))); } @@ -550,6 +557,13 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg, const ShaderClosure float cosNI = dot(N, *omega_in); /* eq. 34: now calculate G1(i,m) */ + if (bsdf->extra) + if (bsdf->extra->is_disney_clearcoat) { + // recalculate G1o + G1o = 2 / (1 + safe_sqrtf(1 + 0.0625f * (1 - cosNO * cosNO) / (cosNO * cosNO))); + alpha2 = 0.0625f; + } + G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI))); } else { diff --git a/intern/cycles/kernel/shaders/node_disney_bsdf.osl b/intern/cycles/kernel/shaders/node_disney_bsdf.osl index dce39b2d6f3..06f1e97a187 100644 --- a/intern/cycles/kernel/shaders/node_disney_bsdf.osl +++ b/intern/cycles/kernel/shaders/node_disney_bsdf.osl @@ -32,11 +32,10 @@ shader node_disney_bsdf( float ClearcoatGloss = 1.0, float IOR = 1.45, float Transparency = 0.0, - float RefractionRoughness = 0.0, + float AnisotropicRotation = 0.0, normal Normal = N, normal ClearcoatNormal = N, normal Tangent = normalize(dPdu), - //normal AnisotropicRotation = normal(0, 0, 0), output closure color BSDF = 0) { float f = max(IOR, 1e-5); @@ -47,8 +46,6 @@ shader node_disney_bsdf( float transp = clamp(Transparency, 0.0, 1.0) * (1.0 - clamp(Metallic, 0.0, 1.0)); float specular_weight = (1.0 - transp); - float refr_roughness = 1.0 - (1.0 - Roughness) * (1.0 - RefractionRoughness); - if (diffuse_weight > 0.0) { BSDF = (((Subsurface * BaseColor * bssrdf_burley(Normal, vector(1.0, 1.0, 1.0), 0.0, BaseColor)) + disney_diffuse(Normal, BaseColor, Roughness) * (1.0 - Subsurface)) + disney_sheen(Normal, BaseColor, Sheen, SheenTint)) * diffuse_weight; @@ -58,10 +55,10 @@ shader node_disney_bsdf( BSDF = BSDF + specular_weight * disney_specular(Normal, Tangent, BaseColor, Metallic, Specular, SpecularTint, Roughness, Anisotropic) + (1.0 - specular_weight) * (Fr * disney_specular(Normal, Tangent, BaseColor, 0.0, 12.5, - SpecularTint, Roughness, 0.0) + (1.0 - Fr) * BaseColor * microfacet_ggx_refraction(Normal, refr_roughness * refr_roughness, eta)); + SpecularTint, Roughness, 0.0) + (1.0 - Fr) * BaseColor * microfacet_ggx_refraction(Normal, Roughness * Roughness, eta)); } else if (transp > 0.0) { BSDF = BSDF + transp * (disney_specular(Normal, Tangent, BaseColor, 0.0, 12.5, SpecularTint, Roughness, 0.0) - + BaseColor * microfacet_ggx_refraction(Normal, refr_roughness * refr_roughness, eta)); + + BaseColor * microfacet_ggx_refraction(Normal, Roughness * Roughness, eta)); } if (Clearcoat != 0.0) { diff --git a/intern/cycles/kernel/svm/svm_closure.h b/intern/cycles/kernel/svm/svm_closure.h index 2f886308a64..332535b787b 100644 --- a/intern/cycles/kernel/svm/svm_closure.h +++ b/intern/cycles/kernel/svm/svm_closure.h @@ -78,14 +78,14 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * switch(type) { case CLOSURE_BSDF_DISNEY_ID: { uint specular_offset, roughness_offset, specularTint_offset, anisotropic_offset, sheen_offset, - sheenTint_offset, clearcoat_offset, clearcoatGloss_offset, eta_offset, transparency_offset, refr_roughness_offset; + sheenTint_offset, clearcoat_offset, clearcoatGloss_offset, eta_offset, transparency_offset, anisotropic_rotation_offset; uint tmp0; 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, &specularTint_offset, &anisotropic_offset); decode_node_uchar4(data_node.w, &sheen_offset, &sheenTint_offset, &clearcoat_offset, &clearcoatGloss_offset); - decode_node_uchar4(data_node2.x, &eta_offset, &transparency_offset, &refr_roughness_offset, &tmp0); + decode_node_uchar4(data_node2.x, &eta_offset, &transparency_offset, &anisotropic_rotation_offset, &tmp0); // get disney parameters float metallic = param1; @@ -99,10 +99,14 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * float clearcoat = stack_load_float(stack, clearcoat_offset); float clearcoatGloss = stack_load_float(stack, clearcoatGloss_offset); float transparency = stack_load_float(stack, transparency_offset); - float refr_roughness = stack_load_float(stack, refr_roughness_offset); - refr_roughness = 1.0f - (1.0f - roughness) * (1.0f - refr_roughness); + float anisotropic_rotation = stack_load_float(stack, anisotropic_rotation_offset); float eta = fmaxf(stack_load_float(stack, eta_offset), 1e-5f); + /* 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; // calculate fresnel for refraction @@ -283,8 +287,8 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * bsdf->extra = extra; bsdf->T = make_float3(0.0f, 0.0f, 0.0f); - bsdf->alpha_x = refr_roughness * refr_roughness; - bsdf->alpha_y = refr_roughness * refr_roughness; + bsdf->alpha_x = roughness * roughness; + bsdf->alpha_y = roughness * roughness; bsdf->ior = ior; bsdf->extra->color = baseColor; @@ -302,18 +306,24 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * if (kernel_data.integrator.caustics_reflective || (path_flag & PATH_RAY_DIFFUSE) == 0) { #endif if (clearcoat > 0.0f) { - float3 clearcoat_weight = weight; + float3 clearcoat_weight = 0.25f * clearcoat * weight; float clearcoat_sample_weight = fabsf(average(clearcoat_weight)); - DisneyClearcoatBsdf *bsdf = (DisneyClearcoatBsdf*)bsdf_alloc(sd, sizeof(DisneyClearcoatBsdf), clearcoat_weight); + MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), clearcoat_weight); + MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra)); - if (bsdf) { + if (bsdf && extra) { bsdf->N = CN; - bsdf->clearcoat = clearcoat; - bsdf->clearcoatGloss = clearcoatGloss; + bsdf->ior = 0.0f; + bsdf->extra = extra; + + bsdf->alpha_x = 0.1f * (1.0f - clearcoatGloss) + 0.001f * clearcoatGloss; + bsdf->alpha_y = 0.1f * (1.0f - clearcoatGloss) + 0.001f * clearcoatGloss; + + bsdf->extra->cspec0 = make_float3(0.04f, 0.04f, 0.04f); /* setup bsdf */ - ccl_fetch(sd, flag) |= bsdf_disney_clearcoat_setup(bsdf); + ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_setup(bsdf, true, true); } } #ifdef __CAUSTICS_TRICKS__ diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index cf366367873..c377e899936 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -2226,7 +2226,7 @@ NODE_DEFINE(DisneyBsdfNode) SOCKET_IN_FLOAT(clearcoatGloss, "ClearcoatGloss", 0.0f); SOCKET_IN_FLOAT(ior, "IOR", 0.0f); SOCKET_IN_FLOAT(transparency, "Transparency", 0.0f); - SOCKET_IN_FLOAT(refractionRoughness, "RefractionRoughness", 0.0f); + SOCKET_IN_FLOAT(anisotropicRotation, "AnisotropicRotation", 0.0f); SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL); SOCKET_IN_NORMAL(clearcoatNormal, "ClearcoatNormal", 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); @@ -2247,7 +2247,7 @@ DisneyBsdfNode::DisneyBsdfNode() void DisneyBsdfNode::compile(SVMCompiler& compiler, ShaderInput *metallic, ShaderInput *subsurface, ShaderInput *specular, ShaderInput *roughness, ShaderInput *specularTint, ShaderInput *anisotropic, ShaderInput *sheen, ShaderInput *sheenTint, ShaderInput *clearcoat, ShaderInput *clearcoatGloss, - ShaderInput *ior, ShaderInput *transparency, ShaderInput *refr_roughness) + ShaderInput *ior, ShaderInput *transparency, ShaderInput *anisotropicRotation) { ShaderInput *base_color_in = input("BaseColor"); ShaderInput *subsurface_color_in = input("SubsurfaceColor"); @@ -2276,7 +2276,7 @@ void DisneyBsdfNode::compile(SVMCompiler& compiler, ShaderInput *metallic, Shade int clearcoatGloss_offset = compiler.stack_assign(clearcoatGloss); int ior_offset = compiler.stack_assign(ior); int transparency_offset = compiler.stack_assign(transparency); - int refr_roughness_offset = compiler.stack_assign(refr_roughness); + int anisotropic_rotation_offset = compiler.stack_assign(anisotropicRotation); compiler.add_node(NODE_CLOSURE_BSDF, compiler.encode_uchar4(closure, @@ -2290,7 +2290,7 @@ void DisneyBsdfNode::compile(SVMCompiler& compiler, ShaderInput *metallic, Shade compiler.encode_uchar4(specular_offset, roughness_offset, specularTint_offset, anisotropic_offset), compiler.encode_uchar4(sheen_offset, sheenTint_offset, clearcoat_offset, clearcoatGloss_offset)); - compiler.add_node(compiler.encode_uchar4(ior_offset, transparency_offset, refr_roughness_offset, SVM_STACK_INVALID), + compiler.add_node(compiler.encode_uchar4(ior_offset, transparency_offset, anisotropic_rotation_offset, SVM_STACK_INVALID), SVM_STACK_INVALID, SVM_STACK_INVALID, SVM_STACK_INVALID); float3 bc_default = get_float3(base_color_in->socket_type); @@ -2310,7 +2310,7 @@ void DisneyBsdfNode::compile(SVMCompiler& compiler) { compile(compiler, input("Metallic"), input("Subsurface"), input("Specular"), input("Roughness"), input("SpecularTint"), input("Anisotropic"), input("Sheen"), input("SheenTint"), - input("Clearcoat"), input("ClearcoatGloss"), input("IOR"), input("Transparency"), input("RefractionRoughness")); + input("Clearcoat"), input("ClearcoatGloss"), input("IOR"), input("Transparency"), input("AnisotropicRotation")); } void DisneyBsdfNode::compile(OSLCompiler& compiler) diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index 6c2467d9bee..c916e4a5f5e 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -372,12 +372,12 @@ public: void compile(SVMCompiler& compiler, ShaderInput *metallic, ShaderInput *subsurface, ShaderInput *specular, ShaderInput *roughness, ShaderInput *specularTint, ShaderInput *anisotropic, ShaderInput *sheen, ShaderInput *sheenTint, ShaderInput *clearcoat, ShaderInput *clearcoatGloss, - ShaderInput *ior, ShaderInput *transparency, ShaderInput *refr_roughness); + ShaderInput *ior, ShaderInput *transparency, ShaderInput *anisotropicRotation); float3 base_color; float3 subsurface_color; float metallic, subsurface, specular, roughness, specularTint, anisotropic, - sheen, sheenTint, clearcoat, clearcoatGloss, ior, transparency, refractionRoughness; + sheen, sheenTint, clearcoat, clearcoatGloss, ior, transparency, anisotropicRotation; float3 normal, clearcoatNormal, tangent; float surface_mix_weight; ClosureType closure; -- cgit v1.2.3