diff --git a/intern/cycles/kernel/osl/shaders/node_subsurface_scattering.osl b/intern/cycles/kernel/osl/shaders/node_subsurface_scattering.osl index f8d82eefb21..1a6f07ccfaa 100644 --- a/intern/cycles/kernel/osl/shaders/node_subsurface_scattering.osl +++ b/intern/cycles/kernel/osl/shaders/node_subsurface_scattering.osl @@ -8,6 +8,7 @@ shader node_subsurface_scattering(color Color = 0.8, float Scale = 1.0, vector Radius = vector(0.1, 0.1, 0.1), float IOR = 1.4, + float Roughness = 1.0, float Anisotropy = 0.0, string method = "random_walk", normal Normal = N, @@ -23,5 +24,5 @@ shader node_subsurface_scattering(color Color = 0.8, "anisotropy", Anisotropy, "roughness", - 1.0); + clamp(Roughness, 0.0, 1.0)); } diff --git a/intern/cycles/kernel/svm/closure.h b/intern/cycles/kernel/svm/closure.h index e707a40cd8c..3d788ee5b4f 100644 --- a/intern/cycles/kernel/svm/closure.h +++ b/intern/cycles/kernel/svm/closure.h @@ -872,7 +872,7 @@ ccl_device bssrdf->albedo = closure_weight; bssrdf->N = maybe_ensure_valid_specular_reflection(sd, N); bssrdf->ior = param2; - bssrdf->alpha = 1.0f; + bssrdf->alpha = saturatef(stack_load_float(stack, data_node.w)); bssrdf->anisotropy = stack_load_float(stack, data_node.z); sd->flag |= bssrdf_setup(sd, bssrdf, path_flag, (ClosureType)type); diff --git a/intern/cycles/scene/shader_nodes.cpp b/intern/cycles/scene/shader_nodes.cpp index 96f879f728a..083a8da518e 100644 --- a/intern/cycles/scene/shader_nodes.cpp +++ b/intern/cycles/scene/shader_nodes.cpp @@ -2899,6 +2899,7 @@ NODE_DEFINE(SubsurfaceScatteringNode) SOCKET_IN_VECTOR(radius, "Radius", make_float3(0.1f, 0.1f, 0.1f)); SOCKET_IN_FLOAT(subsurface_ior, "IOR", 1.4f); + SOCKET_IN_FLOAT(subsurface_roughness, "Roughness", 1.0f); SOCKET_IN_FLOAT(subsurface_anisotropy, "Anisotropy", 0.0f); SOCKET_OUT_CLOSURE(BSSRDF, "BSSRDF"); @@ -2914,7 +2915,12 @@ SubsurfaceScatteringNode::SubsurfaceScatteringNode() : BsdfNode(get_node_type()) void SubsurfaceScatteringNode::compile(SVMCompiler &compiler) { closure = method; - BsdfNode::compile(compiler, input("Scale"), input("IOR"), input("Radius"), input("Anisotropy")); + BsdfNode::compile(compiler, + input("Scale"), + input("IOR"), + input("Radius"), + input("Anisotropy"), + input("Roughness")); } void SubsurfaceScatteringNode::compile(OSLCompiler &compiler) diff --git a/intern/cycles/scene/shader_nodes.h b/intern/cycles/scene/shader_nodes.h index bbb38477a89..cfc28aba752 100644 --- a/intern/cycles/scene/shader_nodes.h +++ b/intern/cycles/scene/shader_nodes.h @@ -653,6 +653,7 @@ class SubsurfaceScatteringNode : public BsdfNode { NODE_SOCKET_API(float, scale) NODE_SOCKET_API(float3, radius) NODE_SOCKET_API(float, subsurface_ior) + NODE_SOCKET_API(float, subsurface_roughness) NODE_SOCKET_API(float, subsurface_anisotropy) NODE_SOCKET_API(ClosureType, method) }; diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index ea8d6367c79..d266da913ac 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -29,7 +29,7 @@ extern "C" { /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 22 +#define BLENDER_FILE_SUBVERSION 23 /* Minimum Blender version that supports reading file written with the current * version. Older Blender versions will test this and cancel loading the file, showing a warning to diff --git a/source/blender/blenloader/intern/versioning_400.cc b/source/blender/blenloader/intern/versioning_400.cc index 14dc663c308..a0581bf6a5c 100644 --- a/source/blender/blenloader/intern/versioning_400.cc +++ b/source/blender/blenloader/intern/versioning_400.cc @@ -534,6 +534,12 @@ void do_versions_after_linking_400(FileData *fd, Main *bmain) } } + if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 23)) { + /* Shift animation data to accomidate the new Roughness input. */ + version_node_socket_index_animdata( + bmain, NTREE_SHADER, SH_NODE_SUBSURFACE_SCATTERING, 4, 1, 5); + } + /** * Always bump subversion in BKE_blender_version.h when adding versioning * code here, and wrap it inside a MAIN_VERSION_FILE_ATLEAST check. diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_subsurface_scattering.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_subsurface_scattering.glsl index db75151419b..fe7d0b79fd2 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_subsurface_scattering.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_subsurface_scattering.glsl @@ -6,6 +6,7 @@ void node_subsurface_scattering(vec4 color, float scale, vec3 radius, float ior, + float roughness, float anisotropy, vec3 N, float weight, @@ -14,6 +15,7 @@ void node_subsurface_scattering(vec4 color, { color = max(color, vec4(0.0)); ior = max(ior, 1e-5); + /* roughness = saturate(roughness) */ N = safe_normalize(N); ClosureSubsurface sss_data; diff --git a/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.cc b/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.cc index af9c98d4c38..b71b017da52 100644 --- a/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.cc +++ b/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.cc @@ -19,6 +19,11 @@ static void node_declare(NodeDeclarationBuilder &b) b.add_input("Scale").default_value(0.05f).min(0.0f).max(1000.0f); b.add_input("Radius").default_value({1.0f, 0.2f, 0.1f}).min(0.0f).max(100.0f); b.add_input("IOR").default_value(1.4f).min(1.01f).max(3.8f).subtype(PROP_FACTOR); + b.add_input("Roughness") + .default_value(1.0f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); b.add_input("Anisotropy") .default_value(0.0f) .min(0.0f) @@ -46,8 +51,8 @@ static int node_shader_gpu_subsurface_scattering(GPUMaterial *mat, GPUNodeStack *in, GPUNodeStack *out) { - if (!in[5].link) { - GPU_link(mat, "world_normals_get", &in[5].link); + if (!in[6].link) { + GPU_link(mat, "world_normals_get", &in[6].link); } bNodeSocket *socket = (bNodeSocket *)BLI_findlink(&node->runtime->original->inputs, 2); @@ -70,6 +75,9 @@ static void node_shader_update_subsurface_scattering(bNodeTree *ntree, bNode *no if (STR_ELEM(sock->name, "IOR", "Anisotropy")) { bke::nodeSetSocketAvailability(ntree, sock, sss_method != SHD_SUBSURFACE_BURLEY); } + if (STR_ELEM(sock->name, "Roughness")) { + bke::nodeSetSocketAvailability(ntree, sock, sss_method == SHD_SUBSURFACE_RANDOM_WALK); + } } }