Eevee: SSS: Add separated Albedo option.
This option prevent from automatically blurring the albedo color applied to the SSS. While this is great for preserving details it can bleed more light onto the nearby objects since the blurring will be done on pure "white" irradiance. This issue is to be tackled in a separate commit.
This commit is contained in:
parent
8d4aa6bf44
commit
7cbc7dd904
|
@ -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):
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
|
|
Loading…
Reference in New Issue