From 36b259fa889afebce390f98862ea243e617aa989 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Sat, 3 Feb 2018 00:00:19 +0100 Subject: Eevee: Render: Add ambient occlusion pass support. --- .../scripts/startup/bl_ui/properties_view_layer.py | 2 + .../blender/draw/engines/eevee/eevee_occlusion.c | 62 ++++++++++++++++++++++ source/blender/draw/engines/eevee/eevee_private.h | 5 ++ source/blender/draw/engines/eevee/eevee_render.c | 38 +++++++++++++ 4 files changed, 107 insertions(+) diff --git a/release/scripts/startup/bl_ui/properties_view_layer.py b/release/scripts/startup/bl_ui/properties_view_layer.py index b58b034ca55..4d61aacbf22 100644 --- a/release/scripts/startup/bl_ui/properties_view_layer.py +++ b/release/scripts/startup/bl_ui/properties_view_layer.py @@ -469,6 +469,8 @@ class VIEWLAYER_PT_eevee_layer_passes(ViewLayerButtonsPanel, Panel): col.prop(view_layer, "use_pass_z") col.prop(view_layer, "use_pass_mist") col.prop(view_layer, "use_pass_normal") + col.separator() + col.prop(view_layer, "use_pass_ambient_occlusion") col = split.column() col.label(text="Subsurface:") diff --git a/source/blender/draw/engines/eevee/eevee_occlusion.c b/source/blender/draw/engines/eevee/eevee_occlusion.c index 9da438e825f..944003d7d1f 100644 --- a/source/blender/draw/engines/eevee/eevee_occlusion.c +++ b/source/blender/draw/engines/eevee/eevee_occlusion.c @@ -123,6 +123,48 @@ int EEVEE_occlusion_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) return 0; } +void EEVEE_occlusion_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) +{ + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_TextureList *txl = vedata->txl; + EEVEE_PassList *psl = vedata->psl; + 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, "gtao_enable")) { + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + + DRWFboTexture tex_data = {&txl->ao_accum, DRW_TEX_R_32, 0}; + DRW_framebuffer_init(&fbl->ao_accum_fb, &draw_engine_eevee_type, (int)viewport_size[0], (int)viewport_size[1], + &tex_data, 1); + + /* Clear texture. */ + DRW_framebuffer_bind(fbl->ao_accum_fb); + DRW_framebuffer_clear(true, false, false, clear, 0.0f); + + /* Accumulation pass */ + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE; + psl->ao_accum_ps = DRW_pass_create("AO Accum", state); + DRWShadingGroup *grp = DRW_shgroup_create(e_data.gtao_debug_sh, psl->ao_accum_ps); + DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex()); + DRW_shgroup_uniform_buffer(grp, "maxzBuffer", &txl->maxzbuffer); + DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth); + DRW_shgroup_uniform_buffer(grp, "normalBuffer", &txl->ssr_normal_input); + DRW_shgroup_uniform_buffer(grp, "horizonBuffer", &txl->gtao_horizons); + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + } + else { + /* Cleanup to release memory */ + DRW_TEXTURE_FREE_SAFE(txl->ao_accum); + DRW_FRAMEBUFFER_FREE_SAFE(fbl->ao_accum_fb); + } +} + void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) { EEVEE_PassList *psl = vedata->psl; @@ -228,6 +270,26 @@ void EEVEE_occlusion_draw_debug(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data } } +void EEVEE_occlusion_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) +{ + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_PassList *psl = vedata->psl; + + if (fbl->ao_accum_fb != NULL) { + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + + /* Update the min_max/horizon buffers so the refracion materials appear in it. */ + EEVEE_create_minmax_buffer(vedata, dtxl->depth, -1); + EEVEE_occlusion_compute(sldata, vedata, dtxl->depth, -1); + + DRW_framebuffer_bind(fbl->ao_accum_fb); + DRW_draw_pass(psl->ao_accum_ps); + + /* Restore */ + DRW_framebuffer_bind(fbl->main); + } +} + void EEVEE_occlusion_free(void) { DRW_SHADER_FREE_SAFE(e_data.gtao_sh); diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index 54da57c7a87..0381f841ea7 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -160,6 +160,7 @@ typedef struct EEVEE_PassList { struct DRWPass *ao_horizon_search; struct DRWPass *ao_horizon_search_layer; struct DRWPass *ao_horizon_debug; + struct DRWPass *ao_accum_ps; struct DRWPass *mist_accum_ps; struct DRWPass *motion_blur; struct DRWPass *bloom_blit; @@ -232,6 +233,7 @@ typedef struct EEVEE_FramebufferList { struct GPUFrameBuffer *screen_tracing_fb; struct GPUFrameBuffer *refract_fb; struct GPUFrameBuffer *mist_accum_fb; + struct GPUFrameBuffer *ao_accum_fb; struct GPUFrameBuffer *update_noise_fb; @@ -254,6 +256,7 @@ typedef struct EEVEE_TextureList { struct GPUTexture *bloom_downsample[MAX_BLOOM_STEP]; /* R16_G16_B16 */ struct GPUTexture *bloom_upsample[MAX_BLOOM_STEP - 1]; /* R16_G16_B16 */ struct GPUTexture *mist_accum; + struct GPUTexture *ao_accum; struct GPUTexture *sss_dir_accum; struct GPUTexture *sss_col_accum; struct GPUTexture *ssr_normal_input; @@ -814,6 +817,8 @@ 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_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, EEVEE_Data *vedata, struct GPUTexture *depth_src, int layer); void EEVEE_occlusion_draw_debug(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 51e8fa241d0..68d575df11c 100644 --- a/source/blender/draw/engines/eevee/eevee_render.c +++ b/source/blender/draw/engines/eevee/eevee_render.c @@ -318,6 +318,35 @@ static void eevee_render_result_mist( } } +static void eevee_render_result_occlusion( + 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 (vedata->fbl->ao_accum_fb == NULL) { + /* AO is not enabled. */ + return; + } + + if ((view_layer->passflag & SCE_PASS_AO) != 0) { + RenderLayer *rl = rr->layers.first; + RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_AO, 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->ao_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 += 3) { + rp->rect[i] = rp->rect[i+1] = rp->rect[i+2] = min_ff(1.0f, rp->rect[i] / render_samples); + } + } +} + static void eevee_render_draw_background(EEVEE_Data *vedata) { EEVEE_TextureList *txl = vedata->txl; @@ -373,6 +402,10 @@ void EEVEE_render_draw(EEVEE_Data *vedata, struct RenderEngine *engine, struct D EEVEE_mist_output_init(sldata, vedata); } + if ((view_layer->passflag & SCE_PASS_AO) != 0) { + EEVEE_occlusion_output_init(sldata, vedata); + } + /* Init render result. */ const char *viewname = RE_GetActiveRenderView(engine->re); const float *render_size = DRW_viewport_size_get(); @@ -431,7 +464,10 @@ void EEVEE_render_draw(EEVEE_Data *vedata, struct RenderEngine *engine, struct D 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(rr, viewname, vedata, sldata); /* Volumetrics Resolve Opaque */ @@ -450,6 +486,7 @@ void EEVEE_render_draw(EEVEE_Data *vedata, struct RenderEngine *engine, struct D eevee_render_result_combined(rr, viewname, vedata, sldata); eevee_render_result_subsurface(rr, viewname, vedata, sldata); eevee_render_result_mist(rr, viewname, vedata, sldata); + eevee_render_result_occlusion(rr, viewname, vedata, sldata); RE_engine_end_result(engine, rr, false, false, false); } @@ -471,6 +508,7 @@ void EEVEE_render_update_passes(RenderEngine *engine, Scene *scene, ViewLayer *v CHECK_PASS(Z, 1, "Z"); CHECK_PASS(MIST, 1, "Z"); CHECK_PASS(NORMAL, 3, "XYZ"); + CHECK_PASS(AO, 3, "RGB"); CHECK_PASS(SUBSURFACE_COLOR, 3, "RGB"); CHECK_PASS(SUBSURFACE_DIRECT, 3, "RGB"); -- cgit v1.2.3