diff options
10 files changed, 97 insertions, 11 deletions
diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py index e62f0a6e100..01dba8ec69b 100644 --- a/release/scripts/startup/bl_ui/properties_render.py +++ b/release/scripts/startup/bl_ui/properties_render.py @@ -780,6 +780,7 @@ class RENDER_PT_eevee_subsurface_scattering(RenderButtonsPanel, Panel): col = layout.column() col.prop(props, "sss_samples") col.prop(props, "sss_jitter_threshold") + col.prop(props, "sss_separate_albedo") class RENDER_PT_eevee_screen_space_reflections(RenderButtonsPanel, Panel): diff --git a/release/scripts/startup/bl_ui/properties_view_layer.py b/release/scripts/startup/bl_ui/properties_view_layer.py index b1c76a79fcd..7f3cefb1161 100644 --- a/release/scripts/startup/bl_ui/properties_view_layer.py +++ b/release/scripts/startup/bl_ui/properties_view_layer.py @@ -346,6 +346,7 @@ class VIEWLAYER_PT_eevee_subsurface_scattering(ViewLayerButtonsPanel, Panel): col = layout.column() col.template_override_property(layer_props, scene_props, "sss_samples") col.template_override_property(layer_props, scene_props, "sss_jitter_threshold") + col.template_override_property(layer_props, scene_props, "sss_separate_albedo") class VIEWLAYER_PT_eevee_screen_space_reflections(ViewLayerButtonsPanel, Panel): diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c index 2378a3c8784..f059fbe2268 100644 --- a/source/blender/draw/engines/eevee/eevee_engine.c +++ b/source/blender/draw/engines/eevee/eevee_engine.c @@ -326,6 +326,7 @@ static void EEVEE_view_layer_settings_create(RenderEngine *UNUSED(engine), IDPro BKE_collection_engine_property_add_bool(props, "sss_enable", false); BKE_collection_engine_property_add_int(props, "sss_samples", 7); BKE_collection_engine_property_add_float(props, "sss_jitter_threshold", 0.3f); + BKE_collection_engine_property_add_bool(props, "sss_separate_albedo", false); BKE_collection_engine_property_add_bool(props, "ssr_enable", false); BKE_collection_engine_property_add_bool(props, "ssr_refraction", false); diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index 7069e46edf1..77d57716852 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -307,6 +307,9 @@ static char *eevee_get_defines(int options) if ((options & VAR_MAT_SSS) != 0) { BLI_dynstr_appendf(ds, "#define USE_SSS\n"); } + if ((options & VAR_MAT_SSSALBED) != 0) { + BLI_dynstr_appendf(ds, "#define USE_SSS_ALBEDO\n"); + } if ((options & VAR_MAT_TRANSLUC) != 0) { BLI_dynstr_appendf(ds, "#define USE_TRANSLUCENCY\n"); } @@ -651,6 +654,7 @@ struct GPUMaterial *EEVEE_material_mesh_get( if (use_multiply) options |= VAR_MAT_MULT; if (use_refract) options |= VAR_MAT_REFRACT; if (use_sss) options |= VAR_MAT_SSS; + if (use_sss && vedata->stl->effects->sss_separate_albedo) options |= VAR_MAT_SSSALBED; if (use_translucency) options |= VAR_MAT_TRANSLUC; if (vedata->stl->effects->use_volumetrics && use_blend) options |= VAR_MAT_VOLUME; diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index a97f7db5c0d..93fc3ee27d3 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -117,6 +117,7 @@ enum { VAR_MAT_VOLUME = (1 << 13), VAR_MAT_SSS = (1 << 14), VAR_MAT_TRANSLUC = (1 << 15), + VAR_MAT_SSSALBED = (1 << 16), }; /* Shadow Technique */ @@ -252,6 +253,7 @@ typedef struct EEVEE_TextureList { struct GPUTexture *gtao_horizons; struct GPUTexture *sss_data; + struct GPUTexture *sss_albedo; struct GPUTexture *sss_blur; struct GPUTexture *sss_stencil; @@ -433,6 +435,7 @@ typedef struct EEVEE_EffectsInfo { /* SSSS */ int sss_sample_count; float sss_jitter_threshold; + bool sss_separate_albedo; /* Volumetrics */ bool use_volumetrics; diff --git a/source/blender/draw/engines/eevee/eevee_subsurface.c b/source/blender/draw/engines/eevee/eevee_subsurface.c index d96d7b6a983..4efdfb0fb84 100644 --- a/source/blender/draw/engines/eevee/eevee_subsurface.c +++ b/source/blender/draw/engines/eevee/eevee_subsurface.c @@ -33,7 +33,7 @@ #include "GPU_texture.h" static struct { - struct GPUShader *sss_sh[2]; + struct GPUShader *sss_sh[3]; } e_data = {NULL}; /* Engine data */ extern char datatoc_effect_subsurface_frag_glsl[]; @@ -42,6 +42,8 @@ static void eevee_create_shader_subsurface(void) { e_data.sss_sh[0] = DRW_shader_create_fullscreen(datatoc_effect_subsurface_frag_glsl, "#define FIRST_PASS\n"); e_data.sss_sh[1] = DRW_shader_create_fullscreen(datatoc_effect_subsurface_frag_glsl, "#define SECOND_PASS\n"); + e_data.sss_sh[2] = DRW_shader_create_fullscreen(datatoc_effect_subsurface_frag_glsl, "#define SECOND_PASS\n" + "#define USE_SEP_ALBEDO\n"); } int EEVEE_subsurface_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) @@ -59,6 +61,7 @@ int EEVEE_subsurface_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedat if (BKE_collection_engine_property_value_get_bool(props, "sss_enable")) { effects->sss_sample_count = 1 + BKE_collection_engine_property_value_get_int(props, "sss_samples") * 2; effects->sss_jitter_threshold = BKE_collection_engine_property_value_get_float(props, "sss_jitter_threshold"); + effects->sss_separate_albedo = BKE_collection_engine_property_value_get_bool(props, "sss_separate_albedo"); /* Shaders */ if (!e_data.sss_sh[0]) { @@ -79,10 +82,16 @@ int EEVEE_subsurface_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedat DRW_framebuffer_init(&fbl->sss_clear_fb, &draw_engine_eevee_type, (int)viewport_size[0], (int)viewport_size[1], &tex_data, 1); + if (effects->sss_separate_albedo && (txl->sss_albedo == NULL)) { + txl->sss_albedo = DRW_texture_create_2D((int)viewport_size[0], (int)viewport_size[1], + DRW_TEX_RGB_11_11_10, 0, NULL); + } + return EFFECT_SSS; } /* Cleanup to release memory */ + DRW_TEXTURE_FREE_SAFE(txl->sss_albedo); DRW_TEXTURE_FREE_SAFE(txl->sss_data); DRW_TEXTURE_FREE_SAFE(txl->sss_blur); DRW_TEXTURE_FREE_SAFE(txl->sss_stencil); @@ -127,7 +136,8 @@ void EEVEE_subsurface_add_pass(EEVEE_Data *vedata, unsigned int sss_id, struct G DRW_shgroup_stencil_mask(grp, sss_id); DRW_shgroup_call_add(grp, quad, NULL); - grp = DRW_shgroup_create(e_data.sss_sh[1], psl->sss_resolve_ps); + struct GPUShader *sh = (effects->sss_separate_albedo) ? e_data.sss_sh[2] : e_data.sss_sh[1]; + grp = DRW_shgroup_create(sh, psl->sss_resolve_ps); DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)vedata->stl->g_data->viewvecs, 2); DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex()); DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth); @@ -136,6 +146,10 @@ void EEVEE_subsurface_add_pass(EEVEE_Data *vedata, unsigned int sss_id, struct G DRW_shgroup_uniform_float(grp, "jitterThreshold", &effects->sss_jitter_threshold, 1); DRW_shgroup_stencil_mask(grp, sss_id); DRW_shgroup_call_add(grp, quad, NULL); + + if (effects->sss_separate_albedo) { + DRW_shgroup_uniform_buffer(grp, "sssAlbedo", &txl->sss_albedo); + } } void EEVEE_subsurface_data_render(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) @@ -152,38 +166,50 @@ void EEVEE_subsurface_data_render(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Dat DRW_framebuffer_bind(fbl->sss_clear_fb); DRW_framebuffer_clear(true, false, false, clear, 0.0f); + + DRW_framebuffer_texture_detach(txl->sss_data); if ((effects->enabled_effects & EFFECT_NORMAL_BUFFER) != 0) { DRW_framebuffer_texture_detach(txl->ssr_normal_input); } if ((effects->enabled_effects & EFFECT_SSR) != 0) { DRW_framebuffer_texture_detach(txl->ssr_specrough_input); } + + /* Start at slot 1 because slot 0 is txl->color */ + int tex_slot = 1; + DRW_framebuffer_texture_attach(fbl->main, txl->sss_data, tex_slot++, 0); + if (effects->sss_separate_albedo) { + DRW_framebuffer_texture_attach(fbl->main, txl->sss_albedo, tex_slot++, 0); + } if ((effects->enabled_effects & EFFECT_NORMAL_BUFFER) != 0) { - DRW_framebuffer_texture_attach(fbl->main, txl->ssr_normal_input, 2, 0); + DRW_framebuffer_texture_attach(fbl->main, txl->ssr_normal_input, tex_slot++, 0); } if ((effects->enabled_effects & EFFECT_SSR) != 0) { - DRW_framebuffer_texture_attach(fbl->main, txl->ssr_specrough_input, 3, 0); + DRW_framebuffer_texture_attach(fbl->main, txl->ssr_specrough_input, tex_slot++, 0); } - DRW_framebuffer_texture_detach(txl->sss_data); - DRW_framebuffer_texture_attach(fbl->main, txl->sss_data, 1, 0); DRW_framebuffer_bind(fbl->main); DRW_draw_pass(psl->sss_pass); + /* Restore */ + DRW_framebuffer_texture_detach(txl->sss_data); + if (effects->sss_separate_albedo) { + DRW_framebuffer_texture_detach(txl->sss_albedo); + } if ((effects->enabled_effects & EFFECT_NORMAL_BUFFER) != 0) { DRW_framebuffer_texture_detach(txl->ssr_normal_input); } if ((effects->enabled_effects & EFFECT_SSR) != 0) { DRW_framebuffer_texture_detach(txl->ssr_specrough_input); } - DRW_framebuffer_texture_detach(txl->sss_data); + + DRW_framebuffer_texture_attach(fbl->sss_clear_fb, txl->sss_data, 0, 0); if ((effects->enabled_effects & EFFECT_NORMAL_BUFFER) != 0) { DRW_framebuffer_texture_attach(fbl->main, txl->ssr_normal_input, 1, 0); } if ((effects->enabled_effects & EFFECT_SSR) != 0) { DRW_framebuffer_texture_attach(fbl->main, txl->ssr_specrough_input, 2, 0); } - DRW_framebuffer_texture_attach(fbl->sss_clear_fb, txl->sss_data, 0, 0); } } @@ -230,4 +256,5 @@ void EEVEE_subsurface_free(void) { DRW_SHADER_FREE_SAFE(e_data.sss_sh[0]); DRW_SHADER_FREE_SAFE(e_data.sss_sh[1]); + DRW_SHADER_FREE_SAFE(e_data.sss_sh[2]); } 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 32d27838da3..54825303b5d 100644 --- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl @@ -583,6 +583,9 @@ struct Closure { float opacity; #ifdef USE_SSS vec4 sss_data; +#ifdef USE_SSS_ALBEDO + vec3 sss_albedo; +#endif #endif vec4 ssr_data; vec2 ssr_normal; @@ -594,7 +597,11 @@ struct Closure { #define REFRACT_CLOSURE_FLAG -3 #ifdef USE_SSS +#ifdef USE_SSS_ALBEDO +#define CLOSURE_DEFAULT Closure(vec3(0.0), 1.0, vec4(0.0), vec3(0.0), vec4(0.0), vec2(0.0), -1) +#else #define CLOSURE_DEFAULT Closure(vec3(0.0), 1.0, vec4(0.0), vec4(0.0), vec2(0.0), -1) +#endif #else #define CLOSURE_DEFAULT Closure(vec3(0.0), 1.0, vec4(0.0), vec2(0.0), -1) #endif @@ -608,6 +615,9 @@ Closure closure_mix(Closure cl1, Closure cl2, float fac) #ifdef USE_SSS cl.sss_data.rgb = mix(cl1.sss_data.rgb, cl2.sss_data.rgb, fac); cl.sss_data.a = (cl1.sss_data.a > 0.0) ? cl1.sss_data.a : cl2.sss_data.a; +#ifdef USE_SSS_ALBEDO + cl.sss_albedo = (cl1.sss_data.a > 0.0) ? cl1.sss_albedo : cl2.sss_albedo; +#endif #endif if (cl1.ssr_id == outputSsrId) { @@ -637,6 +647,9 @@ Closure closure_add(Closure cl1, Closure cl2) Closure cl = (cl1.ssr_id == outputSsrId) ? cl1 : cl2; #ifdef USE_SSS cl.sss_data = (cl1.sss_data.a > 0.0) ? cl1.sss_data : cl2.sss_data; +#ifdef USE_SSS_ALBEDO + cl.sss_albedo = (cl1.sss_data.a > 0.0) ? cl1.sss_albedo : cl2.sss_albedo; +#endif #endif cl.radiance = cl1.radiance + cl2.radiance; cl.opacity = cl1.opacity + cl2.opacity; @@ -646,13 +659,20 @@ Closure closure_add(Closure cl1, Closure cl2) #if defined(MESH_SHADER) && !defined(USE_ALPHA_HASH) && !defined(USE_ALPHA_CLIP) && !defined(SHADOW_SHADER) && !defined(USE_MULTIPLY) layout(location = 0) out vec4 fragColor; #ifdef USE_SSS +#ifdef USE_SSS_ALBEDO +layout(location = 1) out vec4 sssData; +layout(location = 2) out vec4 sssAlbedo; +layout(location = 3) out vec4 ssrNormals; +layout(location = 4) out vec4 ssrData; +#else layout(location = 1) out vec4 sssData; layout(location = 2) out vec4 ssrNormals; layout(location = 3) out vec4 ssrData; +#endif /* USE_SSS_ALBEDO */ #else layout(location = 1) out vec4 ssrNormals; layout(location = 2) out vec4 ssrData; -#endif +#endif /* USE_SSS */ Closure nodetree_exec(void); /* Prototype */ @@ -678,6 +698,9 @@ void main() ssrData = cl.ssr_data; #ifdef USE_SSS sssData = cl.sss_data; +#ifdef USE_SSS_ALBEDO + sssAlbedo = cl.sss_albedo.rgbb; +#endif #endif } diff --git a/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl index ea9711a6cad..88e71a060c5 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl @@ -11,6 +11,7 @@ layout(std140) uniform sssProfile { uniform float jitterThreshold; uniform sampler2D depthBuffer; uniform sampler2D sssData; +uniform sampler2D sssAlbedo; uniform sampler2DArray utilTex; out vec4 FragColor; @@ -80,6 +81,10 @@ void main(void) #ifdef FIRST_PASS FragColor = vec4(accum, sss_data.a); #else /* SECOND_PASS */ + #ifdef USE_SEP_ALBEDO + FragColor = vec4(accum * texture(sssAlbedo, uvs).rgb, 1.0); + #else FragColor = vec4(accum, 1.0); + #endif #endif } diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index b23c1708ee1..9d22fbba65e 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -2909,7 +2909,12 @@ void node_bsdf_principled_clearcoat(vec4 base_color, float subsurface, vec3 subs result.ssr_id = int(ssr_id); #ifdef USE_SSS result.sss_data.a = sss_scalef; - result.sss_data.rgb = (out_diff + out_trans) * mix(vec3(0.0), subsurface_color.rgb, subsurface); + result.sss_data.rgb = out_diff + out_trans; +#ifdef USE_SSS_ALBEDO + result.sss_albedo.rgb = mix(vec3(0.0), subsurface_color.rgb, subsurface); +#else + result.sss_data.rgb *= mix(vec3(0.0), subsurface_color.rgb, subsurface); +#endif result.sss_data.rgb *= (1.0 - transmission); #endif @@ -2954,7 +2959,14 @@ void node_subsurface_scattering( result.ssr_id = -1; result.sss_data.a = scale; eevee_closure_subsurface(N, color.rgb, 1.0, scale, out_diff, out_trans); - result.sss_data.rgb = (out_diff + out_trans) * color.rgb; + result.sss_data.rgb = out_diff + out_trans; +#ifdef USE_SSS_ALBEDO + /* Not perfect for texture_blur not exaclty equal to 0.0 or 1.0. */ + result.sss_albedo.rgb = mix(color.rgb, vec3(1.0), texture_blur); + result.sss_data.rgb *= mix(vec3(1.0), color.rgb, texture_blur); +#else + result.sss_data.rgb *= color.rgb; +#endif #else node_bsdf_diffuse(color, 0.0, N, result); #endif diff --git a/source/blender/makesrna/intern/rna_layer.c b/source/blender/makesrna/intern/rna_layer.c index 81e10324241..4583774318b 100644 --- a/source/blender/makesrna/intern/rna_layer.c +++ b/source/blender/makesrna/intern/rna_layer.c @@ -370,6 +370,7 @@ RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(volumetric_colored_transmittance) RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(sss_enable) RNA_LAYER_ENGINE_EEVEE_GET_SET_INT(sss_samples) RNA_LAYER_ENGINE_EEVEE_GET_SET_FLOAT(sss_jitter_threshold) +RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(sss_separate_albedo) RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(ssr_refraction) RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(ssr_enable) RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(ssr_halfres) @@ -1217,6 +1218,14 @@ static void rna_def_view_layer_engine_settings_eevee(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update"); + prop = RNA_def_property(srna, "sss_separate_albedo", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_Eevee_sss_separate_albedo_get", + "rna_LayerEngineSettings_Eevee_sss_separate_albedo_set"); + RNA_def_property_ui_text(prop, "Separate Albedo", "Avoid albedo being blured by the subsurface scattering " + "but uses more video memory"); + RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); + RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update"); + /* Screen Space Reflection */ prop = RNA_def_property(srna, "ssr_enable", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_Eevee_ssr_enable_get", |