diff options
Diffstat (limited to 'source/blender/draw/engines/eevee')
5 files changed, 333 insertions, 192 deletions
diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c index a1096390bce..173b7ff57a1 100644 --- a/source/blender/draw/engines/eevee/eevee_engine.c +++ b/source/blender/draw/engines/eevee/eevee_engine.c @@ -483,6 +483,7 @@ static void eevee_engine_free(void) EEVEE_screen_raytrace_free(); EEVEE_subsurface_free(); EEVEE_volumes_free(); + EEVEE_renderpasses_free(); } static const DrawEngineDataSize eevee_data_size = DRW_VIEWPORT_DATA_SIZE(EEVEE_Data); diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index 41e38fd8437..b49328d90ab 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -271,6 +271,7 @@ typedef struct EEVEE_PassList { struct DRWPass *update_noise_pass; struct DRWPass *lookdev_glossy_pass; struct DRWPass *lookdev_diffuse_pass; + struct DRWPass *renderpass_pass; } EEVEE_PassList; typedef struct EEVEE_FramebufferList { @@ -295,6 +296,7 @@ typedef struct EEVEE_FramebufferList { struct GPUFrameBuffer *screen_tracing_fb; struct GPUFrameBuffer *refract_fb; struct GPUFrameBuffer *mist_accum_fb; + struct GPUFrameBuffer *renderpass_fb; struct GPUFrameBuffer *ao_accum_fb; struct GPUFrameBuffer *velocity_resolve_fb; @@ -341,6 +343,8 @@ typedef struct EEVEE_TextureList { struct GPUTexture *maxzbuffer; + struct GPUTexture *renderpass; + struct GPUTexture *color; /* R16_G16_B16 */ struct GPUTexture *color_double_buffer; struct GPUTexture *depth_double_buffer; @@ -799,6 +803,10 @@ typedef struct EEVEE_PrivateData { float studiolight_glossy_clamp; float studiolight_filter_quality; + /* Renderpasses */ + /* Bitmask containing the active render_passes */ + eScenePassType render_passes; + /** For rendering shadows. */ struct DRWView *cube_views[6]; /** For rendering probes. */ @@ -1039,6 +1047,16 @@ void EEVEE_mist_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_mist_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_mist_free(void); +/* eevee_renderpasses.c */ +void EEVEE_renderpasses_init(EEVEE_Data *vedata); +void EEVEE_renderpasses_output_init(EEVEE_ViewLayerData *sldata, + EEVEE_Data *vedata, + uint tot_samples); +void EEVEE_renderpasses_postprocess(EEVEE_ViewLayerData *sldata, + EEVEE_Data *vedata, + eScenePassType renderpass_type); +void EEVEE_renderpasses_free(void); + /* eevee_temporal_sampling.c */ void EEVEE_temporal_sampling_reset(EEVEE_Data *vedata); int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c index ee1dc8a0208..9a7d170c9ea 100644 --- a/source/blender/draw/engines/eevee/eevee_render.c +++ b/source/blender/draw/engines/eevee/eevee_render.c @@ -130,7 +130,9 @@ void EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph * DRW_view_default_set(view); DRW_view_set_active(view); - /* EEVEE_effects_init needs to go first for TAA */ + /* `EEVEE_renderpasses_init` will set the active render passes used by `EEVEE_effects_init`. + * `EEVEE_effects_init` needs to go second for TAA. */ + EEVEE_renderpasses_init(vedata); EEVEE_effects_init(sldata, vedata, ob_camera_eval, false); EEVEE_materials_init(sldata, stl, fbl); EEVEE_shadows_init(sldata); @@ -202,79 +204,60 @@ void EEVEE_render_cache(void *vedata, } } -static void eevee_render_result_combined(RenderLayer *rl, - const char *viewname, - const rcti *rect, - EEVEE_Data *vedata, - EEVEE_ViewLayerData *UNUSED(sldata)) +static void eevee_render_color_result(RenderLayer *rl, + const char *viewname, + const rcti *rect, + const char *render_pass_name, + int num_channels, + GPUFrameBuffer *framebuffer, + EEVEE_Data *vedata) { - RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_COMBINED, viewname); - - GPU_framebuffer_bind(vedata->stl->effects->final_fb); - GPU_framebuffer_read_color(vedata->stl->effects->final_fb, + RenderPass *rp = RE_pass_find_by_name(rl, render_pass_name, viewname); + GPU_framebuffer_bind(framebuffer); + GPU_framebuffer_read_color(framebuffer, vedata->stl->g_data->overscan_pixels + rect->xmin, vedata->stl->g_data->overscan_pixels + rect->ymin, BLI_rcti_size_x(rect), BLI_rcti_size_y(rect), - 4, + num_channels, 0, rp->rect); } +static void eevee_render_result_combined(RenderLayer *rl, + const char *viewname, + const rcti *rect, + EEVEE_Data *vedata, + EEVEE_ViewLayerData *UNUSED(sldata)) +{ + eevee_render_color_result( + rl, viewname, rect, RE_PASSNAME_COMBINED, 4, vedata->stl->effects->final_fb, vedata); +} + static void eevee_render_result_subsurface(RenderLayer *rl, const char *viewname, const rcti *rect, EEVEE_Data *vedata, - EEVEE_ViewLayerData *UNUSED(sldata), - int render_samples) + EEVEE_ViewLayerData *sldata) { - const DRWContextState *draw_ctx = DRW_context_state_get(); - ViewLayer *view_layer = draw_ctx->view_layer; - if (vedata->fbl->sss_accum_fb == NULL) { /* SSS is not enabled. */ return; } - if ((view_layer->passflag & SCE_PASS_SUBSURFACE_COLOR) != 0) { - RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_SUBSURFACE_COLOR, viewname); - - GPU_framebuffer_bind(vedata->fbl->sss_accum_fb); - GPU_framebuffer_read_color(vedata->fbl->sss_accum_fb, - vedata->stl->g_data->overscan_pixels + rect->xmin, - vedata->stl->g_data->overscan_pixels + rect->ymin, - BLI_rcti_size_x(rect), - BLI_rcti_size_y(rect), - 3, - 1, - rp->rect); - - /* This is the accumulated color. Divide by the number of samples. */ - for (int i = 0; i < rp->rectx * rp->recty * 3; i++) { - rp->rect[i] /= (float)render_samples; - } + if ((vedata->stl->g_data->render_passes & SCE_PASS_SUBSURFACE_COLOR) != 0) { + EEVEE_renderpasses_postprocess(sldata, vedata, SCE_PASS_SUBSURFACE_COLOR); + eevee_render_color_result( + rl, viewname, rect, RE_PASSNAME_SUBSURFACE_COLOR, 3, vedata->fbl->renderpass_fb, vedata); } - if ((view_layer->passflag & SCE_PASS_SUBSURFACE_DIRECT) != 0) { - RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_SUBSURFACE_DIRECT, viewname); - - GPU_framebuffer_bind(vedata->fbl->sss_accum_fb); - GPU_framebuffer_read_color(vedata->fbl->sss_accum_fb, - vedata->stl->g_data->overscan_pixels + rect->xmin, - vedata->stl->g_data->overscan_pixels + rect->ymin, - BLI_rcti_size_x(rect), - BLI_rcti_size_y(rect), - 3, - 0, - rp->rect); - - /* This is the accumulated color. Divide by the number of samples. */ - for (int i = 0; i < rp->rectx * rp->recty * 3; i++) { - rp->rect[i] /= (float)render_samples; - } + if ((vedata->stl->g_data->render_passes & SCE_PASS_SUBSURFACE_DIRECT) != 0) { + EEVEE_renderpasses_postprocess(sldata, vedata, SCE_PASS_SUBSURFACE_DIRECT); + eevee_render_color_result( + rl, viewname, rect, RE_PASSNAME_SUBSURFACE_DIRECT, 3, vedata->fbl->renderpass_fb, vedata); } - if ((view_layer->passflag & SCE_PASS_SUBSURFACE_INDIRECT) != 0) { + if ((vedata->stl->g_data->render_passes & SCE_PASS_SUBSURFACE_INDIRECT) != 0) { /* Do nothing as all the lighting is in the direct pass. * TODO : Separate Direct from indirect lighting. */ } @@ -284,54 +267,19 @@ static void eevee_render_result_normal(RenderLayer *rl, const char *viewname, const rcti *rect, EEVEE_Data *vedata, - EEVEE_ViewLayerData *UNUSED(sldata)) + EEVEE_ViewLayerData *sldata) { - const DRWContextState *draw_ctx = DRW_context_state_get(); - ViewLayer *view_layer = draw_ctx->view_layer; - EEVEE_StorageList *stl = vedata->stl; - EEVEE_PrivateData *g_data = stl->g_data; + const int current_sample = vedata->stl->effects->taa_current_sample; /* Only read the center texel. */ - if (stl->effects->taa_current_sample > 1) { + if (current_sample > 1) { return; } - if ((view_layer->passflag & SCE_PASS_NORMAL) != 0) { - RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_NORMAL, viewname); - - GPU_framebuffer_bind(vedata->fbl->main_fb); - GPU_framebuffer_read_color(vedata->fbl->main_fb, - g_data->overscan_pixels + rect->xmin, - g_data->overscan_pixels + rect->ymin, - BLI_rcti_size_x(rect), - BLI_rcti_size_y(rect), - 3, - 1, - rp->rect); - - float viewinv[4][4]; - DRW_view_viewmat_get(NULL, viewinv, true); - - /* Convert Eevee encoded normals to Blender normals. */ - for (int i = 0; i < rp->rectx * rp->recty * 3; i += 3) { - if (rp->rect[i] == 0.0f && rp->rect[i + 1] == 0.0f) { - /* If normal is not correct then do not produce NANs. */ - continue; - } - - float fenc[2]; - fenc[0] = rp->rect[i + 0] * 4.0f - 2.0f; - fenc[1] = rp->rect[i + 1] * 4.0f - 2.0f; - - float f = dot_v2v2(fenc, fenc); - float g = sqrtf(1.0f - f / 4.0f); - - rp->rect[i + 0] = fenc[0] * g; - rp->rect[i + 1] = fenc[1] * g; - rp->rect[i + 2] = 1.0f - f / 2.0f; - - mul_mat3_m4_v3(viewinv, &rp->rect[i]); - } + if ((vedata->stl->g_data->render_passes & SCE_PASS_NORMAL) != 0) { + EEVEE_renderpasses_postprocess(sldata, vedata, SCE_PASS_NORMAL); + eevee_render_color_result( + rl, viewname, rect, RE_PASSNAME_NORMAL, 3, vedata->fbl->renderpass_fb, vedata); } } @@ -341,49 +289,17 @@ static void eevee_render_result_z(RenderLayer *rl, EEVEE_Data *vedata, EEVEE_ViewLayerData *sldata) { - const DRWContextState *draw_ctx = DRW_context_state_get(); - ViewLayer *view_layer = draw_ctx->view_layer; - EEVEE_CommonUniformBuffer *common_data = &sldata->common_data; - EEVEE_StorageList *stl = vedata->stl; - EEVEE_PrivateData *g_data = stl->g_data; + const int current_sample = vedata->stl->effects->taa_current_sample; /* Only read the center texel. */ - if (stl->effects->taa_current_sample > 1) { + if (current_sample > 1) { return; } - if ((view_layer->passflag & SCE_PASS_Z) != 0) { - RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_Z, viewname); - - GPU_framebuffer_bind(vedata->fbl->main_fb); - GPU_framebuffer_read_depth(vedata->fbl->main_fb, - g_data->overscan_pixels + rect->xmin, - g_data->overscan_pixels + rect->ymin, - BLI_rcti_size_x(rect), - BLI_rcti_size_y(rect), - rp->rect); - - bool is_persp = DRW_view_is_persp_get(NULL); - - float winmat[4][4]; - DRW_view_winmat_get(NULL, winmat, false); - - /* Convert ogl depth [0..1] to view Z [near..far] */ - for (int i = 0; i < rp->rectx * rp->recty; i++) { - if (rp->rect[i] == 1.0f) { - rp->rect[i] = 1e10f; /* Background */ - } - else { - if (is_persp) { - rp->rect[i] = rp->rect[i] * 2.0f - 1.0f; - rp->rect[i] = winmat[3][2] / (rp->rect[i] + winmat[2][2]); - } - else { - rp->rect[i] = -common_data->view_vecs[0][2] + - rp->rect[i] * -common_data->view_vecs[1][2]; - } - } - } + if ((vedata->stl->g_data->render_passes & SCE_PASS_Z) != 0) { + EEVEE_renderpasses_postprocess(sldata, vedata, SCE_PASS_Z); + eevee_render_color_result( + rl, viewname, rect, RE_PASSNAME_Z, 1, vedata->fbl->renderpass_fb, vedata); } } @@ -391,29 +307,12 @@ static void eevee_render_result_mist(RenderLayer *rl, const char *viewname, const rcti *rect, EEVEE_Data *vedata, - EEVEE_ViewLayerData *UNUSED(sldata), - int render_samples) + EEVEE_ViewLayerData *sldata) { - const DRWContextState *draw_ctx = DRW_context_state_get(); - ViewLayer *view_layer = draw_ctx->view_layer; - - if ((view_layer->passflag & SCE_PASS_MIST) != 0) { - RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_MIST, viewname); - - GPU_framebuffer_bind(vedata->fbl->mist_accum_fb); - GPU_framebuffer_read_color(vedata->fbl->mist_accum_fb, - vedata->stl->g_data->overscan_pixels + rect->xmin, - vedata->stl->g_data->overscan_pixels + rect->ymin, - BLI_rcti_size_x(rect), - BLI_rcti_size_y(rect), - 1, - 0, - rp->rect); - - /* This is the accumulated color. Divide by the number of samples. */ - for (int i = 0; i < rp->rectx * rp->recty; i++) { - rp->rect[i] /= (float)render_samples; - } + if ((vedata->stl->g_data->render_passes & SCE_PASS_MIST) != 0) { + EEVEE_renderpasses_postprocess(sldata, vedata, SCE_PASS_MIST); + eevee_render_color_result( + rl, viewname, rect, RE_PASSNAME_MIST, 1, vedata->fbl->renderpass_fb, vedata); } } @@ -421,35 +320,17 @@ static void eevee_render_result_occlusion(RenderLayer *rl, const char *viewname, const rcti *rect, EEVEE_Data *vedata, - EEVEE_ViewLayerData *UNUSED(sldata), - int render_samples) + EEVEE_ViewLayerData *sldata) { - const DRWContextState *draw_ctx = DRW_context_state_get(); - ViewLayer *view_layer = draw_ctx->view_layer; - if (vedata->fbl->ao_accum_fb == NULL) { /* AO is not enabled. */ return; } - if ((view_layer->passflag & SCE_PASS_AO) != 0) { - RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_AO, viewname); - - GPU_framebuffer_bind(vedata->fbl->ao_accum_fb); - GPU_framebuffer_read_color(vedata->fbl->ao_accum_fb, - vedata->stl->g_data->overscan_pixels + rect->xmin, - vedata->stl->g_data->overscan_pixels + rect->ymin, - BLI_rcti_size_x(rect), - BLI_rcti_size_y(rect), - 3, - 0, - rp->rect); - - /* This is the accumulated color. Divide by the number of samples. */ - for (int i = 0; i < rp->rectx * rp->recty * 3; i += 3) { - rp->rect[i] = rp->rect[i + 1] = rp->rect[i + 2] = min_ff( - 1.0f, rp->rect[i] / (float)render_samples); - } + if ((vedata->stl->g_data->render_passes & SCE_PASS_AO) != 0) { + EEVEE_renderpasses_postprocess(sldata, vedata, SCE_PASS_AO); + eevee_render_color_result( + rl, viewname, rect, RE_PASSNAME_AO, 3, vedata->fbl->renderpass_fb, vedata); } } @@ -488,7 +369,6 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl { const DRWContextState *draw_ctx = DRW_context_state_get(); const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); - ViewLayer *view_layer = draw_ctx->view_layer; const char *viewname = RE_GetActiveRenderView(engine->re); EEVEE_PassList *psl = vedata->psl; EEVEE_StorageList *stl = vedata->stl; @@ -525,18 +405,7 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl tot_sample += 1; } - if ((view_layer->passflag & (SCE_PASS_SUBSURFACE_COLOR | SCE_PASS_SUBSURFACE_DIRECT | - SCE_PASS_SUBSURFACE_INDIRECT)) != 0) { - EEVEE_subsurface_output_init(sldata, vedata, tot_sample); - } - - if ((view_layer->passflag & SCE_PASS_MIST) != 0) { - EEVEE_mist_output_init(sldata, vedata); - } - - if ((view_layer->passflag & SCE_PASS_AO) != 0) { - EEVEE_occlusion_output_init(sldata, vedata, tot_sample); - } + EEVEE_renderpasses_output_init(sldata, vedata, tot_sample); if (RE_engine_test_break(engine)) { return; @@ -644,9 +513,9 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl } eevee_render_result_combined(rl, viewname, rect, vedata, sldata); - eevee_render_result_subsurface(rl, viewname, rect, vedata, sldata, render_samples); - eevee_render_result_mist(rl, viewname, rect, vedata, sldata, render_samples); - eevee_render_result_occlusion(rl, viewname, rect, vedata, sldata, render_samples); + eevee_render_result_subsurface(rl, viewname, rect, vedata, sldata); + eevee_render_result_mist(rl, viewname, rect, vedata, sldata); + eevee_render_result_occlusion(rl, viewname, rect, vedata, sldata); /* Restore original viewport size. */ DRW_render_viewport_size_set((int[2]){g_data->size_orig[0], g_data->size_orig[1]}); diff --git a/source/blender/draw/engines/eevee/eevee_renderpasses.c b/source/blender/draw/engines/eevee/eevee_renderpasses.c new file mode 100644 index 00000000000..17f1f8c96d6 --- /dev/null +++ b/source/blender/draw/engines/eevee/eevee_renderpasses.c @@ -0,0 +1,190 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2019, Blender Foundation. + */ + +/** \file + * \ingroup draw_engine + */ + +#include "DRW_engine.h" +#include "DRW_render.h" + +#include "BLI_string_utils.h" + +#include "eevee_private.h" + +extern char datatoc_common_view_lib_glsl[]; +extern char datatoc_common_uniforms_lib_glsl[]; +extern char datatoc_bsdf_common_lib_glsl[]; +extern char datatoc_renderpass_postprocess_frag_glsl[]; + +static struct { + struct GPUShader *postprocess_sh; +} e_data = {NULL}; /* Engine data */ + +/* bitmask containing all renderpasses that need post-processing */ +#define EEVEE_RENDERPASSES_WITH_POST_PROCESSING \ + (SCE_PASS_Z | SCE_PASS_MIST | SCE_PASS_NORMAL | SCE_PASS_AO | SCE_PASS_SUBSURFACE_COLOR | \ + SCE_PASS_SUBSURFACE_DIRECT) + +#define EEVEE_RENDERPASSES_SUBSURFACE \ + (SCE_PASS_SUBSURFACE_COLOR | SCE_PASS_SUBSURFACE_DIRECT | SCE_PASS_SUBSURFACE_INDIRECT) + +#define EEVEE_RENDERPASSES_ALL (EEVEE_RENDERPASSES_WITH_POST_PROCESSING | SCE_PASS_COMBINED) + +void EEVEE_renderpasses_init(EEVEE_Data *vedata) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + EEVEE_StorageList *stl = vedata->stl; + EEVEE_PrivateData *g_data = stl->g_data; + ViewLayer *view_layer = draw_ctx->view_layer; + + g_data->render_passes = (view_layer->passflag & EEVEE_RENDERPASSES_ALL) | SCE_PASS_COMBINED; +} + +void EEVEE_renderpasses_output_init(EEVEE_ViewLayerData *sldata, + EEVEE_Data *vedata, + uint tot_samples) +{ + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_TextureList *txl = vedata->txl; + EEVEE_PassList *psl = vedata->psl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_PrivateData *g_data = stl->g_data; + + const bool needs_post_processing = (g_data->render_passes & + EEVEE_RENDERPASSES_WITH_POST_PROCESSING) > 0; + if (needs_post_processing) { + if (e_data.postprocess_sh == NULL) { + char *frag_str = BLI_string_joinN(datatoc_common_view_lib_glsl, + datatoc_common_uniforms_lib_glsl, + datatoc_bsdf_common_lib_glsl, + datatoc_renderpass_postprocess_frag_glsl); + e_data.postprocess_sh = DRW_shader_create_fullscreen(frag_str, NULL); + MEM_freeN(frag_str); + } + + /* Create FrameBuffer. */ + + /* Should be enough to store the data needs for a single pass. + * Some passes will use less, but it is only relevant for final renderings and + * when renderpasses other than `SCE_PASS_COMBINED` are requested */ + DRW_texture_ensure_fullscreen_2d(&txl->renderpass, GPU_RGBA16F, 0); + GPU_framebuffer_ensure_config(&fbl->renderpass_fb, + {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->renderpass)}); + + if ((g_data->render_passes & EEVEE_RENDERPASSES_SUBSURFACE) != 0) { + EEVEE_subsurface_output_init(sldata, vedata, tot_samples); + } + + if ((g_data->render_passes & SCE_PASS_MIST) != 0) { + EEVEE_mist_output_init(sldata, vedata); + } + + if ((g_data->render_passes & SCE_PASS_AO) != 0) { + EEVEE_occlusion_output_init(sldata, vedata, tot_samples); + } + + /* Create Pass. */ + DRW_PASS_CREATE(psl->renderpass_pass, DRW_STATE_WRITE_COLOR); + } + else { + /* Free unneeded memory */ + DRW_TEXTURE_FREE_SAFE(txl->renderpass); + GPU_FRAMEBUFFER_FREE_SAFE(fbl->renderpass_fb); + psl->renderpass_pass = NULL; + } +} + +/* Postprocess data to construct a specific renderpass + * + * This method will create a shading group to perform the post-processing for the given + * `renderpass_type`. The post-processing will be done and the result will be stored in the + * `vedata->txl->renderpass` texture. + * + * Only invoke this function for passes that need post-processing. + * + * After invoking this function the active framebuffer is set to `vedata->fbl->renderpass_fb`. */ +void EEVEE_renderpasses_postprocess(EEVEE_ViewLayerData *sldata, + EEVEE_Data *vedata, + eScenePassType renderpass_type) +{ + EEVEE_PassList *psl = vedata->psl; + EEVEE_TextureList *txl = vedata->txl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_EffectsInfo *effects = stl->effects; + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + + const int current_sample = effects->taa_current_sample; + + DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.postprocess_sh, psl->renderpass_pass); + DRW_shgroup_uniform_int_copy(shgrp, "renderpassType", renderpass_type); + + switch (renderpass_type) { + case SCE_PASS_Z: { + DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_texture_ref(shgrp, "depthBuffer", &dtxl->depth); + break; + } + + case SCE_PASS_AO: { + DRW_shgroup_uniform_texture_ref(shgrp, "inputBuffer", &txl->ao_accum); + DRW_shgroup_uniform_int_copy(shgrp, "currentSample", current_sample); + break; + } + + case SCE_PASS_NORMAL: { + DRW_shgroup_uniform_texture_ref(shgrp, "inputBuffer", &effects->ssr_normal_input); + break; + } + + case SCE_PASS_MIST: { + DRW_shgroup_uniform_texture_ref(shgrp, "inputBuffer", &txl->mist_accum); + DRW_shgroup_uniform_int_copy(shgrp, "currentSample", current_sample); + break; + } + + case SCE_PASS_SUBSURFACE_DIRECT: { + DRW_shgroup_uniform_texture_ref(shgrp, "inputBuffer", &txl->sss_dir_accum); + DRW_shgroup_uniform_int_copy(shgrp, "currentSample", current_sample); + break; + } + + case SCE_PASS_SUBSURFACE_COLOR: { + DRW_shgroup_uniform_texture_ref(shgrp, "inputBuffer", &txl->sss_col_accum); + DRW_shgroup_uniform_int_copy(shgrp, "currentSample", current_sample); + break; + } + + default: { + break; + } + } + + DRW_shgroup_call(shgrp, DRW_cache_fullscreen_quad_get(), NULL); + + /* only draw the shading group that has been added. This function can be called multiple times + * and the pass still hold the previous shading groups.*/ + GPU_framebuffer_bind(fbl->renderpass_fb); + DRW_draw_pass_subset(psl->renderpass_pass, shgrp, shgrp); +} + +void EEVEE_renderpasses_free(void) +{ + DRW_SHADER_FREE_SAFE(e_data.postprocess_sh); +} diff --git a/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl b/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl new file mode 100644 index 00000000000..8a543f13fbc --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl @@ -0,0 +1,63 @@ +#define SCE_PASS_Z (1 << 1) +#define SCE_PASS_AO (1 << 6) +#define SCE_PASS_NORMAL (1 << 8) +#define SCE_PASS_MIST (1 << 14) +#define SCE_PASS_SUBSURFACE_DIRECT (1 << 28) +#define SCE_PASS_SUBSURFACE_COLOR (1 << 30) + +#define ACCUMULATED_COLOR_PASSES (SCE_PASS_SUBSURFACE_DIRECT | SCE_PASS_SUBSURFACE_COLOR) +#define ACCUMULATED_VALUE_PASSES (SCE_PASS_MIST) +uniform int renderpassType; +uniform int currentSample; +uniform sampler2D inputBuffer; + +out vec4 fragColor; + +void main() +{ + ivec2 texel = ivec2(gl_FragCoord.xy); + + if (renderpassType == SCE_PASS_Z) { + float depth = texelFetch(depthBuffer, texel, 0).r; + if (depth == 1.0f) { + depth = 1e10; + } + else { + depth = -get_view_z_from_depth(depth); + } + fragColor.r = depth; + } + + else if (renderpassType == SCE_PASS_AO) { + float ao_accum = texelFetch(inputBuffer, texel, 0).r; + fragColor = vec4(vec3(min(1.0, ao_accum / currentSample)), 1.0); + } + + else if (renderpassType == SCE_PASS_NORMAL) { + vec2 encoded_normal = texelFetch(inputBuffer, texel, 0).rg; + /* decode the normals only when they are valid. otherwise the result buffer will be filled with + * NaN's */ + if (any(notEqual(encoded_normal, vec2(0.0)))) { + vec3 decoded_normal = normal_decode(texelFetch(inputBuffer, texel, 0).rg, vec3(0.0)); + vec3 world_normal = mat3(ViewMatrixInverse) * decoded_normal; + fragColor = vec4(world_normal, 0.0); + } + else { + fragColor = vec4(0.0); + } + } + + else if ((renderpassType & ACCUMULATED_VALUE_PASSES) != 0) { + float accumulated_value = texelFetch(inputBuffer, texel, 0).r; + fragColor.r = accumulated_value / currentSample; + } + + else if ((renderpassType & ACCUMULATED_COLOR_PASSES) != 0) { + vec3 accumulated_color = texelFetch(inputBuffer, texel, 0).rgb; + fragColor.rgb = accumulated_color / currentSample; + } + + else { + fragColor = vec4(1.0, 0.0, 1.0, 1.0); + } +}
\ No newline at end of file |