diff options
-rw-r--r-- | intern/cycles/kernel/closure/bsdf_principled_sheen.h | 25 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_passes.h | 4 | ||||
-rw-r--r-- | intern/cycles/kernel/osl/osl_closures.cpp | 40 | ||||
-rw-r--r-- | intern/cycles/kernel/svm/svm_closure.h | 2 |
4 files changed, 55 insertions, 16 deletions
diff --git a/intern/cycles/kernel/closure/bsdf_principled_sheen.h b/intern/cycles/kernel/closure/bsdf_principled_sheen.h index 1326d23668a..3707de29d73 100644 --- a/intern/cycles/kernel/closure/bsdf_principled_sheen.h +++ b/intern/cycles/kernel/closure/bsdf_principled_sheen.h @@ -26,13 +26,26 @@ CCL_NAMESPACE_BEGIN typedef ccl_addr_space struct PrincipledSheenBsdf { SHADER_CLOSURE_BASE; + float avg_value; } PrincipledSheenBsdf; static_assert(sizeof(ShaderClosure) >= sizeof(PrincipledSheenBsdf), "PrincipledSheenBsdf is too large!"); -ccl_device float3 calculate_principled_sheen_brdf( - const PrincipledSheenBsdf *bsdf, float3 N, float3 V, float3 L, float3 H, float *pdf) +ccl_device_inline float calculate_avg_principled_sheen_brdf(float3 N, float3 I) +{ + /* To compute the average, we set the half-vector to the normal, resulting in + * NdotI = NdotL = NdotV = LdotH */ + float NdotI = dot(N, I); + if (NdotI < 0.0f) { + return 0.0f; + } + + return schlick_fresnel(NdotI) * NdotI; +} + +ccl_device float3 +calculate_principled_sheen_brdf(float3 N, float3 V, float3 L, float3 H, float *pdf) { float NdotL = dot(N, L); float NdotV = dot(N, V); @@ -49,9 +62,11 @@ ccl_device float3 calculate_principled_sheen_brdf( return make_float3(value, value, value); } -ccl_device int bsdf_principled_sheen_setup(PrincipledSheenBsdf *bsdf) +ccl_device int bsdf_principled_sheen_setup(const ShaderData *sd, PrincipledSheenBsdf *bsdf) { bsdf->type = CLOSURE_BSDF_PRINCIPLED_SHEEN_ID; + bsdf->avg_value = calculate_avg_principled_sheen_brdf(bsdf->N, sd->I); + bsdf->sample_weight *= bsdf->avg_value; return SD_BSDF | SD_BSDF_HAS_EVAL; } @@ -69,7 +84,7 @@ ccl_device float3 bsdf_principled_sheen_eval_reflect(const ShaderClosure *sc, if (dot(N, omega_in) > 0.0f) { *pdf = fmaxf(dot(N, omega_in), 0.0f) * M_1_PI_F; - return calculate_principled_sheen_brdf(bsdf, N, V, L, H, pdf); + return calculate_principled_sheen_brdf(N, V, L, H, pdf); } else { *pdf = 0.0f; @@ -107,7 +122,7 @@ ccl_device int bsdf_principled_sheen_sample(const ShaderClosure *sc, if (dot(Ng, *omega_in) > 0) { float3 H = normalize(I + *omega_in); - *eval = calculate_principled_sheen_brdf(bsdf, N, I, *omega_in, H, pdf); + *eval = calculate_principled_sheen_brdf(N, I, *omega_in, H, pdf); #ifdef __RAY_DIFFERENTIALS__ // TODO: find a better approximation for the diffuse bounce diff --git a/intern/cycles/kernel/kernel_passes.h b/intern/cycles/kernel/kernel_passes.h index d372a4f3e61..7345e9ee5bb 100644 --- a/intern/cycles/kernel/kernel_passes.h +++ b/intern/cycles/kernel/kernel_passes.h @@ -80,6 +80,10 @@ ccl_device_inline void kernel_update_denoising_features(KernelGlobals *kg, MicrofacetBsdf *bsdf = (MicrofacetBsdf *)sc; closure_albedo *= bsdf->extra->fresnel_color; } + else if (sc->type == CLOSURE_BSDF_PRINCIPLED_SHEEN_ID) { + PrincipledSheenBsdf *bsdf = (PrincipledSheenBsdf *)sc; + closure_albedo *= bsdf->avg_value; + } albedo += closure_albedo; sum_nonspecular_weight += sc->sample_weight; diff --git a/intern/cycles/kernel/osl/osl_closures.cpp b/intern/cycles/kernel/osl/osl_closures.cpp index 27205df3732..463a65f21a0 100644 --- a/intern/cycles/kernel/osl/osl_closures.cpp +++ b/intern/cycles/kernel/osl/osl_closures.cpp @@ -197,15 +197,32 @@ CLOSURE_FLOAT3_PARAM(DiffuseClosure, params.N), CLOSURE_FLOAT_PARAM(PrincipledDiffuseClosure, params.roughness), BSDF_CLOSURE_CLASS_END(PrincipledDiffuse, principled_diffuse) - BSDF_CLOSURE_CLASS_BEGIN(PrincipledSheen, - principled_sheen, - PrincipledSheenBsdf, - LABEL_DIFFUSE) - CLOSURE_FLOAT3_PARAM(PrincipledSheenClosure, params.N), - BSDF_CLOSURE_CLASS_END(PrincipledSheen, principled_sheen) + class PrincipledSheenClosure : public CBSDFClosure { + public: + PrincipledSheenBsdf params; + + void setup(ShaderData *sd, int path_flag, float3 weight) + { + if (!skip(sd, path_flag, LABEL_DIFFUSE)) { + PrincipledSheenBsdf *bsdf = (PrincipledSheenBsdf *)bsdf_alloc_osl( + sd, sizeof(PrincipledSheenBsdf), weight, ¶ms); + sd->flag |= (bsdf) ? bsdf_principled_sheen_setup(sd, bsdf) : 0; + } + } +}; - /* PRINCIPLED HAIR BSDF */ - class PrincipledHairClosure : public CBSDFClosure { +static ClosureParam *bsdf_principled_sheen_params() +{ + static ClosureParam params[] = {CLOSURE_FLOAT3_PARAM(PrincipledSheenClosure, params.N), + CLOSURE_STRING_KEYPARAM(PrincipledSheenClosure, label, "label"), + CLOSURE_FINISH_PARAM(PrincipledSheenClosure)}; + return params; +} + +CCLOSURE_PREPARE_STATIC(closure_bsdf_principled_sheen_prepare, PrincipledSheenClosure) + +/* PRINCIPLED HAIR BSDF */ +class PrincipledHairClosure : public CBSDFClosure { public: PrincipledHairBSDF params; @@ -425,8 +442,11 @@ void OSLShader::register_closures(OSLShadingSystem *ss_) id++, bsdf_principled_diffuse_params(), bsdf_principled_diffuse_prepare); - register_closure( - ss, "principled_sheen", id++, bsdf_principled_sheen_params(), bsdf_principled_sheen_prepare); + register_closure(ss, + "principled_sheen", + id++, + bsdf_principled_sheen_params(), + closure_bsdf_principled_sheen_prepare); register_closure(ss, "principled_clearcoat", id++, diff --git a/intern/cycles/kernel/svm/svm_closure.h b/intern/cycles/kernel/svm/svm_closure.h index 1511fc65835..bf2d3f4fbff 100644 --- a/intern/cycles/kernel/svm/svm_closure.h +++ b/intern/cycles/kernel/svm/svm_closure.h @@ -290,7 +290,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, bsdf->N = N; /* setup bsdf */ - sd->flag |= bsdf_principled_sheen_setup(bsdf); + sd->flag |= bsdf_principled_sheen_setup(sd, bsdf); } } |