From 778652612e27877a44d751413c6ca359e745ebbc Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Sat, 5 Aug 2023 00:01:43 +0200 Subject: [PATCH 1/7] Cycles: Tweak Principled BSDF Subsurface parameters Previously, the Principled BSDF used the Subsurface input to scale the radius. When it was zero, it used a diffuse closure, otherwise a subsurface closure. This sort of scaling input makes sense, but it should be specified in distance units, rather than a 0..1 factor, so this commit changes the unit. Additionally, it adds support for mixing diffuse and subsurface components. This is part of e.g. the OpenPBR spec, and the logic behind it is to support modeling e.g. dirt or paint on top of skin. For typical materials, this will be either zero or one (like metallic or transmission), but supporting fractional inputs makes sense for e.g. smooth transitions at boundaries. --- intern/cycles/kernel/closure/bssrdf.h | 15 +++- intern/cycles/kernel/osl/closures_setup.h | 4 +- .../osl/shaders/node_principled_bsdf.osl | 29 +++--- intern/cycles/kernel/svm/closure.h | 69 +++++--------- intern/cycles/kernel/svm/types.h | 5 +- intern/cycles/scene/shader_nodes.cpp | 10 +-- intern/cycles/scene/shader_nodes.h | 4 +- .../blenloader/intern/versioning_400.cc | 90 +++++++++++++++++++ .../gpu_shader_material_principled.glsl | 4 +- .../nodes/node_shader_bsdf_principled.cc | 29 +++--- 10 files changed, 172 insertions(+), 87 deletions(-) diff --git a/intern/cycles/kernel/closure/bssrdf.h b/intern/cycles/kernel/closure/bssrdf.h index b472656efc2..07a3132d05e 100644 --- a/intern/cycles/kernel/closure/bssrdf.h +++ b/intern/cycles/kernel/closure/bssrdf.h @@ -281,17 +281,26 @@ ccl_device_inline ccl_private Bssrdf *bssrdf_alloc(ccl_private ShaderData *sd, S ccl_device int bssrdf_setup(ccl_private ShaderData *sd, ccl_private Bssrdf *bssrdf, + int path_flag, ClosureType type, - const float ior) + float ior) { + /* Clamps protecting against bad/extreme and non physical values. */ + bssrdf->anisotropy = clamp(bssrdf->anisotropy, 0.0f, 0.9f); + ior = clamp(ior, 1.01f, 3.8f); + int flag = 0; /* Verify if the radii are large enough to sample without precision issues. */ int bssrdf_channels = SPECTRUM_CHANNELS; Spectrum diffuse_weight = zero_spectrum(); + /* Fall back to diffuse in case of diffuse ancestor, can't see it well then and adds considerable + * noise due to probabilities of continuing the path getting lower and lower. */ + const bool is_diffuse_ancestor = (path_flag & PATH_RAY_DIFFUSE_ANCESTOR); + FOREACH_SPECTRUM_CHANNEL (i) { - if (GET_SPECTRUM_CHANNEL(bssrdf->radius, i) < BSSRDF_MIN_RADIUS) { + if (is_diffuse_ancestor || GET_SPECTRUM_CHANNEL(bssrdf->radius, i) < BSSRDF_MIN_RADIUS) { GET_SPECTRUM_CHANNEL(diffuse_weight, i) = GET_SPECTRUM_CHANNEL(bssrdf->weight, i); GET_SPECTRUM_CHANNEL(bssrdf->weight, i) = 0.0f; GET_SPECTRUM_CHANNEL(bssrdf->radius, i) = 0.0f; @@ -320,7 +329,7 @@ ccl_device int bssrdf_setup(ccl_private ShaderData *sd, flag |= SD_BSSRDF; } else { - bssrdf->type = type; + bssrdf->type = CLOSURE_NONE_ID; bssrdf->sample_weight = 0.0f; } diff --git a/intern/cycles/kernel/osl/closures_setup.h b/intern/cycles/kernel/osl/closures_setup.h index a8cdac2ddec..38b35050711 100644 --- a/intern/cycles/kernel/osl/closures_setup.h +++ b/intern/cycles/kernel/osl/closures_setup.h @@ -758,9 +758,9 @@ ccl_device void osl_closure_bssrdf_setup(KernelGlobals kg, bssrdf->albedo = closure->albedo; bssrdf->N = closure->N; bssrdf->roughness = closure->roughness; - bssrdf->anisotropy = clamp(closure->anisotropy, 0.0f, 0.9f); + bssrdf->anisotropy = closure->anisotropy; - sd->flag |= bssrdf_setup(sd, bssrdf, type, clamp(closure->ior, 1.01f, 3.8f)); + sd->flag |= bssrdf_setup(sd, bssrdf, path_flag, type, closure->ior); } /* Hair */ diff --git a/intern/cycles/kernel/osl/shaders/node_principled_bsdf.osl b/intern/cycles/kernel/osl/shaders/node_principled_bsdf.osl index 8e17e7afd6b..f8549b8f9b7 100644 --- a/intern/cycles/kernel/osl/shaders/node_principled_bsdf.osl +++ b/intern/cycles/kernel/osl/shaders/node_principled_bsdf.osl @@ -9,9 +9,9 @@ shader node_principled_bsdf(string distribution = "multi_ggx", string subsurface_method = "random_walk", color BaseColor = color(0.8, 0.8, 0.8), float Subsurface = 0.0, + float SubsurfaceScale = 0.1, vector SubsurfaceRadius = vector(1.0, 1.0, 1.0), color SubsurfaceColor = color(0.7, 0.1, 0.1), - float SubsurfaceIOR = 1.4, float SubsurfaceAnisotropy = 0.0, float Metallic = 0.0, float Specular = 0.5, @@ -45,21 +45,20 @@ shader node_principled_bsdf(string distribution = "multi_ggx", } if (Metallic < 1.0 && Transmission < 1.0) { - color diffuse_color = mix(BaseColor, SubsurfaceColor, Subsurface); + BSDF = BaseColor * diffuse(Normal); if (Subsurface > 1e-5) { - BSDF = diffuse_color * bssrdf(subsurface_method, - Normal, - Subsurface * SubsurfaceRadius, - diffuse_color, - "roughness", - Roughness, - "ior", - SubsurfaceIOR, - "anisotropy", - SubsurfaceAnisotropy); - } - else { - BSDF = diffuse_color * diffuse(Normal); + vector radius = SubsurfaceScale * SubsurfaceRadius; + closure color SubsurfBSDF = bssrdf(subsurface_method, + Normal, + SubsurfaceScale * SubsurfaceRadius, + SubsurfaceColor, + "roughness", + Roughness, + "ior", + IOR, + "anisotropy", + SubsurfaceAnisotropy); + BSDF = mix(BSDF, SubsurfaceColor * SubsurfBSDF, Subsurface); } color f0 = color(F0_from_ior(IOR)); diff --git a/intern/cycles/kernel/svm/closure.h b/intern/cycles/kernel/svm/closure.h index 68f849ab608..5dd07142893 100644 --- a/intern/cycles/kernel/svm/closure.h +++ b/intern/cycles/kernel/svm/closure.h @@ -125,8 +125,9 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, float3 subsurface_radius = stack_valid(data_cn_ssr.y) ? stack_load_float3(stack, data_cn_ssr.y) : one_float3(); - float subsurface_ior = stack_valid(data_cn_ssr.z) ? stack_load_float(stack, data_cn_ssr.z) : - 1.4f; + float subsurface_scale = stack_valid(data_cn_ssr.z) ? + stack_load_float(stack, data_cn_ssr.z) : + 1.0f; float subsurface_anisotropy = stack_valid(data_cn_ssr.w) ? stack_load_float(stack, data_cn_ssr.w) : 0.0f; @@ -299,44 +300,31 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, } } - /* Diffuse component */ - float3 diffuse_color = mix(base_color, subsurface_color, subsurface); + /* Diffuse/Subsurface component */ #ifdef __SUBSURFACE__ - /* disable in case of diffuse ancestor, can't see it well then and - * adds considerably noise due to probabilities of continuing path - * getting lower and lower */ - if ((subsurface > CLOSURE_WEIGHT_CUTOFF) && !(path_flag & PATH_RAY_DIFFUSE_ANCESTOR)) { - /* Skip in case of extremely low albedo. */ - if (fabsf(average(diffuse_color)) > CLOSURE_WEIGHT_CUTOFF) { - ccl_private Bssrdf *bssrdf = bssrdf_alloc(sd, rgb_to_spectrum(diffuse_color) * weight); + ccl_private Bssrdf *bssrdf = bssrdf_alloc( + sd, rgb_to_spectrum(subsurface_color) * subsurface * weight); + if (bssrdf) { + bssrdf->radius = rgb_to_spectrum(subsurface_radius * subsurface_scale); + bssrdf->albedo = rgb_to_spectrum(subsurface_color); + bssrdf->N = N; + bssrdf->roughness = sqr(roughness); + bssrdf->anisotropy = subsurface_anisotropy; - if (bssrdf) { - bssrdf->radius = rgb_to_spectrum(subsurface_radius * subsurface); - bssrdf->albedo = rgb_to_spectrum(diffuse_color); - bssrdf->N = N; - bssrdf->roughness = roughness; - - /* Clamps protecting against bad/extreme and non physical values. */ - subsurface_ior = clamp(subsurface_ior, 1.01f, 3.8f); - bssrdf->anisotropy = clamp(subsurface_anisotropy, 0.0f, 0.9f); - - /* setup bsdf */ - sd->flag |= bssrdf_setup(sd, bssrdf, subsurface_method, subsurface_ior); - } - } + /* setup bsdf */ + sd->flag |= bssrdf_setup(sd, bssrdf, path_flag, subsurface_method, eta); } - else +#else + subsurface = 0.0f; #endif - { - ccl_private DiffuseBsdf *bsdf = (ccl_private DiffuseBsdf *)bsdf_alloc( - sd, sizeof(DiffuseBsdf), rgb_to_spectrum(diffuse_color) * weight); - if (bsdf) { - bsdf->N = N; + ccl_private DiffuseBsdf *bsdf = (ccl_private DiffuseBsdf *)bsdf_alloc( + sd, sizeof(DiffuseBsdf), rgb_to_spectrum(base_color) * (1.0f - subsurface) * weight); + if (bsdf) { + bsdf->N = N; - /* setup bsdf */ - sd->flag |= bsdf_diffuse_setup(bsdf); - } + /* setup bsdf */ + sd->flag |= bsdf_diffuse_setup(bsdf); } break; @@ -721,22 +709,13 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, ccl_private Bssrdf *bssrdf = bssrdf_alloc(sd, weight); if (bssrdf) { - /* disable in case of diffuse ancestor, can't see it well then and - * adds considerably noise due to probabilities of continuing path - * getting lower and lower */ - if (path_flag & PATH_RAY_DIFFUSE_ANCESTOR) - param1 = 0.0f; - bssrdf->radius = rgb_to_spectrum(stack_load_float3(stack, data_node.z) * param1); bssrdf->albedo = closure_weight; bssrdf->N = N; bssrdf->roughness = FLT_MAX; + bssrdf->anisotropy = stack_load_float(stack, data_node.w); - const float subsurface_ior = clamp(param2, 1.01f, 3.8f); - const float subsurface_anisotropy = stack_load_float(stack, data_node.w); - bssrdf->anisotropy = clamp(subsurface_anisotropy, 0.0f, 0.9f); - - sd->flag |= bssrdf_setup(sd, bssrdf, (ClosureType)type, subsurface_ior); + sd->flag |= bssrdf_setup(sd, bssrdf, path_flag, (ClosureType)type, param2); } break; diff --git a/intern/cycles/kernel/svm/types.h b/intern/cycles/kernel/svm/types.h index bab608fc920..087ec8acf6d 100644 --- a/intern/cycles/kernel/svm/types.h +++ b/intern/cycles/kernel/svm/types.h @@ -463,7 +463,7 @@ typedef enum ClosureType { } ClosureType; /* watch this, being lazy with memory usage */ -#define CLOSURE_IS_BSDF(type) (type <= CLOSURE_BSDF_TRANSPARENT_ID) +#define CLOSURE_IS_BSDF(type) (type != CLOSURE_NONE_ID && type <= CLOSURE_BSDF_TRANSPARENT_ID) #define CLOSURE_IS_BSDF_DIFFUSE(type) \ (type >= CLOSURE_BSDF_DIFFUSE_ID && type <= CLOSURE_BSDF_TRANSLUCENT_ID) #define CLOSURE_IS_BSDF_GLOSSY(type) \ @@ -483,7 +483,8 @@ typedef enum ClosureType { type <= CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID) || \ (type >= CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID && \ type <= CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID)) -#define CLOSURE_IS_BSDF_OR_BSSRDF(type) (type <= CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID) +#define CLOSURE_IS_BSDF_OR_BSSRDF(type) \ + (type != CLOSURE_NONE_ID && type <= CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID) #define CLOSURE_IS_BSSRDF(type) \ (type >= CLOSURE_BSSRDF_BURLEY_ID && type <= CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID) #define CLOSURE_IS_VOLUME(type) \ diff --git a/intern/cycles/scene/shader_nodes.cpp b/intern/cycles/scene/shader_nodes.cpp index 896c9cc51fa..49a813ed38c 100644 --- a/intern/cycles/scene/shader_nodes.cpp +++ b/intern/cycles/scene/shader_nodes.cpp @@ -2653,8 +2653,8 @@ NODE_DEFINE(PrincipledBsdfNode) SOCKET_IN_COLOR(subsurface_color, "Subsurface Color", make_float3(0.8f, 0.8f, 0.8f)); SOCKET_IN_FLOAT(metallic, "Metallic", 0.0f); SOCKET_IN_FLOAT(subsurface, "Subsurface", 0.0f); + SOCKET_IN_FLOAT(subsurface_scale, "Subsurface Scale", 0.1f); SOCKET_IN_VECTOR(subsurface_radius, "Subsurface Radius", make_float3(0.1f, 0.1f, 0.1f)); - SOCKET_IN_FLOAT(subsurface_ior, "Subsurface IOR", 1.4f); SOCKET_IN_FLOAT(subsurface_anisotropy, "Subsurface Anisotropy", 0.0f); SOCKET_IN_FLOAT(specular, "Specular", 0.0f); SOCKET_IN_FLOAT(roughness, "Roughness", 0.5f); @@ -2764,8 +2764,8 @@ void PrincipledBsdfNode::attributes(Shader *shader, AttributeRequestSet *attribu void PrincipledBsdfNode::compile(SVMCompiler &compiler, ShaderInput *p_metallic, ShaderInput *p_subsurface, + ShaderInput *p_subsurface_scale, ShaderInput *p_subsurface_radius, - ShaderInput *p_subsurface_ior, ShaderInput *p_subsurface_anisotropy, ShaderInput *p_specular, ShaderInput *p_roughness, @@ -2806,7 +2806,7 @@ void PrincipledBsdfNode::compile(SVMCompiler &compiler, int transmission_offset = compiler.stack_assign(p_transmission); int anisotropic_rotation_offset = compiler.stack_assign(p_anisotropic_rotation); int subsurface_radius_offset = compiler.stack_assign(p_subsurface_radius); - int subsurface_ior_offset = compiler.stack_assign(p_subsurface_ior); + int subsurface_scale_offset = compiler.stack_assign(p_subsurface_scale); int subsurface_anisotropy_offset = compiler.stack_assign(p_subsurface_anisotropy); compiler.add_node(NODE_CLOSURE_BSDF, @@ -2842,7 +2842,7 @@ void PrincipledBsdfNode::compile(SVMCompiler &compiler, compiler.add_node(clearcoat_normal_offset, subsurface_radius_offset, - subsurface_ior_offset, + subsurface_scale_offset, subsurface_anisotropy_offset); float3 ss_default = get_float3(subsurface_color_in->socket_type); @@ -2859,8 +2859,8 @@ void PrincipledBsdfNode::compile(SVMCompiler &compiler) compile(compiler, input("Metallic"), input("Subsurface"), + input("Subsurface Scale"), input("Subsurface Radius"), - input("Subsurface IOR"), input("Subsurface Anisotropy"), input("Specular"), input("Roughness"), diff --git a/intern/cycles/scene/shader_nodes.h b/intern/cycles/scene/shader_nodes.h index 764e0cc9c52..6a5ebc8a248 100644 --- a/intern/cycles/scene/shader_nodes.h +++ b/intern/cycles/scene/shader_nodes.h @@ -518,8 +518,8 @@ class PrincipledBsdfNode : public BsdfBaseNode { void compile(SVMCompiler &compiler, ShaderInput *metallic, ShaderInput *subsurface, + ShaderInput *subsurface_scale, ShaderInput *subsurface_radius, - ShaderInput *subsurface_ior, ShaderInput *subsurface_anisotropy, ShaderInput *specular, ShaderInput *roughness, @@ -537,7 +537,7 @@ class PrincipledBsdfNode : public BsdfBaseNode { NODE_SOCKET_API(float3, base_color) NODE_SOCKET_API(float3, subsurface_color) NODE_SOCKET_API(float3, subsurface_radius) - NODE_SOCKET_API(float, subsurface_ior) + NODE_SOCKET_API(float, subsurface_scale) NODE_SOCKET_API(float, subsurface_anisotropy) NODE_SOCKET_API(float, metallic) NODE_SOCKET_API(float, subsurface) diff --git a/source/blender/blenloader/intern/versioning_400.cc b/source/blender/blenloader/intern/versioning_400.cc index 50c8f87674b..0d154964250 100644 --- a/source/blender/blenloader/intern/versioning_400.cc +++ b/source/blender/blenloader/intern/versioning_400.cc @@ -374,6 +374,88 @@ static void version_principled_bsdf_sheen(bNodeTree *ntree) } } +/* Convert subsurface inputs on the Principled BSDF. */ +static void version_principled_bsdf_subsurface(bNodeTree *ntree) +{ + /* - Create Subsurface Scale input + * - Remove Subsurface IOR input + * - If a node's Subsurface input was connected or nonzero: + * - Make the Subsurface Color a mix of Base Color and its old value, + * using Subsurface as the mix factor + * - Move Subsurface link and default value to the new Subsurface Scale input + * - Set the Subsurface input to 1.0 + */ + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { + if (node->type != SH_NODE_BSDF_PRINCIPLED) { + continue; + } + if (nodeFindSocket(node, SOCK_IN, "Subsurface Scale")) { + /* Node is already updated. */ + continue; + } + + /* Delete IOR input */ + bNodeSocket *ior_in = nodeFindSocket(node, SOCK_IN, "Subsurface IOR"); + if (ior_in != nullptr) { + nodeRemoveSocket(ntree, node, ior_in); + } + + /* Add Scale input */ + bNodeSocket *scale_in = nodeAddStaticSocket( + ntree, node, SOCK_IN, SOCK_FLOAT, PROP_DISTANCE, "Subsurface Scale", "Subsurface Scale"); + + bNodeSocket *subsurf = nodeFindSocket(node, SOCK_IN, "Subsurface"); + float *subsurf_val = version_cycles_node_socket_float_value(subsurf); + *version_cycles_node_socket_float_value(scale_in) = *subsurf_val; + + if (subsurf->link == nullptr && *subsurf_val == 0.0f) { + /* Node doesn't use Subsurf, we're done here. */ + continue; + } + + /* Fix up Subsurface Color input */ + bNodeSocket *base_col = nodeFindSocket(node, SOCK_IN, "Base Color"); + bNodeSocket *subsurf_col = nodeFindSocket(node, SOCK_IN, "Subsurface Color"); + float *base_col_val = version_cycles_node_socket_rgba_value(base_col); + float *subsurf_col_val = version_cycles_node_socket_rgba_value(subsurf_col); + /* If any of the three inputs is dynamic, we need a Mix node. */ + if (subsurf->link || subsurf_col->link || base_col->link) { + bNode *mix = nodeAddStaticNode(nullptr, ntree, SH_NODE_MIX); + static_cast(mix->storage)->data_type = SOCK_RGBA; + mix->locx = node->locx - 170; + mix->locy = node->locy - 120; + + bNodeSocket *a_in = nodeFindSocket(mix, SOCK_IN, "A_Color"); + bNodeSocket *b_in = nodeFindSocket(mix, SOCK_IN, "B_Color"); + bNodeSocket *fac_in = nodeFindSocket(mix, SOCK_IN, "Factor_Float"); + bNodeSocket *result_out = nodeFindSocket(mix, SOCK_OUT, "Result_Color"); + + copy_v4_v4(version_cycles_node_socket_rgba_value(a_in), base_col_val); + copy_v4_v4(version_cycles_node_socket_rgba_value(b_in), subsurf_col_val); + *version_cycles_node_socket_float_value(fac_in) = *subsurf_val; + + if (base_col->link) { + nodeAddLink(ntree, base_col->link->fromnode, base_col->link->fromsock, mix, a_in); + } + if (subsurf_col->link) { + nodeAddLink(ntree, subsurf_col->link->fromnode, subsurf_col->link->fromsock, mix, b_in); + nodeRemLink(ntree, subsurf_col->link); + } + if (subsurf->link) { + nodeAddLink(ntree, subsurf->link->fromnode, subsurf->link->fromsock, mix, fac_in); + nodeAddLink(ntree, subsurf->link->fromnode, subsurf->link->fromsock, node, scale_in); + nodeRemLink(ntree, subsurf->link); + } + nodeAddLink(ntree, mix, result_out, node, subsurf_col); + } + /* Mix the fixed values. */ + interp_v4_v4v4(subsurf_col_val, base_col_val, subsurf_col_val, *subsurf_val); + + /* Set node to 100% subsurface, 0% diffuse. */ + *subsurf_val = 1.0f; + }; +} + void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain) { if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 1)) { @@ -642,5 +724,13 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain) scene->eevee.gi_irradiance_pool_size = 16; } } + + FOREACH_NODETREE_BEGIN (bmain, ntree, id) { + if (ntree->type == NTREE_SHADER) { + /* Convert subsurface inputs on the Principled BSDF. */ + version_principled_bsdf_subsurface(ntree); + } + } + FOREACH_NODETREE_END; } } diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl index 20f41fff18e..86d56add371 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl @@ -17,9 +17,9 @@ float principled_sheen(float NV, float rough) void node_bsdf_principled(vec4 base_color, float subsurface, + float subsurface_scale, vec3 subsurface_radius, vec4 subsurface_color, - float subsurface_ior, float subsurface_anisotropy, float metallic, float specular, @@ -87,7 +87,7 @@ void node_bsdf_principled(vec4 base_color, /* Sheen Coarse approximation: We reuse the diffuse radiance and just scale it. */ diffuse_data.color += sheen * sheen_tint.rgb * principled_sheen(NV, sheen_roughness); diffuse_data.N = N; - diffuse_data.sss_radius = subsurface_radius * subsurface; + diffuse_data.sss_radius = subsurface_radius * subsurface_scale; diffuse_data.sss_id = uint(do_sss); /* NOTE(@fclem): We need to blend the reflection color but also need to avoid applying the diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc index 607fc407936..5ef83a07707 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc @@ -23,22 +23,29 @@ static void node_declare(NodeDeclarationBuilder &b) .default_value(0.0f) .min(0.0f) .max(1.0f) - .subtype(PROP_FACTOR); + .subtype(PROP_FACTOR) + .description( + "Blend between diffuse surface and subsurface scattering. " + "Typically should be zero or one (either fully diffuse or subsurface)"); #define SOCK_SUBSURFACE_ID 1 + b.add_input("Subsurface Scale") + .default_value(0.05f) + .min(0.0f) + .max(10.0f) + .subtype(PROP_DISTANCE) + .description("Scale of the subsurface scattering (multiplied with Radius)"); +#define SOCK_SUBSURFACE_IOR_ID 2 b.add_input("Subsurface Radius") .default_value({1.0f, 0.2f, 0.1f}) .min(0.0f) .max(100.0f) - .compact(); -#define SOCK_SUBSURFACE_RADIUS_ID 2 - b.add_input("Subsurface Color").default_value({0.8f, 0.8f, 0.8f, 1.0f}); -#define SOCK_SUBSURFACE_COLOR_ID 3 - b.add_input("Subsurface IOR") - .default_value(1.4f) - .min(1.01f) - .max(3.8f) - .subtype(PROP_FACTOR); -#define SOCK_SUBSURFACE_IOR_ID 4 + .compact() + .description("Scattering radius to use for subsurface component (multiplied with Scale)"); +#define SOCK_SUBSURFACE_RADIUS_ID 3 + b.add_input("Subsurface Color") + .default_value({0.8f, 0.8f, 0.8f, 1.0f}) + .description("The overall color resulting from subsurface scattering effects"); +#define SOCK_SUBSURFACE_COLOR_ID 4 b.add_input("Subsurface Anisotropy") .default_value(0.0f) .min(0.0f) -- 2.30.2 From d4b3d39dd61657eec498b010245192cb455d2e65 Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Fri, 4 Aug 2023 23:49:41 +0200 Subject: [PATCH 2/7] Cycles: Implement refractive BSSRDF entry bounce The existing random walk subsurface scattering code worked like this: 1. Perform lambertian diffuse transmission bounce into volume 2. Trace path until we hit the surface again 3. Perform lambertian diffuse transmission bounce out of volume This has the advantage that unlike other approaches for handling the interface (e.g. not doing anything by treating it as transparent), the appearance of the BSSRDF converges to a classic diffuse BSDF as the radius goes to zero, so we can easily e.g. swap it out for a diffuse BSDF for secondary bounces. Also, it's very straightforward to implement, and doesn't need much storage (which is important for GPU performance). However, it also has downsides - for example, it's not particularly physically plausible, and it leads to excessive white edges. Therefore, this commit replaces the entry bounce with a GGX refraction bounce. The exit bounce remains lambertian, because a) This way the BSSRDF still converges to a lambertian BSDF for radius->0 b) This way we avoid having to store a bunch of extra data in the path state c) In materials that are well-described by subsurface scattering models, the path will generally encounter many internal bounces. Therefore, the incoming distribution at the exit interface is basically diffuse already anyways, so the impact is much lower than for the entry bounce. d) It looks good, and that's what really matters in the end ;) --- intern/cycles/kernel/closure/bssrdf.h | 24 ++++-- .../cycles/kernel/integrator/state_template.h | 2 +- intern/cycles/kernel/integrator/subsurface.h | 86 ++++++++++++++++--- .../kernel/integrator/subsurface_disk.h | 2 +- .../integrator/subsurface_random_walk.h | 16 +--- intern/cycles/kernel/osl/closures_setup.h | 15 +--- intern/cycles/kernel/svm/closure.h | 11 ++- 7 files changed, 107 insertions(+), 49 deletions(-) diff --git a/intern/cycles/kernel/closure/bssrdf.h b/intern/cycles/kernel/closure/bssrdf.h index 07a3132d05e..282331fad68 100644 --- a/intern/cycles/kernel/closure/bssrdf.h +++ b/intern/cycles/kernel/closure/bssrdf.h @@ -11,8 +11,11 @@ typedef struct Bssrdf { Spectrum radius; Spectrum albedo; - float roughness; float anisotropy; + + /* Parameters for refractive entry bounce. */ + float ior; + float alpha; } Bssrdf; static_assert(sizeof(ShaderClosure) >= sizeof(Bssrdf), "Bssrdf is too large!"); @@ -55,8 +58,7 @@ ccl_device float bssrdf_dipole_compute_alpha_prime(float rd, float fourthirdA) } ccl_device void bssrdf_setup_radius(ccl_private Bssrdf *bssrdf, - const ClosureType type, - const float eta) + const ClosureType type) { if (type == CLOSURE_BSSRDF_BURLEY_ID || type == CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID) { /* Scale mean free path length so it gives similar looking result to older @@ -65,8 +67,8 @@ ccl_device void bssrdf_setup_radius(ccl_private Bssrdf *bssrdf, } else { /* Adjust radius based on IOR and albedo. */ - const float inv_eta = 1.0f / eta; - const float F_dr = inv_eta * (-1.440f * inv_eta + 0.710f) + 0.668f + 0.0636f * eta; + const float inv_eta = 1.0f / bssrdf->ior; + const float F_dr = inv_eta * (-1.440f * inv_eta + 0.710f) + 0.668f + 0.0636f * bssrdf->ior; const float fourthirdA = (4.0f / 3.0f) * (1.0f + F_dr) / (1.0f - F_dr); /* From Jensen's `Fdr` ratio formula. */ @@ -282,15 +284,19 @@ ccl_device_inline ccl_private Bssrdf *bssrdf_alloc(ccl_private ShaderData *sd, S ccl_device int bssrdf_setup(ccl_private ShaderData *sd, ccl_private Bssrdf *bssrdf, int path_flag, - ClosureType type, - float ior) + ClosureType type) { /* Clamps protecting against bad/extreme and non physical values. */ bssrdf->anisotropy = clamp(bssrdf->anisotropy, 0.0f, 0.9f); - ior = clamp(ior, 1.01f, 3.8f); + bssrdf->ior = clamp(bssrdf->ior, 1.01f, 3.8f); int flag = 0; + if (type == CLOSURE_BSSRDF_RANDOM_WALK_ID) { + /* CLOSURE_BSSRDF_RANDOM_WALK_ID uses a fixed roughness. */ + bssrdf->alpha = 1.0f; + } + /* Verify if the radii are large enough to sample without precision issues. */ int bssrdf_channels = SPECTRUM_CHANNELS; Spectrum diffuse_weight = zero_spectrum(); @@ -324,7 +330,7 @@ ccl_device int bssrdf_setup(ccl_private ShaderData *sd, bssrdf->type = type; bssrdf->sample_weight = fabsf(average(bssrdf->weight)) * bssrdf_channels; - bssrdf_setup_radius(bssrdf, type, ior); + bssrdf_setup_radius(bssrdf, type); flag |= SD_BSSRDF; } diff --git a/intern/cycles/kernel/integrator/state_template.h b/intern/cycles/kernel/integrator/state_template.h index adc4a46e5a6..e8683ed9179 100644 --- a/intern/cycles/kernel/integrator/state_template.h +++ b/intern/cycles/kernel/integrator/state_template.h @@ -95,7 +95,7 @@ KERNEL_STRUCT_BEGIN(subsurface) KERNEL_STRUCT_MEMBER(subsurface, PackedSpectrum, albedo, KERNEL_FEATURE_SUBSURFACE) KERNEL_STRUCT_MEMBER(subsurface, PackedSpectrum, radius, KERNEL_FEATURE_SUBSURFACE) KERNEL_STRUCT_MEMBER(subsurface, float, anisotropy, KERNEL_FEATURE_SUBSURFACE) -KERNEL_STRUCT_MEMBER(subsurface, packed_float3, Ng, KERNEL_FEATURE_SUBSURFACE) +KERNEL_STRUCT_MEMBER(subsurface, packed_float3, N, KERNEL_FEATURE_SUBSURFACE) KERNEL_STRUCT_END(subsurface) /********************************** Volume Stack ******************************/ diff --git a/intern/cycles/kernel/integrator/subsurface.h b/intern/cycles/kernel/integrator/subsurface.h index caf10c93c97..5d2d981428a 100644 --- a/intern/cycles/kernel/integrator/subsurface.h +++ b/intern/cycles/kernel/integrator/subsurface.h @@ -23,6 +23,58 @@ CCL_NAMESPACE_BEGIN #ifdef __SUBSURFACE__ +ccl_device_inline float subsurface_entry_bounce(KernelGlobals kg, + ccl_private const Bssrdf *bssrdf, + ccl_private ShaderData *sd, + ccl_private RNGState *rng_state, + ccl_private float3 *wo) +{ + float2 rand_bsdf = path_state_rng_2D(kg, rng_state, PRNG_SUBSURFACE_BSDF); + + if (bssrdf->type == CLOSURE_BSSRDF_RANDOM_WALK_ID) { + /* CLOSURE_BSSRDF_RANDOM_WALK_ID has a 50% chance to sample a diffuse entry bounce. + * Also, for the refractive entry, it uses a fixed roughness of 1.0. */ + if (rand_bsdf.x < 0.5f) { + rand_bsdf.x *= 2.0f; + float pdf; + sample_cos_hemisphere(-bssrdf->N, rand_bsdf, wo, &pdf); + return 1.0f; + } + rand_bsdf.x = 2.0f * (rand_bsdf.x - 0.5f); + } + + const float cos_NI = dot(bssrdf->N, sd->wi); + if (cos_NI <= 0.0f) { + return 0.0f; + } + + float3 X, Y, Z = bssrdf->N; + make_orthonormals(Z, &X, &Y); + + const float alpha = bssrdf->alpha; + const float alpha2 = sqr(alpha); + const float neta = 1.0f / bssrdf->ior; + + /* Sample microfacet normal by transforming to/from local coordinates. */ + const float3 local_I = make_float3(dot(X, sd->wi), dot(Y, sd->wi), cos_NI); + const float3 local_H = microfacet_ggx_sample_vndf(local_I, alpha, alpha, rand_bsdf); + const float3 H = X * local_H.x + Y * local_H.y + Z * local_H.z; + + const float cos_HI = dot(H, sd->wi); + const float arg = 1.0f - (sqr(neta) * (1.0f - sqr(cos_HI))); + /* We clamp subsurface IOR to be above 1, so there should never be TIR. */ + kernel_assert(arg >= 0.0f); + + const float dnp = max(sqrtf(arg), 1e-7f); + const float nK = (neta * cos_HI) - dnp; + *wo = -(neta * sd->wi) + (nK * H); + const float cos_NO = dot(Z, *wo); + + const float lambdaI = bsdf_lambda(alpha2, cos_NI); + const float lambdaO = bsdf_lambda(alpha2, cos_NO); + return (1.0f + lambdaI) / (1.0f + lambdaI + lambdaO); +} + ccl_device int subsurface_bounce(KernelGlobals kg, IntegratorState state, ccl_private ShaderData *sd, @@ -37,22 +89,39 @@ ccl_device int subsurface_bounce(KernelGlobals kg, /* Setup ray into surface. */ INTEGRATOR_STATE_WRITE(state, ray, P) = sd->P; - INTEGRATOR_STATE_WRITE(state, ray, D) = bssrdf->N; INTEGRATOR_STATE_WRITE(state, ray, tmin) = 0.0f; INTEGRATOR_STATE_WRITE(state, ray, tmax) = FLT_MAX; INTEGRATOR_STATE_WRITE(state, ray, dP) = differential_make_compact(sd->dP); INTEGRATOR_STATE_WRITE(state, ray, dD) = differential_zero_compact(); - /* Pass along object info, reusing isect to save memory. */ - INTEGRATOR_STATE_WRITE(state, subsurface, Ng) = sd->Ng; - - uint32_t path_flag = (INTEGRATOR_STATE(state, path, flag) & ~PATH_RAY_CAMERA) | - ((sc->type == CLOSURE_BSSRDF_BURLEY_ID) ? PATH_RAY_SUBSURFACE_DISK : - PATH_RAY_SUBSURFACE_RANDOM_WALK); + /* Advance random number offset for bounce. */ + INTEGRATOR_STATE_WRITE(state, path, rng_offset) += PRNG_BOUNCE_NUM; /* Compute weight, optionally including Fresnel from entry point. */ Spectrum weight = surface_shader_bssrdf_sample_weight(sd, sc); + uint32_t path_flag = (INTEGRATOR_STATE(state, path, flag) & ~PATH_RAY_CAMERA); + if (sc->type == CLOSURE_BSSRDF_BURLEY_ID) + { + path_flag |= PATH_RAY_SUBSURFACE_DISK; + INTEGRATOR_STATE_WRITE(state, subsurface, N) = sd->Ng; + } + else { + path_flag |= PATH_RAY_SUBSURFACE_RANDOM_WALK; + + /* Sample entry bounce into the material. */ + RNGState rng_state; + path_state_rng_load(state, &rng_state); + float3 wo; + weight *= subsurface_entry_bounce(kg, bssrdf, sd, &rng_state, &wo); + if (is_zero(weight) || dot(sd->Ng, wo) >= 0.0f) { + /* Sampling failed, give up on this bounce. */ + return LABEL_NONE; + } + INTEGRATOR_STATE_WRITE(state, ray, D) = wo; + INTEGRATOR_STATE_WRITE(state, subsurface, N) = sd->N; + } + if (sd->flag & SD_BACKFACING) { path_flag |= PATH_RAY_SUBSURFACE_BACKFACING; } @@ -60,9 +129,6 @@ ccl_device int subsurface_bounce(KernelGlobals kg, INTEGRATOR_STATE_WRITE(state, path, throughput) *= weight; INTEGRATOR_STATE_WRITE(state, path, flag) = path_flag; - /* Advance random number offset for bounce. */ - INTEGRATOR_STATE_WRITE(state, path, rng_offset) += PRNG_BOUNCE_NUM; - if (kernel_data.kernel_features & KERNEL_FEATURE_LIGHT_PASSES) { if (INTEGRATOR_STATE(state, path, bounce) == 0) { INTEGRATOR_STATE_WRITE(state, path, pass_diffuse_weight) = one_spectrum(); diff --git a/intern/cycles/kernel/integrator/subsurface_disk.h b/intern/cycles/kernel/integrator/subsurface_disk.h index 985cc1b5ffe..6902df850cf 100644 --- a/intern/cycles/kernel/integrator/subsurface_disk.h +++ b/intern/cycles/kernel/integrator/subsurface_disk.h @@ -34,7 +34,7 @@ ccl_device_inline bool subsurface_disk(KernelGlobals kg, const float3 P = INTEGRATOR_STATE(state, ray, P); const float ray_dP = INTEGRATOR_STATE(state, ray, dP); const float time = INTEGRATOR_STATE(state, ray, time); - const float3 Ng = INTEGRATOR_STATE(state, subsurface, Ng); + const float3 Ng = INTEGRATOR_STATE(state, subsurface, N); const int object = INTEGRATOR_STATE(state, isect, object); const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag); diff --git a/intern/cycles/kernel/integrator/subsurface_random_walk.h b/intern/cycles/kernel/integrator/subsurface_random_walk.h index 2ddf62d5b2f..3a19cfb8713 100644 --- a/intern/cycles/kernel/integrator/subsurface_random_walk.h +++ b/intern/cycles/kernel/integrator/subsurface_random_walk.h @@ -168,24 +168,14 @@ ccl_device_inline bool subsurface_random_walk(KernelGlobals kg, ccl_private Ray &ray, ccl_private LocalIntersection &ss_isect) { - const float2 rand_bsdf = path_state_rng_2D(kg, &rng_state, PRNG_SUBSURFACE_BSDF); - const float3 P = INTEGRATOR_STATE(state, ray, P); - const float3 N = INTEGRATOR_STATE(state, ray, D); + const float3 D = INTEGRATOR_STATE(state, ray, D); const float ray_dP = INTEGRATOR_STATE(state, ray, dP); const float time = INTEGRATOR_STATE(state, ray, time); - const float3 Ng = INTEGRATOR_STATE(state, subsurface, Ng); + const float3 N = INTEGRATOR_STATE(state, subsurface, N); const int object = INTEGRATOR_STATE(state, isect, object); const int prim = INTEGRATOR_STATE(state, isect, prim); - /* Sample diffuse surface scatter into the object. */ - float3 D; - float pdf; - sample_cos_hemisphere(-N, rand_bsdf, &D, &pdf); - if (dot(-Ng, D) <= 0.0f) { - return false; - } - /* Setup ray. */ ray.P = P; ray.D = D; @@ -439,7 +429,7 @@ ccl_device_inline bool subsurface_random_walk(KernelGlobals kg, guiding_record_bssrdf_bounce( kg, state, - pdf, + 1.0f, N, D, safe_divide_color(throughput, INTEGRATOR_STATE(state, path, throughput)), diff --git a/intern/cycles/kernel/osl/closures_setup.h b/intern/cycles/kernel/osl/closures_setup.h index 38b35050711..63bccde8bd0 100644 --- a/intern/cycles/kernel/osl/closures_setup.h +++ b/intern/cycles/kernel/osl/closures_setup.h @@ -744,23 +744,16 @@ ccl_device void osl_closure_bssrdf_setup(KernelGlobals kg, return; } - /* disable in case of diffuse ancestor, can't see it well then and - * adds considerably noise due to probabilities of continuing path - * getting lower and lower */ - if (path_flag & PATH_RAY_DIFFUSE_ANCESTOR) { - bssrdf->radius = zero_spectrum(); - } - else { - bssrdf->radius = closure->radius; - } + bssrdf->radius = closure->radius; /* create one closure per color channel */ bssrdf->albedo = closure->albedo; bssrdf->N = closure->N; - bssrdf->roughness = closure->roughness; + bssrdf->alpha = sqr(closure->roughness); + bssrdf->ior = closure->ior; bssrdf->anisotropy = closure->anisotropy; - sd->flag |= bssrdf_setup(sd, bssrdf, path_flag, type, closure->ior); + sd->flag |= bssrdf_setup(sd, bssrdf, path_flag, type); } /* Hair */ diff --git a/intern/cycles/kernel/svm/closure.h b/intern/cycles/kernel/svm/closure.h index 5dd07142893..387f400fcbe 100644 --- a/intern/cycles/kernel/svm/closure.h +++ b/intern/cycles/kernel/svm/closure.h @@ -308,11 +308,12 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, bssrdf->radius = rgb_to_spectrum(subsurface_radius * subsurface_scale); bssrdf->albedo = rgb_to_spectrum(subsurface_color); bssrdf->N = N; - bssrdf->roughness = sqr(roughness); + bssrdf->alpha = sqr(roughness); + bssrdf->ior = eta; bssrdf->anisotropy = subsurface_anisotropy; /* setup bsdf */ - sd->flag |= bssrdf_setup(sd, bssrdf, path_flag, subsurface_method, eta); + sd->flag |= bssrdf_setup(sd, bssrdf, path_flag, subsurface_method); } #else subsurface = 0.0f; @@ -712,10 +713,12 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, bssrdf->radius = rgb_to_spectrum(stack_load_float3(stack, data_node.z) * param1); bssrdf->albedo = closure_weight; bssrdf->N = N; - bssrdf->roughness = FLT_MAX; + bssrdf->ior = param2; + /* TODO */ + bssrdf->alpha = 1.0f; bssrdf->anisotropy = stack_load_float(stack, data_node.w); - sd->flag |= bssrdf_setup(sd, bssrdf, path_flag, (ClosureType)type, param2); + sd->flag |= bssrdf_setup(sd, bssrdf, path_flag, (ClosureType)type); } break; -- 2.30.2 From e50bae796d76be238c6c8badb6e8749af2b58c86 Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Fri, 11 Aug 2023 18:36:45 -0700 Subject: [PATCH 3/7] Update logic for falling back to diffuse --- intern/cycles/kernel/closure/bssrdf.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/intern/cycles/kernel/closure/bssrdf.h b/intern/cycles/kernel/closure/bssrdf.h index 282331fad68..dff5f0ab803 100644 --- a/intern/cycles/kernel/closure/bssrdf.h +++ b/intern/cycles/kernel/closure/bssrdf.h @@ -301,12 +301,16 @@ ccl_device int bssrdf_setup(ccl_private ShaderData *sd, int bssrdf_channels = SPECTRUM_CHANNELS; Spectrum diffuse_weight = zero_spectrum(); - /* Fall back to diffuse in case of diffuse ancestor, can't see it well then and adds considerable - * noise due to probabilities of continuing the path getting lower and lower. */ - const bool is_diffuse_ancestor = (path_flag & PATH_RAY_DIFFUSE_ANCESTOR); + /* Fall back to diffuse if the radius is smaller than a quarter pixel. */ + float min_radius = max(0.25f * sd->dP, BSSRDF_MIN_RADIUS); + if (path_flag & PATH_RAY_DIFFUSE_ANCESTOR) { + /* Always fall back to diffuse after a diffuse ancestor. Can't see it well then and adds + * considerable noise due to probabilities of continuing the path getting lower and lower. */ + min_radius = FLT_MAX; + } FOREACH_SPECTRUM_CHANNEL (i) { - if (is_diffuse_ancestor || GET_SPECTRUM_CHANNEL(bssrdf->radius, i) < BSSRDF_MIN_RADIUS) { + if (GET_SPECTRUM_CHANNEL(bssrdf->radius, i) < min_radius) { GET_SPECTRUM_CHANNEL(diffuse_weight, i) = GET_SPECTRUM_CHANNEL(bssrdf->weight, i); GET_SPECTRUM_CHANNEL(bssrdf->weight, i) = 0.0f; GET_SPECTRUM_CHANNEL(bssrdf->radius, i) = 0.0f; -- 2.30.2 From 1794806b5e7bcb42d45bed7ff281a3fff3a50da7 Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Fri, 11 Aug 2023 19:38:12 -0700 Subject: [PATCH 4/7] Avoid GGX darkening --- intern/cycles/kernel/closure/bssrdf.h | 3 +- intern/cycles/kernel/integrator/subsurface.h | 35 ++++++++++---------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/intern/cycles/kernel/closure/bssrdf.h b/intern/cycles/kernel/closure/bssrdf.h index dff5f0ab803..fe17aeed32c 100644 --- a/intern/cycles/kernel/closure/bssrdf.h +++ b/intern/cycles/kernel/closure/bssrdf.h @@ -57,8 +57,7 @@ ccl_device float bssrdf_dipole_compute_alpha_prime(float rd, float fourthirdA) return xmid; } -ccl_device void bssrdf_setup_radius(ccl_private Bssrdf *bssrdf, - const ClosureType type) +ccl_device void bssrdf_setup_radius(ccl_private Bssrdf *bssrdf, const ClosureType type) { if (type == CLOSURE_BSSRDF_BURLEY_ID || type == CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID) { /* Scale mean free path length so it gives similar looking result to older diff --git a/intern/cycles/kernel/integrator/subsurface.h b/intern/cycles/kernel/integrator/subsurface.h index 5d2d981428a..9eb7d25e0d8 100644 --- a/intern/cycles/kernel/integrator/subsurface.h +++ b/intern/cycles/kernel/integrator/subsurface.h @@ -23,11 +23,11 @@ CCL_NAMESPACE_BEGIN #ifdef __SUBSURFACE__ -ccl_device_inline float subsurface_entry_bounce(KernelGlobals kg, - ccl_private const Bssrdf *bssrdf, - ccl_private ShaderData *sd, - ccl_private RNGState *rng_state, - ccl_private float3 *wo) +ccl_device_inline bool subsurface_entry_bounce(KernelGlobals kg, + ccl_private const Bssrdf *bssrdf, + ccl_private ShaderData *sd, + ccl_private RNGState *rng_state, + ccl_private float3 *wo) { float2 rand_bsdf = path_state_rng_2D(kg, rng_state, PRNG_SUBSURFACE_BSDF); @@ -38,14 +38,14 @@ ccl_device_inline float subsurface_entry_bounce(KernelGlobals kg, rand_bsdf.x *= 2.0f; float pdf; sample_cos_hemisphere(-bssrdf->N, rand_bsdf, wo, &pdf); - return 1.0f; + return true; } rand_bsdf.x = 2.0f * (rand_bsdf.x - 0.5f); } const float cos_NI = dot(bssrdf->N, sd->wi); if (cos_NI <= 0.0f) { - return 0.0f; + return false; } float3 X, Y, Z = bssrdf->N; @@ -68,11 +68,14 @@ ccl_device_inline float subsurface_entry_bounce(KernelGlobals kg, const float dnp = max(sqrtf(arg), 1e-7f); const float nK = (neta * cos_HI) - dnp; *wo = -(neta * sd->wi) + (nK * H); - const float cos_NO = dot(Z, *wo); - - const float lambdaI = bsdf_lambda(alpha2, cos_NI); - const float lambdaO = bsdf_lambda(alpha2, cos_NO); - return (1.0f + lambdaI) / (1.0f + lambdaI + lambdaO); + return true; + /* Note: For a proper refractive GGX interface, we should be computing lambdaI and lambdaO + * and multiplying the throughput by BSDF/pdf, which for VNDF sampling works out to + * (1 + lambdaI) / (1 + lambdaI + lambdaO). + * However, this causes darkening due to the single-scattering approximation, which we'd + * then have to correct with a lookup table. + * Since we only really care about the directional distribution here, it's much easier to + * just skip all that instead. */ } ccl_device int subsurface_bounce(KernelGlobals kg, @@ -99,10 +102,10 @@ ccl_device int subsurface_bounce(KernelGlobals kg, /* Compute weight, optionally including Fresnel from entry point. */ Spectrum weight = surface_shader_bssrdf_sample_weight(sd, sc); + INTEGRATOR_STATE_WRITE(state, path, throughput) *= weight; uint32_t path_flag = (INTEGRATOR_STATE(state, path, flag) & ~PATH_RAY_CAMERA); - if (sc->type == CLOSURE_BSSRDF_BURLEY_ID) - { + if (sc->type == CLOSURE_BSSRDF_BURLEY_ID) { path_flag |= PATH_RAY_SUBSURFACE_DISK; INTEGRATOR_STATE_WRITE(state, subsurface, N) = sd->Ng; } @@ -113,8 +116,7 @@ ccl_device int subsurface_bounce(KernelGlobals kg, RNGState rng_state; path_state_rng_load(state, &rng_state); float3 wo; - weight *= subsurface_entry_bounce(kg, bssrdf, sd, &rng_state, &wo); - if (is_zero(weight) || dot(sd->Ng, wo) >= 0.0f) { + if (!subsurface_entry_bounce(kg, bssrdf, sd, &rng_state, &wo) || dot(sd->Ng, wo) >= 0.0f) { /* Sampling failed, give up on this bounce. */ return LABEL_NONE; } @@ -126,7 +128,6 @@ ccl_device int subsurface_bounce(KernelGlobals kg, path_flag |= PATH_RAY_SUBSURFACE_BACKFACING; } - INTEGRATOR_STATE_WRITE(state, path, throughput) *= weight; INTEGRATOR_STATE_WRITE(state, path, flag) = path_flag; if (kernel_data.kernel_features & KERNEL_FEATURE_LIGHT_PASSES) { -- 2.30.2 From c9f2dd126b8cc16b4ae93eed897ffe0ecd3142aa Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Fri, 11 Aug 2023 21:05:01 -0700 Subject: [PATCH 5/7] Bring back Subsurface IOR, remove Subsurface Color --- .../osl/shaders/node_principled_bsdf.osl | 9 +- intern/cycles/kernel/svm/closure.h | 20 ++-- intern/cycles/scene/shader_nodes.cpp | 99 +++++-------------- intern/cycles/scene/shader_nodes.h | 20 +--- .../blenloader/intern/versioning_400.cc | 18 ++-- .../gpu_shader_material_principled.glsl | 4 +- .../nodes/node_shader_bsdf_principled.cc | 22 +++-- 7 files changed, 61 insertions(+), 131 deletions(-) diff --git a/intern/cycles/kernel/osl/shaders/node_principled_bsdf.osl b/intern/cycles/kernel/osl/shaders/node_principled_bsdf.osl index f8549b8f9b7..3659b0de38a 100644 --- a/intern/cycles/kernel/osl/shaders/node_principled_bsdf.osl +++ b/intern/cycles/kernel/osl/shaders/node_principled_bsdf.osl @@ -11,7 +11,7 @@ shader node_principled_bsdf(string distribution = "multi_ggx", float Subsurface = 0.0, float SubsurfaceScale = 0.1, vector SubsurfaceRadius = vector(1.0, 1.0, 1.0), - color SubsurfaceColor = color(0.7, 0.1, 0.1), + float SubsurfaceIOR = 1.4, float SubsurfaceAnisotropy = 0.0, float Metallic = 0.0, float Specular = 0.5, @@ -48,17 +48,18 @@ shader node_principled_bsdf(string distribution = "multi_ggx", BSDF = BaseColor * diffuse(Normal); if (Subsurface > 1e-5) { vector radius = SubsurfaceScale * SubsurfaceRadius; + float subsurface_ior = (subsurface_method == "random_walk") ? SubsurfaceIOR : IOR; closure color SubsurfBSDF = bssrdf(subsurface_method, Normal, SubsurfaceScale * SubsurfaceRadius, - SubsurfaceColor, + BaseColor, "roughness", Roughness, "ior", - IOR, + subsurface_ior, "anisotropy", SubsurfaceAnisotropy); - BSDF = mix(BSDF, SubsurfaceColor * SubsurfBSDF, Subsurface); + BSDF = mix(BSDF, BaseColor * SubsurfBSDF, Subsurface); } color f0 = color(F0_from_ior(IOR)); diff --git a/intern/cycles/kernel/svm/closure.h b/intern/cycles/kernel/svm/closure.h index 387f400fcbe..ced1d80e8ae 100644 --- a/intern/cycles/kernel/svm/closure.h +++ b/intern/cycles/kernel/svm/closure.h @@ -22,7 +22,6 @@ ccl_device_inline int svm_node_closure_bsdf_skip(KernelGlobals kg, int offset, u read_node(kg, &offset); read_node(kg, &offset); read_node(kg, &offset); - read_node(kg, &offset); } return offset; @@ -70,7 +69,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, case CLOSURE_BSDF_PRINCIPLED_ID: { uint specular_offset, roughness_offset, specular_tint_offset, anisotropic_offset, sheen_offset, sheen_tint_offset, clearcoat_offset, clearcoat_roughness_offset, - eta_offset, transmission_offset, anisotropic_rotation_offset, pad1; + eta_offset, transmission_offset, anisotropic_rotation_offset, subsurface_ior_offset; uint4 data_node2 = read_node(kg, &offset); float3 T = stack_load_float3(stack, data_node.y); @@ -85,7 +84,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, &clearcoat_offset, &clearcoat_roughness_offset); svm_unpack_node_uchar4( - data_node2.x, &eta_offset, &transmission_offset, &anisotropic_rotation_offset, &pad1); + data_node2.x, &eta_offset, &transmission_offset, &anisotropic_rotation_offset, &subsurface_ior_offset); // get Disney principled parameters float metallic = saturatef(param1); @@ -132,14 +131,6 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, stack_load_float(stack, data_cn_ssr.w) : 0.0f; - // get the subsurface color - uint4 data_subsurface_color = read_node(kg, &offset); - float3 subsurface_color = stack_valid(data_subsurface_color.x) ? - stack_load_float3(stack, data_subsurface_color.x) : - make_float3(__uint_as_float(data_subsurface_color.y), - __uint_as_float(data_subsurface_color.z), - __uint_as_float(data_subsurface_color.w)); - Spectrum weight = closure_weight * mix_weight; float alpha_x = sqr(roughness), alpha_y = sqr(roughness); @@ -303,14 +294,17 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, /* Diffuse/Subsurface component */ #ifdef __SUBSURFACE__ ccl_private Bssrdf *bssrdf = bssrdf_alloc( - sd, rgb_to_spectrum(subsurface_color) * subsurface * weight); + sd, rgb_to_spectrum(base_color) * subsurface * weight); if (bssrdf) { bssrdf->radius = rgb_to_spectrum(subsurface_radius * subsurface_scale); - bssrdf->albedo = rgb_to_spectrum(subsurface_color); + bssrdf->albedo = rgb_to_spectrum(base_color); bssrdf->N = N; bssrdf->alpha = sqr(roughness); bssrdf->ior = eta; bssrdf->anisotropy = subsurface_anisotropy; + if (subsurface_method == CLOSURE_BSSRDF_RANDOM_WALK_ID) { + bssrdf->ior = stack_load_float(stack, subsurface_ior_offset); + } /* setup bsdf */ sd->flag |= bssrdf_setup(sd, bssrdf, path_flag, subsurface_method); diff --git a/intern/cycles/scene/shader_nodes.cpp b/intern/cycles/scene/shader_nodes.cpp index 49a813ed38c..564f9b03fea 100644 --- a/intern/cycles/scene/shader_nodes.cpp +++ b/intern/cycles/scene/shader_nodes.cpp @@ -2649,12 +2649,12 @@ NODE_DEFINE(PrincipledBsdfNode) subsurface_method_enum, CLOSURE_BSSRDF_RANDOM_WALK_ID); - 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_COLOR(base_color, "Base Color", make_float3(0.8f, 0.8f, 0.8f)) SOCKET_IN_FLOAT(metallic, "Metallic", 0.0f); SOCKET_IN_FLOAT(subsurface, "Subsurface", 0.0f); SOCKET_IN_FLOAT(subsurface_scale, "Subsurface Scale", 0.1f); SOCKET_IN_VECTOR(subsurface_radius, "Subsurface Radius", make_float3(0.1f, 0.1f, 0.1f)); + SOCKET_IN_FLOAT(subsurface_ior, "Subsurface IOR", 1.4f); SOCKET_IN_FLOAT(subsurface_anisotropy, "Subsurface Anisotropy", 0.0f); SOCKET_IN_FLOAT(specular, "Specular", 0.0f); SOCKET_IN_FLOAT(roughness, "Roughness", 0.5f); @@ -2761,53 +2761,36 @@ void PrincipledBsdfNode::attributes(Shader *shader, AttributeRequestSet *attribu ShaderNode::attributes(shader, attributes); } -void PrincipledBsdfNode::compile(SVMCompiler &compiler, - ShaderInput *p_metallic, - ShaderInput *p_subsurface, - ShaderInput *p_subsurface_scale, - ShaderInput *p_subsurface_radius, - ShaderInput *p_subsurface_anisotropy, - ShaderInput *p_specular, - ShaderInput *p_roughness, - ShaderInput *p_specular_tint, - ShaderInput *p_anisotropic, - ShaderInput *p_sheen, - ShaderInput *p_sheen_roughness, - ShaderInput *p_sheen_tint, - ShaderInput *p_clearcoat, - ShaderInput *p_clearcoat_roughness, - ShaderInput *p_ior, - ShaderInput *p_transmission, - ShaderInput *p_anisotropic_rotation) +void PrincipledBsdfNode::compile(SVMCompiler &compiler) { ShaderInput *base_color_in = input("Base Color"); - ShaderInput *subsurface_color_in = input("Subsurface Color"); - ShaderInput *normal_in = input("Normal"); - ShaderInput *clearcoat_normal_in = input("Clearcoat Normal"); - ShaderInput *tangent_in = input("Tangent"); + + ShaderInput *p_metallic = input("Metallic"); + ShaderInput *p_subsurface = input("Subsurface"); float3 weight = one_float3(); compiler.add_node(NODE_CLOSURE_SET_WEIGHT, weight); - int normal_offset = compiler.stack_assign_if_linked(normal_in); - int clearcoat_normal_offset = compiler.stack_assign_if_linked(clearcoat_normal_in); - int tangent_offset = compiler.stack_assign_if_linked(tangent_in); - int specular_offset = compiler.stack_assign(p_specular); - 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 sheen_offset = compiler.stack_assign(p_sheen); - int sheen_roughness_offset = compiler.stack_assign(p_sheen_roughness); - int sheen_tint_offset = compiler.stack_assign(p_sheen_tint); - int clearcoat_offset = compiler.stack_assign(p_clearcoat); - int clearcoat_roughness_offset = compiler.stack_assign(p_clearcoat_roughness); - int ior_offset = compiler.stack_assign(p_ior); - int transmission_offset = compiler.stack_assign(p_transmission); - int anisotropic_rotation_offset = compiler.stack_assign(p_anisotropic_rotation); - int subsurface_radius_offset = compiler.stack_assign(p_subsurface_radius); - int subsurface_scale_offset = compiler.stack_assign(p_subsurface_scale); - int subsurface_anisotropy_offset = compiler.stack_assign(p_subsurface_anisotropy); + int normal_offset = compiler.stack_assign_if_linked(input("Normal")); + int clearcoat_normal_offset = compiler.stack_assign_if_linked(input("Clearcoat Normal")); + int tangent_offset = compiler.stack_assign_if_linked(input("Tangent")); + int specular_offset = compiler.stack_assign(input("Specular")); + int roughness_offset = compiler.stack_assign(input("Roughness")); + int specular_tint_offset = compiler.stack_assign(input("Specular Tint")); + int anisotropic_offset = compiler.stack_assign(input("Anisotropic")); + int sheen_offset = compiler.stack_assign(input("Sheen")); + int sheen_roughness_offset = compiler.stack_assign(input("Sheen Roughness")); + int sheen_tint_offset = compiler.stack_assign(input("Sheen Tint")); + int clearcoat_offset = compiler.stack_assign(input("Clearcoat")); + int clearcoat_roughness_offset = compiler.stack_assign(input("Clearcoat Roughness")); + int ior_offset = compiler.stack_assign(input("IOR")); + int transmission_offset = compiler.stack_assign(input("Transmission")); + int anisotropic_rotation_offset = compiler.stack_assign(input("Anisotropic Rotation")); + int subsurface_radius_offset = compiler.stack_assign(input("Subsurface Radius")); + int subsurface_scale_offset = compiler.stack_assign(input("Subsurface Scale")); + int subsurface_ior_offset = compiler.stack_assign(input("Subsurface IOR")); + int subsurface_anisotropy_offset = compiler.stack_assign(input("Subsurface Anisotropy")); compiler.add_node(NODE_CLOSURE_BSDF, compiler.encode_uchar4(closure, @@ -2827,7 +2810,7 @@ void PrincipledBsdfNode::compile(SVMCompiler &compiler, compiler.add_node( compiler.encode_uchar4( - ior_offset, transmission_offset, anisotropic_rotation_offset, SVM_STACK_INVALID), + ior_offset, transmission_offset, anisotropic_rotation_offset, subsurface_ior_offset), distribution, subsurface_method, sheen_roughness_offset); @@ -2844,36 +2827,6 @@ void PrincipledBsdfNode::compile(SVMCompiler &compiler, subsurface_radius_offset, subsurface_scale_offset, subsurface_anisotropy_offset); - - float3 ss_default = get_float3(subsurface_color_in->socket_type); - - compiler.add_node(((subsurface_color_in->link) ? compiler.stack_assign(subsurface_color_in) : - SVM_STACK_INVALID), - __float_as_int(ss_default.x), - __float_as_int(ss_default.y), - __float_as_int(ss_default.z)); -} - -void PrincipledBsdfNode::compile(SVMCompiler &compiler) -{ - compile(compiler, - input("Metallic"), - input("Subsurface"), - input("Subsurface Scale"), - input("Subsurface Radius"), - input("Subsurface Anisotropy"), - input("Specular"), - input("Roughness"), - input("Specular Tint"), - input("Anisotropic"), - input("Sheen"), - input("Sheen Roughness"), - input("Sheen Tint"), - input("Clearcoat"), - input("Clearcoat Roughness"), - input("IOR"), - input("Transmission"), - input("Anisotropic Rotation")); } void PrincipledBsdfNode::compile(OSLCompiler &compiler) diff --git a/intern/cycles/scene/shader_nodes.h b/intern/cycles/scene/shader_nodes.h index 6a5ebc8a248..436d2a746c9 100644 --- a/intern/cycles/scene/shader_nodes.h +++ b/intern/cycles/scene/shader_nodes.h @@ -515,29 +515,11 @@ class PrincipledBsdfNode : public BsdfBaseNode { void expand(ShaderGraph *graph); bool has_surface_bssrdf(); bool has_bssrdf_bump(); - void compile(SVMCompiler &compiler, - ShaderInput *metallic, - ShaderInput *subsurface, - ShaderInput *subsurface_scale, - ShaderInput *subsurface_radius, - ShaderInput *subsurface_anisotropy, - ShaderInput *specular, - ShaderInput *roughness, - ShaderInput *specular_tint, - ShaderInput *anisotropic, - ShaderInput *sheen, - ShaderInput *sheen_roughness, - ShaderInput *sheen_tint, - ShaderInput *clearcoat, - ShaderInput *clearcoat_roughness, - ShaderInput *ior, - ShaderInput *transmission, - ShaderInput *anisotropic_rotation); NODE_SOCKET_API(float3, base_color) - NODE_SOCKET_API(float3, subsurface_color) NODE_SOCKET_API(float3, subsurface_radius) NODE_SOCKET_API(float, subsurface_scale) + NODE_SOCKET_API(float, subsurface_ior) NODE_SOCKET_API(float, subsurface_anisotropy) NODE_SOCKET_API(float, metallic) NODE_SOCKET_API(float, subsurface) diff --git a/source/blender/blenloader/intern/versioning_400.cc b/source/blender/blenloader/intern/versioning_400.cc index 0d154964250..71eb5bb222d 100644 --- a/source/blender/blenloader/intern/versioning_400.cc +++ b/source/blender/blenloader/intern/versioning_400.cc @@ -378,12 +378,12 @@ static void version_principled_bsdf_sheen(bNodeTree *ntree) static void version_principled_bsdf_subsurface(bNodeTree *ntree) { /* - Create Subsurface Scale input - * - Remove Subsurface IOR input * - If a node's Subsurface input was connected or nonzero: - * - Make the Subsurface Color a mix of Base Color and its old value, + * - Make the Base Color a mix of old Base Color and Subsurface Color, * using Subsurface as the mix factor * - Move Subsurface link and default value to the new Subsurface Scale input * - Set the Subsurface input to 1.0 + * - Remove Subsurface Color input */ LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { if (node->type != SH_NODE_BSDF_PRINCIPLED) { @@ -394,12 +394,6 @@ static void version_principled_bsdf_subsurface(bNodeTree *ntree) continue; } - /* Delete IOR input */ - bNodeSocket *ior_in = nodeFindSocket(node, SOCK_IN, "Subsurface IOR"); - if (ior_in != nullptr) { - nodeRemoveSocket(ntree, node, ior_in); - } - /* Add Scale input */ bNodeSocket *scale_in = nodeAddStaticSocket( ntree, node, SOCK_IN, SOCK_FLOAT, PROP_DISTANCE, "Subsurface Scale", "Subsurface Scale"); @@ -436,6 +430,7 @@ static void version_principled_bsdf_subsurface(bNodeTree *ntree) if (base_col->link) { nodeAddLink(ntree, base_col->link->fromnode, base_col->link->fromsock, mix, a_in); + nodeRemLink(ntree, base_col->link); } if (subsurf_col->link) { nodeAddLink(ntree, subsurf_col->link->fromnode, subsurf_col->link->fromsock, mix, b_in); @@ -446,13 +441,16 @@ static void version_principled_bsdf_subsurface(bNodeTree *ntree) nodeAddLink(ntree, subsurf->link->fromnode, subsurf->link->fromsock, node, scale_in); nodeRemLink(ntree, subsurf->link); } - nodeAddLink(ntree, mix, result_out, node, subsurf_col); + nodeAddLink(ntree, mix, result_out, node, base_col); } /* Mix the fixed values. */ - interp_v4_v4v4(subsurf_col_val, base_col_val, subsurf_col_val, *subsurf_val); + interp_v4_v4v4(base_col_val, base_col_val, subsurf_col_val, *subsurf_val); /* Set node to 100% subsurface, 0% diffuse. */ *subsurf_val = 1.0f; + + /* Delete Subsurface Color input */ + nodeRemoveSocket(ntree, node, subsurf_col); }; } diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl index 86d56add371..2e129805a33 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl @@ -19,7 +19,7 @@ void node_bsdf_principled(vec4 base_color, float subsurface, float subsurface_scale, vec3 subsurface_radius, - vec4 subsurface_color, + float subsurface_ior, float subsurface_anisotropy, float metallic, float specular, @@ -83,7 +83,7 @@ void node_bsdf_principled(vec4 base_color, /* Diffuse. */ ClosureDiffuse diffuse_data; diffuse_data.weight = diffuse_weight * weight; - diffuse_data.color = mix(base_color.rgb, subsurface_color.rgb, subsurface); + diffuse_data.color = base_color.rgb; /* Sheen Coarse approximation: We reuse the diffuse radiance and just scale it. */ diffuse_data.color += sheen * sheen_tint.rgb * principled_sheen(NV, sheen_roughness); diffuse_data.N = N; diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc index 5ef83a07707..efa8f9c0aa9 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc @@ -34,7 +34,7 @@ static void node_declare(NodeDeclarationBuilder &b) .max(10.0f) .subtype(PROP_DISTANCE) .description("Scale of the subsurface scattering (multiplied with Radius)"); -#define SOCK_SUBSURFACE_IOR_ID 2 +#define SOCK_SUBSURFACE_SCALE_ID 2 b.add_input("Subsurface Radius") .default_value({1.0f, 0.2f, 0.1f}) .min(0.0f) @@ -42,10 +42,13 @@ static void node_declare(NodeDeclarationBuilder &b) .compact() .description("Scattering radius to use for subsurface component (multiplied with Scale)"); #define SOCK_SUBSURFACE_RADIUS_ID 3 - b.add_input("Subsurface Color") - .default_value({0.8f, 0.8f, 0.8f, 1.0f}) - .description("The overall color resulting from subsurface scattering effects"); -#define SOCK_SUBSURFACE_COLOR_ID 4 + b.add_input("Subsurface IOR") + .default_value(1.4f) + .min(1.01f) + .max(3.8f) + .subtype(PROP_FACTOR) + .description("Index of refraction used for rays that enter the subsurface component"); +#define SOCK_SUBSURFACE_IOR_ID 4 b.add_input("Subsurface Anisotropy") .default_value(0.0f) .min(0.0f) @@ -250,11 +253,10 @@ static void node_shader_update_principled(bNodeTree *ntree, bNode *node) { const int sss_method = node->custom2; - LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) { - if (STR_ELEM(sock->name, "Subsurface IOR", "Subsurface Anisotropy")) { - bke::nodeSetSocketAvailability(ntree, sock, sss_method != SHD_SUBSURFACE_BURLEY); - } - } + bke::nodeSetSocketAvailability( + ntree, nodeFindSocket(node, SOCK_IN, "Subsurface IOR"), sss_method == SHD_SUBSURFACE_RANDOM_WALK); + bke::nodeSetSocketAvailability( + ntree, nodeFindSocket(node, SOCK_IN, "Subsurface Anisotropy"), sss_method != SHD_SUBSURFACE_BURLEY); } } // namespace blender::nodes::node_shader_bsdf_principled_cc -- 2.30.2 From 4c7c4a42812cf225719677ea7b6c7272a9fdd711 Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Mon, 11 Sep 2023 04:19:07 +0200 Subject: [PATCH 6/7] Address review --- intern/cycles/kernel/integrator/subsurface.h | 1 - intern/cycles/kernel/svm/closure.h | 1 - 2 files changed, 2 deletions(-) diff --git a/intern/cycles/kernel/integrator/subsurface.h b/intern/cycles/kernel/integrator/subsurface.h index 9eb7d25e0d8..7fc4b4d5f4f 100644 --- a/intern/cycles/kernel/integrator/subsurface.h +++ b/intern/cycles/kernel/integrator/subsurface.h @@ -52,7 +52,6 @@ ccl_device_inline bool subsurface_entry_bounce(KernelGlobals kg, make_orthonormals(Z, &X, &Y); const float alpha = bssrdf->alpha; - const float alpha2 = sqr(alpha); const float neta = 1.0f / bssrdf->ior; /* Sample microfacet normal by transforming to/from local coordinates. */ diff --git a/intern/cycles/kernel/svm/closure.h b/intern/cycles/kernel/svm/closure.h index f1642f84d9a..adc69569c2f 100644 --- a/intern/cycles/kernel/svm/closure.h +++ b/intern/cycles/kernel/svm/closure.h @@ -756,7 +756,6 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, bssrdf->albedo = closure_weight; bssrdf->N = N; bssrdf->ior = param2; - /* TODO */ bssrdf->alpha = 1.0f; bssrdf->anisotropy = stack_load_float(stack, data_node.w); -- 2.30.2 From fe6b3960b436470e8e0ebcd1babce2a3f692233d Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Wed, 13 Sep 2023 02:23:51 +0200 Subject: [PATCH 7/7] Add TODO comment for guiding PDF --- intern/cycles/kernel/integrator/subsurface_random_walk.h | 1 + 1 file changed, 1 insertion(+) diff --git a/intern/cycles/kernel/integrator/subsurface_random_walk.h b/intern/cycles/kernel/integrator/subsurface_random_walk.h index 3a19cfb8713..4da558be4b0 100644 --- a/intern/cycles/kernel/integrator/subsurface_random_walk.h +++ b/intern/cycles/kernel/integrator/subsurface_random_walk.h @@ -426,6 +426,7 @@ ccl_device_inline bool subsurface_random_walk(KernelGlobals kg, if (hit) { kernel_assert(isfinite_safe(throughput)); + /* TODO(lukas): Which PDF should we report here? Entry bounce? The random walk? Just 1.0? */ guiding_record_bssrdf_bounce( kg, state, -- 2.30.2