diff options
Diffstat (limited to 'source')
5 files changed, 105 insertions, 13 deletions
diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl index b2c72126c40..bbb69d557c4 100644 --- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl @@ -580,6 +580,9 @@ Closure closure_add(Closure cl1, Closure cl2) struct Closure { vec3 radiance; float opacity; +#ifdef USE_SSS + vec4 sss_data; +#endif vec4 ssr_data; vec2 ssr_normal; int ssr_id; @@ -589,13 +592,22 @@ struct Closure { #define TRANSPARENT_CLOSURE_FLAG -2 #define REFRACT_CLOSURE_FLAG -3 +#ifdef USE_SSS +#define CLOSURE_DEFAULT Closure(vec3(0.0), 1.0, vec4(0.0), vec4(0.0), vec2(0.0), -1) +#else #define CLOSURE_DEFAULT Closure(vec3(0.0), 1.0, vec4(0.0), vec2(0.0), -1) +#endif uniform int outputSsrId; Closure closure_mix(Closure cl1, Closure cl2, float fac) { Closure cl; + +#ifdef USE_SSS + cl.sss_data = mix(cl1.sss_data, cl2.sss_data, fac); +#endif + if (cl1.ssr_id == outputSsrId) { cl.ssr_data = mix(cl1.ssr_data.xyzw, vec4(vec3(0.0), cl1.ssr_data.w), fac); /* do not blend roughness */ cl.ssr_normal = cl1.ssr_normal; @@ -603,6 +615,7 @@ Closure closure_mix(Closure cl1, Closure cl2, float fac) } else { cl.ssr_data = mix(vec4(vec3(0.0), cl2.ssr_data.w), cl2.ssr_data.xyzw, fac); /* do not blend roughness */ + cl.ssr_data = mix(vec4(vec3(0.0), cl2.ssr_data.w), cl2.ssr_data.xyzw, fac); /* do not blend roughness */ cl.ssr_normal = cl2.ssr_normal; cl.ssr_id = cl2.ssr_id; } diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index 2cf66c78db1..e829c4a0c0e 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -2672,7 +2672,11 @@ void node_bsdf_diffuse(vec4 color, float roughness, vec3 N, out Closure result) #ifdef EEVEE_ENGINE vec3 L = eevee_surface_diffuse_lit(N, vec3(1.0), 1.0); vec3 vN = normalize(mat3(ViewMatrix) * N); - result = Closure(L * color.rgb, 1.0, vec4(0.0), normal_encode(vN, viewCameraVec), -1); + result.radiance = L * color.rgb; + result.opacity = 1.0; + result.ssr_data = vec4(0.0); + result.ssr_normal = normal_encode(vN, viewCameraVec); + result.ssr_id = -1; #else /* ambient light */ vec3 L = vec3(0.2); @@ -2697,7 +2701,11 @@ void node_bsdf_glossy(vec4 color, float roughness, vec3 N, float ssr_id, out Clo roughness = sqrt(roughness); vec3 L = eevee_surface_glossy_lit(N, vec3(1.0), roughness, 1.0, int(ssr_id), ssr_spec); vec3 vN = normalize(mat3(ViewMatrix) * N); - result = Closure(L * color.rgb, 1.0, vec4(ssr_spec * color.rgb, roughness), normal_encode(vN, viewCameraVec), int(ssr_id)); + result.radiance = L * color.rgb; + result.opacity = 1.0; + result.ssr_data = vec4(ssr_spec * color.rgb, roughness); + result.ssr_normal = normal_encode(vN, viewCameraVec); + result.ssr_id = int(ssr_id); #else /* ambient light */ vec3 L = vec3(0.2); @@ -2735,7 +2743,11 @@ void node_bsdf_glass(vec4 color, float roughness, float ior, vec3 N, float ssr_i roughness = sqrt(roughness); vec3 L = eevee_surface_glass(N, (refractionDepth > 0.0) ? color.rgb : vec3(1.0), roughness, ior, int(ssr_id), ssr_spec); vec3 vN = normalize(mat3(ViewMatrix) * N); - result = Closure(L * color.rgb, 1.0, vec4(ssr_spec * color.rgb, roughness), normal_encode(vN, viewCameraVec), int(ssr_id)); + result.radiance = L * color.rgb; + result.opacity = 1.0; + result.ssr_data = vec4(ssr_spec * color.rgb, roughness); + result.ssr_normal = normal_encode(vN, viewCameraVec); + result.ssr_id = int(ssr_id); #else node_bsdf_diffuse(color, 0.0, N, result); #endif @@ -2856,7 +2868,11 @@ void node_bsdf_principled_simple(vec4 base_color, float subsurface, vec3 subsurf vec3 L = eevee_surface_lit(N, diffuse, f0, roughness, 1.0, int(ssr_id), ssr_spec); vec3 vN = normalize(mat3(ViewMatrix) * N); - result = Closure(L, 1.0, vec4(ssr_spec, roughness), normal_encode(vN, viewCameraVec), int(ssr_id)); + result.radiance = L; + result.opacity = 1.0; + result.ssr_data = vec4(ssr_spec, roughness); + result.ssr_normal = normal_encode(vN, viewCameraVec); + result.ssr_id = int(ssr_id); #else node_bsdf_principled(base_color, subsurface, subsurface_radius, subsurface_color, metallic, specular, specular_tint, roughness, anisotropic, anisotropic_rotation, sheen, sheen_tint, clearcoat, @@ -2909,7 +2925,11 @@ void node_bsdf_principled_clearcoat(vec4 base_color, float subsurface, vec3 subs vec3 L = eevee_surface_clearcoat_lit(N, diffuse, f0, roughness, CN, clearcoat, clearcoat_roughness, 1.0, int(ssr_id), ssr_spec); L = mix(L, L_trans, transmission); vec3 vN = normalize(mat3(ViewMatrix) * N); - result = Closure(L, 1.0, vec4(ssr_spec, roughness), normal_encode(vN, viewCameraVec), int(ssr_id)); + result.radiance = L; + result.opacity = 1.0; + result.ssr_data = vec4(ssr_spec, roughness); + result.ssr_normal = normal_encode(vN, viewCameraVec); + result.ssr_id = int(ssr_id); #endif #else @@ -2940,10 +2960,21 @@ void node_bsdf_velvet(vec4 color, float sigma, vec3 N, out Closure result) } void node_subsurface_scattering( - vec4 color, float scale, vec3 radius, float sharpen, float texture_blur, vec3 N, + vec4 color, float scale, vec3 radius, float sharpen, float texture_blur, vec3 N, float sss_id, out Closure result) { +#if defined(EEVEE_ENGINE) && defined(USE_SSS) + vec3 vN = normalize(mat3(ViewMatrix) * N); + result.radiance = vec3(0.0); + result.opacity = 1.0; + result.ssr_data = vec4(0.0); + result.ssr_normal = normal_encode(vN, viewCameraVec); + result.ssr_id = -1; + result.sss_data.rgb = eevee_surface_diffuse_lit(N, vec3(1.0), 1.0) * color.rgb; + result.sss_data.a = scale; +#else node_bsdf_diffuse(color, 0.0, N, result); +#endif } void node_bsdf_refraction(vec4 color, float roughness, float ior, vec3 N, out Closure result) @@ -2952,7 +2983,9 @@ void node_bsdf_refraction(vec4 color, float roughness, float ior, vec3 N, out Cl color.rgb *= (refractionDepth > 0.0) ? color.rgb : vec3(1.0); /* Simulate 2 absorption event. */ roughness = sqrt(roughness); vec3 L = eevee_surface_refraction(N, vec3(1.0), roughness, ior); - result = Closure(L * color.rgb, 1.0, vec4(0.0), vec2(0.0), REFRACT_CLOSURE_FLAG); + result.radiance = L * color.rgb; + result.opacity = 1.0; + result.ssr_id = REFRACT_CLOSURE_FLAG; #else node_bsdf_diffuse(color, 0.0, N, result); #endif /* EEVEE_ENGINE */ @@ -2980,7 +3013,11 @@ void node_emission(vec4 color, float strength, vec3 N, out Closure result) #ifndef VOLUMETRICS color *= strength; #ifdef EEVEE_ENGINE - result = Closure(color.rgb, color.a, vec4(0.0), normal_encode(N, viewCameraVec), -1); + result.radiance = color.rgb; + result.opacity = color.a; + result.ssr_data = vec4(0.0); + result.ssr_normal = normal_encode(N, viewCameraVec); + result.ssr_id = -1; #else result = Closure(color.rgb, color.a); #endif @@ -3009,7 +3046,8 @@ void node_background(vec4 color, float strength, out Closure result) #ifndef VOLUMETRICS color *= strength; #ifdef EEVEE_ENGINE - result = Closure(color.rgb, color.a, vec4(0.0), vec2(0.0), -1); + result.radiance = color.rgb; + result.opacity = color.a; #else result = Closure(color.rgb, color.a); #endif @@ -4115,7 +4153,8 @@ void node_output_world(Closure surface, Closure volume, out Closure result) { #ifndef VOLUMETRICS #ifdef EEVEE_ENGINE - result = Closure(surface.radiance, backgroundAlpha, vec4(0.0), vec2(0.0), -1); + result.radiance = surface.radiance; + result.opacity = backgroundAlpha; #else result = Closure(surface.radiance, backgroundAlpha); #endif @@ -4142,7 +4181,11 @@ void node_eevee_specular( vec3 L = eevee_surface_lit(normal, diffuse.rgb, specular.rgb, roughness, occlusion, int(ssr_id), ssr_spec); vec3 vN = normalize(mat3(ViewMatrix) * normal); - result = Closure(L + emissive.rgb, 1.0 - transp, vec4(ssr_spec, roughness), normal_encode(vN, viewCameraVec), int(ssr_id)); + result.radiance = L + emissive.rgb; + result.opacity = 1.0 - transp; + result.ssr_data = vec4(ssr_spec, roughness); + result.ssr_normal = normal_encode(vN, viewCameraVec); + result.ssr_id = int(ssr_id); } #endif /* EEVEE_ENGINE */ diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 016de0f1cc9..0bd36244ffb 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -225,7 +225,7 @@ typedef struct bNode { struct uiBlock *block; /* runtime during drawing */ float ssr_id; /* XXX: eevee only, id of screen space reflection layer, needs to be a float to feed GPU_uniform. */ - float pad3; + float sss_id; /* XXX: eevee only, id of screen subsurface scatter layer, needs to be a float to feed GPU_uniform. */ } bNode; /* node->flag */ diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c index d05f9316fc4..18229db384f 100644 --- a/source/blender/nodes/shader/node_shader_tree.c +++ b/source/blender/nodes/shader/node_shader_tree.c @@ -527,6 +527,41 @@ static void ntree_shader_tag_ssr_node(bNodeTree *ntree, short compatibility) nodeChainIter(ntree, output_node, ntree_tag_ssr_bsdf_cb, &lobe_count, true); } +static bool ntree_tag_sss_bsdf_cb(bNode *fromnode, bNode *UNUSED(tonode), void *userdata, const bool UNUSED(reversed)) +{ + switch (fromnode->type) { + case SH_NODE_BSDF_PRINCIPLED: + case SH_NODE_SUBSURFACE_SCATTERING: + fromnode->sss_id = (*(float *)userdata); + (*(float *)userdata) += 1; + break; + default: + break; + } + + return true; +} + +/* EEVEE: Scan the ntree to set the Subsurface Scattering id of every SSS node. + */ +static void ntree_shader_tag_sss_node(bNodeTree *ntree, short compatibility) +{ + if (compatibility & NODE_NEWER_SHADING) { + /* We can only deal with new shading system here. */ + return; + } + + bNode *output_node = ntree_shader_output_node(ntree); + if (output_node == NULL) { + return; + } + /* Make sure sockets links pointers are correct. */ + ntreeUpdateTree(G.main, ntree); + + int sss_count = 0; + nodeChainIter(ntree, output_node, ntree_tag_sss_bsdf_cb, &sss_count, true); +} + /* EEVEE: Find which material domain are used (volume, surface ...). */ void ntreeGPUMaterialDomain(bNodeTree *ntree, bool *has_surface_output, bool *has_volume_output) @@ -568,6 +603,7 @@ void ntreeGPUMaterialNodes(bNodeTree *ntree, GPUMaterial *mat, short compatibili ntree_shader_relink_displacement(localtree, compatibility); ntree_shader_tag_ssr_node(localtree, compatibility); + ntree_shader_tag_sss_node(localtree, compatibility); exec = ntreeShaderBeginExecTree(localtree); ntreeExecGPUNodes(exec, mat, 1, compatibility); diff --git a/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c b/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c index e34ff0aa420..58f345c2590 100644 --- a/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c +++ b/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c @@ -54,7 +54,7 @@ static int node_shader_gpu_subsurface_scattering(GPUMaterial *mat, bNode *node, if (!in[5].link) GPU_link(mat, "world_normals_get", &in[5].link); - return GPU_stack_link(mat, node, "node_subsurface_scattering", in, out); + return GPU_stack_link(mat, node, "node_subsurface_scattering", in, out, GPU_uniform(&node->sss_id)); } static void node_shader_update_subsurface_scattering(bNodeTree *UNUSED(ntree), bNode *node) |