Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2018-01-31 23:17:27 +0300
committerClément Foucault <foucault.clem@gmail.com>2018-02-01 20:09:17 +0300
commit253b412acefc6abe9c221a4886e153739c4f50f4 (patch)
tree1b6c307dc634d55b5337e3ae0b370d295d1ac844 /source
parenta57063a432a3908b0b750b889478ba87dfed60e2 (diff)
Eevee: Render: Add Subsurface Pass support.
Diffstat (limited to 'source')
-rw-r--r--source/blender/draw/engines/eevee/eevee_materials.c13
-rw-r--r--source/blender/draw/engines/eevee/eevee_private.h6
-rw-r--r--source/blender/draw/engines/eevee/eevee_render.c57
-rw-r--r--source/blender/draw/engines/eevee/eevee_subsurface.c93
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl16
-rw-r--r--source/blender/draw/intern/draw_manager.c1
6 files changed, 174 insertions, 12 deletions
diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c
index 84627e03137..8c0ba921419 100644
--- a/source/blender/draw/engines/eevee/eevee_materials.c
+++ b/source/blender/draw/engines/eevee/eevee_materials.c
@@ -1056,9 +1056,16 @@ static void material_opaque(
DRW_shgroup_uniform_texture(*shgrp, "sssTexProfile", sss_tex_profile);
}
- DRW_shgroup_stencil_mask(*shgrp, e_data.sss_count + 1);
- EEVEE_subsurface_add_pass(sldata, vedata, e_data.sss_count + 1, sss_profile);
- e_data.sss_count++;
+ /* Limit of 8 bit stencil buffer. ID 255 is refraction. */
+ if (e_data.sss_count < 254) {
+ DRW_shgroup_stencil_mask(*shgrp, e_data.sss_count + 1);
+ EEVEE_subsurface_add_pass(sldata, vedata, e_data.sss_count + 1, sss_profile);
+ e_data.sss_count++;
+ }
+ else {
+ /* TODO : display message. */
+ printf("Error: Too many different Subsurface shader in the scene.\n");
+ }
}
}
}
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
index 17d41cabe66..1c35d5e7262 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -178,6 +178,7 @@ typedef struct EEVEE_PassList {
struct DRWPass *ssr_resolve;
struct DRWPass *sss_blur_ps;
struct DRWPass *sss_resolve_ps;
+ struct DRWPass *sss_accum_ps;
struct DRWPass *color_downsample_ps;
struct DRWPass *color_downsample_cube_ps;
struct DRWPass *taa_resolve;
@@ -220,6 +221,7 @@ typedef struct EEVEE_FramebufferList {
struct GPUFrameBuffer *bloom_accum_fb[MAX_BLOOM_STEP - 1];
struct GPUFrameBuffer *sss_blur_fb;
struct GPUFrameBuffer *sss_clear_fb;
+ struct GPUFrameBuffer *sss_accum_fb;
struct GPUFrameBuffer *dof_down_fb;
struct GPUFrameBuffer *dof_scatter_far_fb;
struct GPUFrameBuffer *dof_scatter_near_fb;
@@ -249,6 +251,8 @@ typedef struct EEVEE_TextureList {
struct GPUTexture *bloom_blit; /* R16_G16_B16 */
struct GPUTexture *bloom_downsample[MAX_BLOOM_STEP]; /* R16_G16_B16 */
struct GPUTexture *bloom_upsample[MAX_BLOOM_STEP - 1]; /* R16_G16_B16 */
+ struct GPUTexture *sss_dir_accum;
+ struct GPUTexture *sss_col_accum;
struct GPUTexture *ssr_normal_input;
struct GPUTexture *ssr_specrough_input;
struct GPUTexture *ssr_hit_output;
@@ -820,10 +824,12 @@ void EEVEE_screen_raytrace_free(void);
/* eevee_subsurface.c */
int EEVEE_subsurface_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_subsurface_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_subsurface_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_subsurface_add_pass(
EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, unsigned int sss_id, struct GPUUniformBuffer *sss_profile);
void EEVEE_subsurface_data_render(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_subsurface_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_subsurface_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_subsurface_free(void);
/* eevee_motion_blur.c */
diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c
index f7ebded2408..e3d6d182053 100644
--- a/source/blender/draw/engines/eevee/eevee_render.c
+++ b/source/blender/draw/engines/eevee/eevee_render.c
@@ -160,6 +160,51 @@ static void eevee_render_result_combined(
DRW_framebuffer_read_data(rr->xof, rr->yof, rr->rectx, rr->recty, 4, 0, rp->rect);
}
+static void eevee_render_result_subsurface(
+ RenderResult *rr, const char *viewname,
+ EEVEE_Data *vedata, EEVEE_ViewLayerData *UNUSED(sldata))
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ ViewLayer *view_layer = draw_ctx->view_layer;
+
+ if ((view_layer->passflag & SCE_PASS_SUBSURFACE_COLOR) != 0) {
+ RenderLayer *rl = rr->layers.first;
+ RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_SUBSURFACE_COLOR, viewname);
+
+ IDProperty *props = BKE_view_layer_engine_evaluated_get(view_layer, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_EEVEE);
+ float render_samples = (float)BKE_collection_engine_property_value_get_int(props, "taa_render_samples");
+
+ DRW_framebuffer_bind(vedata->fbl->sss_accum_fb);
+ DRW_framebuffer_read_data(rr->xof, rr->yof, rr->rectx, rr->recty, 3, 1, rp->rect);
+
+ /* This is the accumulated color. Divide by the number of samples. */
+ for (int i = 0; i < rr->rectx * rr->recty * 3; i++) {
+ rp->rect[i] /= render_samples;
+ }
+ }
+
+ if ((view_layer->passflag & SCE_PASS_SUBSURFACE_DIRECT) != 0) {
+ RenderLayer *rl = rr->layers.first;
+ RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_SUBSURFACE_DIRECT, viewname);
+
+ IDProperty *props = BKE_view_layer_engine_evaluated_get(view_layer, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_EEVEE);
+ float render_samples = (float)BKE_collection_engine_property_value_get_int(props, "taa_render_samples");
+
+ DRW_framebuffer_bind(vedata->fbl->sss_accum_fb);
+ DRW_framebuffer_read_data(rr->xof, rr->yof, rr->rectx, rr->recty, 3, 0, rp->rect);
+
+ /* This is the accumulated color. Divide by the number of samples. */
+ for (int i = 0; i < rr->rectx * rr->recty * 3; i++) {
+ rp->rect[i] /= render_samples;
+ }
+ }
+
+ if ((view_layer->passflag & SCE_PASS_SUBSURFACE_INDIRECT) != 0) {
+ /* Do nothing as all the lighting is in the direct pass.
+ * TODO : Separate Direct from indirect lighting. */
+ }
+}
+
static void eevee_render_result_normal(
RenderResult *rr, const char *viewname,
EEVEE_Data *vedata, EEVEE_ViewLayerData *UNUSED(sldata))
@@ -253,6 +298,13 @@ void EEVEE_render_draw(EEVEE_Data *vedata, struct RenderEngine *engine, struct D
EEVEE_lights_cache_finish(sldata);
EEVEE_lightprobes_cache_finish(sldata, vedata);
+ if ((view_layer->passflag & (SCE_PASS_SUBSURFACE_COLOR |
+ SCE_PASS_SUBSURFACE_DIRECT |
+ SCE_PASS_SUBSURFACE_INDIRECT)) != 0)
+ {
+ EEVEE_subsurface_output_init(sldata, vedata);
+ }
+
/* Init render result. */
const char *viewname = NULL;
const float *render_size = DRW_viewport_size_get();
@@ -304,13 +356,12 @@ void EEVEE_render_draw(EEVEE_Data *vedata, struct RenderEngine *engine, struct D
/* Effects pre-transparency */
EEVEE_subsurface_compute(sldata, vedata);
EEVEE_reflection_compute(sldata, vedata);
- EEVEE_occlusion_draw_debug(sldata, vedata);
- DRW_draw_pass(psl->probe_display);
EEVEE_refraction_compute(sldata, vedata);
/* Opaque refraction */
DRW_draw_pass(psl->refract_depth_pass);
DRW_draw_pass(psl->refract_depth_pass_cull);
DRW_draw_pass(psl->refract_pass);
+ EEVEE_subsurface_output_accumulate(sldata, vedata);
/* Result NORMAL */
eevee_render_result_normal(rr, viewname, vedata, sldata);
/* Volumetrics Resolve Opaque */
@@ -324,8 +375,8 @@ void EEVEE_render_draw(EEVEE_Data *vedata, struct RenderEngine *engine, struct D
EEVEE_draw_effects(sldata, vedata);
}
- /* Result Combined */
eevee_render_result_combined(rr, viewname, vedata, sldata);
+ eevee_render_result_subsurface(rr, viewname, vedata, sldata);
RE_engine_end_result(engine, rr, false, false, false);
}
diff --git a/source/blender/draw/engines/eevee/eevee_subsurface.c b/source/blender/draw/engines/eevee/eevee_subsurface.c
index e93e9574acd..4ca1f0f42a1 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[3];
+ struct GPUShader *sss_sh[4];
} e_data = {NULL}; /* Engine data */
extern char datatoc_common_uniforms_lib_glsl[];
@@ -49,6 +49,9 @@ static void eevee_create_shader_subsurface(void)
e_data.sss_sh[1] = DRW_shader_create_fullscreen(frag_str, "#define SECOND_PASS\n");
e_data.sss_sh[2] = DRW_shader_create_fullscreen(frag_str, "#define SECOND_PASS\n"
"#define USE_SEP_ALBEDO\n");
+ e_data.sss_sh[3] = DRW_shader_create_fullscreen(frag_str, "#define SECOND_PASS\n"
+ "#define USE_SEP_ALBEDO\n"
+ "#define RESULT_ACCUM\n");
MEM_freeN(frag_str);
}
@@ -71,6 +74,11 @@ int EEVEE_subsurface_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
effects->sss_separate_albedo = BKE_collection_engine_property_value_get_bool(props, "sss_separate_albedo");
common_data->sss_jitter_threshold = BKE_collection_engine_property_value_get_float(props, "sss_jitter_threshold");
+ /* Force separate albedo for final render */
+ if (DRW_state_is_image_render()) {
+ effects->sss_separate_albedo = true;
+ }
+
/* Shaders */
if (!e_data.sss_sh[0]) {
eevee_create_shader_subsurface();
@@ -109,6 +117,47 @@ int EEVEE_subsurface_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
return 0;
}
+static void set_shgrp_stencil(void *UNUSED(userData), DRWShadingGroup *shgrp)
+{
+ DRW_shgroup_stencil_mask(shgrp, 255);
+}
+
+void EEVEE_subsurface_output_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+{
+ EEVEE_FramebufferList *fbl = vedata->fbl;
+ EEVEE_TextureList *txl = vedata->txl;
+ const float *viewport_size = DRW_viewport_size_get();
+
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ ViewLayer *view_layer = draw_ctx->view_layer;
+ IDProperty *props = BKE_view_layer_engine_evaluated_get(view_layer, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_EEVEE);
+
+ if (BKE_collection_engine_property_value_get_bool(props, "sss_enable")) {
+ float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+
+ DRWFboTexture tex_data[2] = {{&txl->sss_dir_accum, DRW_TEX_RGBA_16, 0},
+ {&txl->sss_col_accum, DRW_TEX_RGBA_16, 0}};
+ DRW_framebuffer_init(&fbl->sss_accum_fb, &draw_engine_eevee_type, (int)viewport_size[0], (int)viewport_size[1],
+ tex_data, 2);
+
+ /* Clear texture. */
+ DRW_framebuffer_bind(fbl->sss_accum_fb);
+ DRW_framebuffer_clear(true, false, false, clear, 0.0f);
+
+ /* Make the opaque refraction pass mask the sss. */
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES |
+ DRW_STATE_WIRE | DRW_STATE_WRITE_STENCIL;
+ DRW_pass_state_set(vedata->psl->refract_pass, state);
+ DRW_pass_foreach_shgroup(vedata->psl->refract_pass, &set_shgrp_stencil, NULL);
+ }
+ else {
+ /* Cleanup to release memory */
+ DRW_TEXTURE_FREE_SAFE(txl->sss_dir_accum);
+ DRW_TEXTURE_FREE_SAFE(txl->sss_col_accum);
+ DRW_FRAMEBUFFER_FREE_SAFE(fbl->sss_accum_fb);
+ }
+}
+
void EEVEE_subsurface_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
{
EEVEE_PassList *psl = vedata->psl;
@@ -121,7 +170,9 @@ void EEVEE_subsurface_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
*/
psl->sss_blur_ps = DRW_pass_create("Blur Horiz", DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_EQUAL);
- psl->sss_resolve_ps = DRW_pass_create("Blur Vert", DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE | DRW_STATE_STENCIL_EQUAL);
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE | DRW_STATE_STENCIL_EQUAL;
+ psl->sss_resolve_ps = DRW_pass_create("Blur Vert", state);
+ psl->sss_accum_ps = DRW_pass_create("Resolve Accum", state);
}
}
@@ -157,6 +208,18 @@ void EEVEE_subsurface_add_pass(
if (effects->sss_separate_albedo) {
DRW_shgroup_uniform_buffer(grp, "sssAlbedo", &txl->sss_albedo);
}
+
+ if (DRW_state_is_image_render()) {
+ grp = DRW_shgroup_create(e_data.sss_sh[3], psl->sss_accum_ps);
+ DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
+ DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth);
+ DRW_shgroup_uniform_buffer(grp, "sssData", &txl->sss_blur);
+ DRW_shgroup_uniform_buffer(grp, "sssAlbedo", &txl->sss_albedo);
+ DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+ DRW_shgroup_stencil_mask(grp, sss_id);
+ DRW_shgroup_call_add(grp, quad, NULL);
+ }
}
void EEVEE_subsurface_data_render(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
@@ -271,9 +334,35 @@ void EEVEE_subsurface_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v
}
}
+void EEVEE_subsurface_output_accumulate(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+{
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_FramebufferList *fbl = vedata->fbl;
+ EEVEE_TextureList *txl = vedata->txl;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_EffectsInfo *effects = stl->effects;
+
+ if (((effects->enabled_effects & EFFECT_SSS) != 0) && (fbl->sss_accum_fb != NULL)) {
+ /* Copy stencil channel, could be avoided (see EEVEE_subsurface_init) */
+ DRW_framebuffer_blit(fbl->main, fbl->sss_blur_fb, false, true);
+
+ /* Only do vertical pass + Resolve */
+ DRW_framebuffer_texture_detach(txl->sss_stencil);
+ DRW_framebuffer_texture_attach(fbl->sss_accum_fb, txl->sss_stencil, 0, 0);
+ DRW_framebuffer_bind(fbl->sss_accum_fb);
+ DRW_draw_pass(psl->sss_accum_ps);
+
+ /* Restore */
+ DRW_framebuffer_texture_detach(txl->sss_stencil);
+ DRW_framebuffer_texture_attach(fbl->sss_blur_fb, txl->sss_stencil, 0, 0);
+ DRW_framebuffer_bind(fbl->main);
+ }
+}
+
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]);
+ DRW_SHADER_FREE_SAFE(e_data.sss_sh[3]);
}
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 184eac54c26..d9e12bcc4bd 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl
@@ -18,7 +18,10 @@ uniform sampler2DArray utilTex;
#define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0)
#endif /* UTIL_TEX */
-out vec4 FragColor;
+layout(location = 0) out vec4 FragColor;
+#ifdef RESULT_ACCUM
+layout(location = 1) out vec4 sssColor;
+#endif
uniform mat4 ProjectionMatrix;
@@ -84,10 +87,15 @@ void main(void)
#ifdef FIRST_PASS
FragColor = vec4(accum, sss_data.a);
#else /* SECOND_PASS */
- #ifdef USE_SEP_ALBEDO
+# ifdef USE_SEP_ALBEDO
+# ifdef RESULT_ACCUM
+ FragColor = vec4(accum, 1.0);
+ sssColor = texture(sssAlbedo, uvs);
+# else
FragColor = vec4(accum * texture(sssAlbedo, uvs).rgb, 1.0);
- #else
+# endif
+# else
FragColor = vec4(accum, 1.0);
- #endif
+# endif
#endif
}
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index b9873ff3926..0e8861b48bb 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -1105,6 +1105,7 @@ void DRW_shgroup_state_disable(DRWShadingGroup *shgroup, DRWState state)
void DRW_shgroup_stencil_mask(DRWShadingGroup *shgroup, unsigned int mask)
{
+ BLI_assert(mask <= 255);
shgroup->stencil_mask = mask;
}