diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2019-12-02 03:40:58 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2019-12-02 03:40:58 +0300 |
commit | a35c635edb3db548e11555024ec3a384f93ce352 (patch) | |
tree | ae0c0c9435c2e7daed4cbd916e0be90df7898b51 /source/blender/draw/engines/eevee | |
parent | 7164e63fefcfa26caf387a2ad04a8c51b533c32b (diff) | |
parent | f1ac64921b49eaea8658d144754a1a532198c720 (diff) |
Merge branch 'master' into tmp-overlay-enginetmp-overlay-engine
# Conflicts:
# source/blender/draw/modes/paint_texture_mode.c
Diffstat (limited to 'source/blender/draw/engines/eevee')
10 files changed, 497 insertions, 229 deletions
diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c index d59d1f56e92..824ea69ea73 100644 --- a/source/blender/draw/engines/eevee/eevee_effects.c +++ b/source/blender/draw/engines/eevee/eevee_effects.c @@ -136,8 +136,6 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_TextureList *txl = vedata->txl; EEVEE_EffectsInfo *effects; DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); - const DRWContextState *draw_ctx = DRW_context_state_get(); - ViewLayer *view_layer = draw_ctx->view_layer; const float *viewport_size = DRW_viewport_size_get(); int size_fs[2] = {(int)viewport_size[0], (int)viewport_size[1]}; @@ -172,7 +170,7 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_subsurface_init(sldata, vedata); /* Force normal buffer creation. */ - if (DRW_state_is_image_render() && !minimal && (view_layer->passflag & SCE_PASS_NORMAL) != 0) { + if (!minimal && (stl->g_data->render_passes & SCE_PASS_NORMAL) != 0) { effects->enabled_effects |= EFFECT_NORMAL_BUFFER; } diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c index a1096390bce..603a4787dba 100644 --- a/source/blender/draw/engines/eevee/eevee_engine.c +++ b/source/blender/draw/engines/eevee/eevee_engine.c @@ -27,6 +27,8 @@ #include "BKE_object.h" #include "BKE_global.h" /* for G.debug_value */ +#include "DEG_depsgraph_query.h" + #include "DNA_world_types.h" #include "eevee_private.h" @@ -81,7 +83,9 @@ static void eevee_engine_init(void *ved) &sldata->common_data); } - /* 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, camera, false); EEVEE_materials_init(sldata, stl, fbl); EEVEE_shadows_init(sldata); @@ -147,6 +151,8 @@ static void eevee_cache_finish(void *vedata) { EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure(); EEVEE_PrivateData *g_data = ((EEVEE_Data *)vedata)->stl->g_data; + const DRWContextState *draw_ctx = DRW_context_state_get(); + const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); EEVEE_volumes_cache_finish(sldata, vedata); EEVEE_materials_cache_finish(sldata, vedata); @@ -156,6 +162,14 @@ static void eevee_cache_finish(void *vedata) EEVEE_effects_draw_init(sldata, vedata); EEVEE_volumes_draw_init(sldata, vedata); + uint tot_samples = scene_eval->eevee.taa_render_samples; + if (tot_samples == 0) { + /* use a high number of samples so the outputs accum buffers + * will have the highest possible precision */ + tot_samples = 1024; + } + EEVEE_renderpasses_output_init(sldata, vedata, tot_samples); + /* Restart taa if a shader has finish compiling. */ /* HACK We should use notification of some sort from the compilation job instead. */ if (g_data->queued_shaders_count != g_data->queued_shaders_count_prev) { @@ -306,6 +320,8 @@ static void eevee_draw_background(void *vedata) EEVEE_draw_effects(sldata, vedata); DRW_stats_group_end(); + EEVEE_renderpasses_output_accumulate(sldata, vedata); + DRW_view_set_active(NULL); if (DRW_state_is_image_render() && (stl->effects->enabled_effects & EFFECT_SSR) && @@ -319,14 +335,19 @@ static void eevee_draw_background(void *vedata) } } - /* Tonemapping and transfer result to default framebuffer. */ - bool use_render_settings = stl->g_data->use_color_render_settings; + if ((stl->g_data->render_passes & SCE_PASS_COMBINED) > 0) { + /* Tonemapping and transfer result to default framebuffer. */ + bool use_render_settings = stl->g_data->use_color_render_settings; - GPU_framebuffer_bind(dfbl->default_fb); - DRW_transform_to_display(stl->effects->final_tx, true, use_render_settings); + GPU_framebuffer_bind(dfbl->default_fb); + DRW_transform_to_display(stl->effects->final_tx, true, use_render_settings); - /* Draw checkerboard with alpha under. */ - EEVEE_draw_alpha_checker(vedata); + /* Draw checkerboard with alpha under. */ + EEVEE_draw_alpha_checker(vedata); + } + else { + EEVEE_renderpasses_draw(sldata, vedata); + } /* Debug : Output buffer to view. */ switch (G.debug_value) { @@ -483,6 +504,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_mist.c b/source/blender/draw/engines/eevee/eevee_mist.c index 7209651a1d4..c9b56a6d551 100644 --- a/source/blender/draw/engines/eevee/eevee_mist.c +++ b/source/blender/draw/engines/eevee/eevee_mist.c @@ -49,6 +49,7 @@ void EEVEE_mist_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) EEVEE_TextureList *txl = vedata->txl; EEVEE_StorageList *stl = vedata->stl; EEVEE_PassList *psl = vedata->psl; + EEVEE_EffectsInfo *effects = stl->effects; EEVEE_PrivateData *g_data = stl->g_data; Scene *scene = draw_ctx->scene; @@ -74,8 +75,10 @@ void EEVEE_mist_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->mist_accum)}); /* Clear texture. */ - GPU_framebuffer_bind(fbl->mist_accum_fb); - GPU_framebuffer_clear_color(fbl->mist_accum_fb, clear); + if (DRW_state_is_image_render() || effects->taa_current_sample == 1) { + GPU_framebuffer_bind(fbl->mist_accum_fb); + GPU_framebuffer_clear_color(fbl->mist_accum_fb, clear); + } /* Mist settings. */ if (scene && scene->world) { diff --git a/source/blender/draw/engines/eevee/eevee_occlusion.c b/source/blender/draw/engines/eevee/eevee_occlusion.c index 48e9b5bcc13..6ba518b3a28 100644 --- a/source/blender/draw/engines/eevee/eevee_occlusion.c +++ b/source/blender/draw/engines/eevee/eevee_occlusion.c @@ -131,7 +131,7 @@ int EEVEE_occlusion_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) return 0; } -void EEVEE_occlusion_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) +void EEVEE_occlusion_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, uint tot_samples) { EEVEE_FramebufferList *fbl = vedata->fbl; EEVEE_TextureList *txl = vedata->txl; @@ -143,18 +143,22 @@ void EEVEE_occlusion_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); if (scene_eval->eevee.flag & SCE_EEVEE_GTAO_ENABLED) { + const eGPUTextureFormat texture_format = (tot_samples > 128) ? GPU_R32F : GPU_R16F; + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; /* Should be enough precision for many samples. */ - DRW_texture_ensure_fullscreen_2d(&txl->ao_accum, GPU_R32F, 0); + DRW_texture_ensure_fullscreen_2d(&txl->ao_accum, texture_format, 0); GPU_framebuffer_ensure_config(&fbl->ao_accum_fb, {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->ao_accum)}); /* Clear texture. */ - GPU_framebuffer_bind(fbl->ao_accum_fb); - GPU_framebuffer_clear_color(fbl->ao_accum_fb, clear); + if (DRW_state_is_image_render() || effects->taa_current_sample == 1) { + GPU_framebuffer_bind(fbl->ao_accum_fb); + GPU_framebuffer_clear_color(fbl->ao_accum_fb, clear); + } /* Accumulation pass */ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ADD; diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index 7d02aacfac7..97bde2e5f2e 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. */ @@ -988,7 +996,9 @@ void EEVEE_bloom_free(void); /* eevee_occlusion.c */ int EEVEE_occlusion_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); -void EEVEE_occlusion_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_occlusion_output_init(EEVEE_ViewLayerData *sldata, + EEVEE_Data *vedata, + uint tot_samples); void EEVEE_occlusion_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_occlusion_compute(EEVEE_ViewLayerData *sldata, @@ -1009,7 +1019,9 @@ void EEVEE_screen_raytrace_free(void); void EEVEE_subsurface_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_subsurface_draw_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_output_init(EEVEE_ViewLayerData *sldata, + EEVEE_Data *vedata, + uint tot_samples); void EEVEE_subsurface_add_pass(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, uint sss_id, @@ -1035,6 +1047,19 @@ 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_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_renderpasses_postprocess(EEVEE_ViewLayerData *sldata, + EEVEE_Data *vedata, + eScenePassType renderpass_type); +void EEVEE_renderpasses_draw(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_renderpasses_free(void); +bool EEVEE_renderpasses_only_first_sample_pass_active(EEVEE_Data *vedata); + /* 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 75e837f140b..ba5704f14e5 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; @@ -517,31 +397,20 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl GPU_framebuffer_bind(fbl->main_fb); DRW_hair_update(); - if ((view_layer->passflag & (SCE_PASS_SUBSURFACE_COLOR | SCE_PASS_SUBSURFACE_DIRECT | - SCE_PASS_SUBSURFACE_INDIRECT)) != 0) { - EEVEE_subsurface_output_init(sldata, vedata); - } - - 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); - } - uint tot_sample = scene_eval->eevee.taa_render_samples; uint render_samples = 0; - if (RE_engine_test_break(engine)) { - return; - } - /* SSR needs one iteration to start properly. */ if (stl->effects->enabled_effects & EFFECT_SSR) { tot_sample += 1; } + EEVEE_renderpasses_output_init(sldata, vedata, tot_sample); + + if (RE_engine_test_break(engine)) { + return; + } + while (render_samples < tot_sample && !RE_engine_test_break(engine)) { float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.0f}; float clear_depth = 1.0f; @@ -616,16 +485,12 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl DRW_draw_pass(psl->refract_depth_pass); DRW_draw_pass(psl->refract_depth_pass_cull); DRW_draw_pass(psl->refract_pass); - /* Subsurface output */ - EEVEE_subsurface_output_accumulate(sldata, vedata); - /* Occlusion output */ - EEVEE_occlusion_output_accumulate(sldata, vedata); /* Result NORMAL */ eevee_render_result_normal(rl, viewname, rect, vedata, sldata); /* Volumetrics Resolve Opaque */ EEVEE_volumes_resolve(sldata, vedata); - /* Mist output */ - EEVEE_mist_output_accumulate(sldata, vedata); + /* Subsurface output, Occlusion output, Mist output */ + EEVEE_renderpasses_output_accumulate(sldata, vedata); /* Transparent */ GPU_framebuffer_texture_attach(fbl->main_color_fb, dtxl->depth, 0, 0); GPU_framebuffer_bind(fbl->main_color_fb); @@ -644,9 +509,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..927ff70a52b --- /dev/null +++ b/source/blender/draw/engines/eevee/eevee_renderpasses.c @@ -0,0 +1,278 @@ +/* + * 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 "DEG_depsgraph_query.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) + +#define EEVEE_RENDERPASSES_POST_PROCESS_ON_FIRST_SAMPLE (SCE_PASS_Z | SCE_PASS_NORMAL) + +#define EEVEE_RENDERPASSES_COLOR_PASS (SCE_PASS_SUBSURFACE_COLOR | SCE_PASS_SUBSURFACE_DIRECT) + +bool EEVEE_renderpasses_only_first_sample_pass_active(EEVEE_Data *vedata) +{ + EEVEE_StorageList *stl = vedata->stl; + EEVEE_PrivateData *g_data = stl->g_data; + return (g_data->render_passes & ~EEVEE_RENDERPASSES_POST_PROCESS_ON_FIRST_SAMPLE) == 0; +} + +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; + View3D *v3d = draw_ctx->v3d; + + if (v3d) { + g_data->render_passes = v3d->shading.render_pass; + } + else { + 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_block(shgrp, "common_block", sldata->common_ubo); + 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_block(shgrp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_texture_ref(shgrp, "inputBuffer", &effects->ssr_normal_input); + DRW_shgroup_uniform_texture_ref(shgrp, "depthBuffer", &dtxl->depth); + break; + } + + case SCE_PASS_MIST: { + DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo); + 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_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) +{ + EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = stl->effects; + eScenePassType render_pass = stl->g_data->render_passes; + + if ((render_pass & SCE_PASS_MIST) != 0) { + EEVEE_mist_output_accumulate(sldata, vedata); + } + if ((effects->enabled_effects & EFFECT_SSS) && + (render_pass & EEVEE_RENDERPASSES_SUBSURFACE) != 0) { + EEVEE_subsurface_output_accumulate(sldata, vedata); + } + if ((render_pass & SCE_PASS_AO) != 0) { + EEVEE_occlusion_output_accumulate(sldata, vedata); + } +} + +void EEVEE_renderpasses_draw(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) +{ + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_TextureList *txl = vedata->txl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = stl->effects; + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + eScenePassType render_pass = stl->g_data->render_passes; + const DRWContextState *draw_ctx = DRW_context_state_get(); + const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); + + bool is_valid = (render_pass & EEVEE_RENDERPASSES_ALL) > 0; + bool needs_color_transfer = (render_pass & EEVEE_RENDERPASSES_COLOR_PASS) > 0 && + DRW_state_is_opengl_render(); + + /* When SSS isn't available, but the pass is requested, we mark it as invalid */ + if ((render_pass & EEVEE_RENDERPASSES_SUBSURFACE) != 0 && + (effects->enabled_effects & EFFECT_SSS) == 0) { + is_valid = false; + } + + /* When SSS isn't available, but the pass is requested, we mark it as invalid */ + if ((render_pass & SCE_PASS_AO) != 0 && (scene_eval->eevee.flag & SCE_EEVEE_GTAO_ENABLED) == 0) { + is_valid = false; + } + + const int current_sample = stl->effects->taa_current_sample; + const int total_samples = stl->effects->taa_total_sample; + if ((render_pass & EEVEE_RENDERPASSES_POST_PROCESS_ON_FIRST_SAMPLE) && + (current_sample > 1 && total_samples != 1)) { + return; + } + + if (is_valid) { + EEVEE_renderpasses_postprocess(sldata, vedata, render_pass); + GPU_framebuffer_bind(dfbl->default_fb); + DRW_transform_to_display(txl->renderpass, needs_color_transfer, false); + } + else { + /* Draw state is not valid for this pass, clear the buffer */ + static float clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + GPU_framebuffer_bind(dfbl->default_fb); + GPU_framebuffer_clear_color(dfbl->default_fb, clear_color); + } + GPU_framebuffer_bind(fbl->main_fb); +} + +void EEVEE_renderpasses_free(void) +{ + DRW_SHADER_FREE_SAFE(e_data.postprocess_sh); +} diff --git a/source/blender/draw/engines/eevee/eevee_subsurface.c b/source/blender/draw/engines/eevee/eevee_subsurface.c index 8376b8c67b8..e94fc903694 100644 --- a/source/blender/draw/engines/eevee/eevee_subsurface.c +++ b/source/blender/draw/engines/eevee/eevee_subsurface.c @@ -156,7 +156,9 @@ 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) +void EEVEE_subsurface_output_init(EEVEE_ViewLayerData *UNUSED(sldata), + EEVEE_Data *vedata, + uint tot_samples) { EEVEE_FramebufferList *fbl = vedata->fbl; EEVEE_TextureList *txl = vedata->txl; @@ -164,8 +166,10 @@ void EEVEE_subsurface_output_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Dat EEVEE_EffectsInfo *effects = stl->effects; if (effects->enabled_effects & EFFECT_SSS) { - DRW_texture_ensure_fullscreen_2d(&txl->sss_dir_accum, GPU_RGBA16F, 0); - DRW_texture_ensure_fullscreen_2d(&txl->sss_col_accum, GPU_RGBA16F, 0); + const eGPUTextureFormat texture_format_light = (tot_samples > 128) ? GPU_RGBA32F : GPU_RGBA16F; + const eGPUTextureFormat texture_format_color = (tot_samples > 512) ? GPU_RGBA32F : GPU_RGBA16F; + DRW_texture_ensure_fullscreen_2d(&txl->sss_dir_accum, texture_format_light, 0); + DRW_texture_ensure_fullscreen_2d(&txl->sss_col_accum, texture_format_color, 0); GPUTexture *stencil_tex = effects->sss_stencil; @@ -183,9 +187,11 @@ void EEVEE_subsurface_output_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Dat GPU_ATTACHMENT_TEXTURE(txl->sss_col_accum)}); /* Clear texture. */ - float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - GPU_framebuffer_bind(fbl->sss_accum_fb); - GPU_framebuffer_clear_color(fbl->sss_accum_fb, clear); + if (DRW_state_is_image_render() || effects->taa_current_sample == 1) { + float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + GPU_framebuffer_bind(fbl->sss_accum_fb); + GPU_framebuffer_clear_color(fbl->sss_accum_fb, clear); + } /* Make the opaque refraction pass mask the sss. */ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES | @@ -253,7 +259,8 @@ void EEVEE_subsurface_add_pass(EEVEE_ViewLayerData *sldata, DRW_shgroup_stencil_mask(grp, sss_id); DRW_shgroup_call(grp, quad, NULL); - if (DRW_state_is_image_render()) { + if ((stl->g_data->render_passes & (SCE_PASS_SUBSURFACE_COLOR | SCE_PASS_SUBSURFACE_DIRECT)) != + 0) { grp = DRW_shgroup_create(e_data.sss_sh[2], psl->sss_accum_ps); DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex()); DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src); diff --git a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c index e5f89aab4d1..0f0b4a3e0a9 100644 --- a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c +++ b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c @@ -234,7 +234,9 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data view_is_valid = view_is_valid && (ED_screen_animation_no_scrub(wm) == NULL); } - effects->taa_total_sample = scene_eval->eevee.taa_samples; + effects->taa_total_sample = EEVEE_renderpasses_only_first_sample_pass_active(vedata) ? + 1 : + scene_eval->eevee.taa_samples; MAX2(effects->taa_total_sample, 0); DRW_view_persmat_get(NULL, persmat, false); 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..5a738d0f130 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl @@ -0,0 +1,64 @@ +#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) { + float depth = texelFetch(depthBuffer, texel, 0).r; + 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 (depth != 1.0 && 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, 1.0); + } + else { + fragColor = vec4(0.0, 0.0, 0.0, 1.0); + } + } + + else if ((renderpassType & ACCUMULATED_VALUE_PASSES) != 0) { + float accumulated_value = texelFetch(inputBuffer, texel, 0).r; + fragColor = vec4(vec3(accumulated_value / currentSample), 1.0); + } + + else if ((renderpassType & ACCUMULATED_COLOR_PASSES) != 0) { + vec3 accumulated_color = texelFetch(inputBuffer, texel, 0).rgb; + fragColor = vec4(accumulated_color / currentSample, 1.0); + } + + else { + fragColor = vec4(1.0, 0.0, 1.0, 1.0); + } +}
\ No newline at end of file |