diff options
Diffstat (limited to 'source/blender/draw/engines/eevee')
24 files changed, 1626 insertions, 331 deletions
diff --git a/source/blender/draw/engines/eevee/eevee_bloom.c b/source/blender/draw/engines/eevee/eevee_bloom.c index c6cc336db56..53465455d57 100644 --- a/source/blender/draw/engines/eevee/eevee_bloom.c +++ b/source/blender/draw/engines/eevee/eevee_bloom.c @@ -40,6 +40,8 @@ static struct { extern char datatoc_effect_bloom_frag_glsl[]; +const bool use_highres = true; + static void eevee_create_shader_bloom(void) { e_data.bloom_blit_sh[0] = DRW_shader_create_fullscreen(datatoc_effect_bloom_frag_glsl, @@ -179,7 +181,8 @@ static DRWShadingGroup *eevee_create_bloom_pass(const char *name, EEVEE_EffectsInfo *effects, struct GPUShader *sh, DRWPass **pass, - bool upsample) + bool upsample, + bool resolve) { struct GPUBatch *quad = DRW_cache_fullscreen_quad_get(); @@ -193,6 +196,10 @@ static DRWShadingGroup *eevee_create_bloom_pass(const char *name, DRW_shgroup_uniform_texture_ref(grp, "baseBuffer", &effects->unf_base_buffer); DRW_shgroup_uniform_float(grp, "sampleScale", &effects->bloom_sample_scale, 1); } + if (resolve) { + DRW_shgroup_uniform_vec3(grp, "bloomColor", effects->bloom_color, 1); + DRW_shgroup_uniform_bool_copy(grp, "bloomAddBase", true); + } return grp; } @@ -203,6 +210,8 @@ void EEVEE_bloom_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *ved EEVEE_StorageList *stl = vedata->stl; EEVEE_EffectsInfo *effects = stl->effects; + psl->bloom_accum_ps = NULL; + if ((effects->enabled_effects & EFFECT_BLOOM) != 0) { /** Bloom algorithm * @@ -234,29 +243,41 @@ void EEVEE_bloom_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *ved * </pre> */ DRWShadingGroup *grp; - const bool use_highres = true; const bool use_antiflicker = true; eevee_create_bloom_pass("Bloom Downsample First", effects, e_data.bloom_downsample_sh[use_antiflicker], &psl->bloom_downsample_first, + false, + false); + eevee_create_bloom_pass("Bloom Downsample", + effects, + e_data.bloom_downsample_sh[0], + &psl->bloom_downsample, + false, false); - eevee_create_bloom_pass( - "Bloom Downsample", effects, e_data.bloom_downsample_sh[0], &psl->bloom_downsample, false); eevee_create_bloom_pass("Bloom Upsample", effects, e_data.bloom_upsample_sh[use_highres], &psl->bloom_upsample, - true); + true, + false); - grp = eevee_create_bloom_pass( - "Bloom Blit", effects, e_data.bloom_blit_sh[use_antiflicker], &psl->bloom_blit, false); + grp = eevee_create_bloom_pass("Bloom Blit", + effects, + e_data.bloom_blit_sh[use_antiflicker], + &psl->bloom_blit, + false, + false); DRW_shgroup_uniform_vec4(grp, "curveThreshold", effects->bloom_curve_threshold, 1); DRW_shgroup_uniform_float(grp, "clampIntensity", &effects->bloom_clamp, 1); - grp = eevee_create_bloom_pass( - "Bloom Resolve", effects, e_data.bloom_resolve_sh[use_highres], &psl->bloom_resolve, true); - DRW_shgroup_uniform_vec3(grp, "bloomColor", effects->bloom_color, 1); + grp = eevee_create_bloom_pass("Bloom Resolve", + effects, + e_data.bloom_resolve_sh[use_highres], + &psl->bloom_resolve, + true, + true); } } @@ -322,6 +343,47 @@ void EEVEE_bloom_draw(EEVEE_Data *vedata) } } +void EEVEE_bloom_output_init(EEVEE_ViewLayerData *UNUSED(sldata), + EEVEE_Data *vedata, + uint UNUSED(tot_samples)) +{ + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_TextureList *txl = vedata->txl; + EEVEE_PassList *psl = vedata->psl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = stl->effects; + + /* Create FrameBuffer. */ + DRW_texture_ensure_fullscreen_2d(&txl->bloom_accum, GPU_R11F_G11F_B10F, 0); + + GPU_framebuffer_ensure_config(&fbl->bloom_pass_accum_fb, + {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->bloom_accum)}); + + /* Create Pass and shgroup. */ + DRWShadingGroup *grp = eevee_create_bloom_pass("Bloom Accumulate", + effects, + e_data.bloom_resolve_sh[use_highres], + &psl->bloom_accum_ps, + true, + true); + DRW_shgroup_uniform_bool_copy(grp, "bloomAddBase", false); +} + +void EEVEE_bloom_output_accumulate(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) +{ + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_PassList *psl = vedata->psl; + EEVEE_StorageList *stl = vedata->stl; + + if (stl->g_data->render_passes & EEVEE_RENDER_PASS_BLOOM) { + GPU_framebuffer_bind(fbl->bloom_pass_accum_fb); + DRW_draw_pass(psl->bloom_accum_ps); + + /* Restore */ + GPU_framebuffer_bind(fbl->main_fb); + } +} + void EEVEE_bloom_free(void) { for (int i = 0; i < 2; i++) { diff --git a/source/blender/draw/engines/eevee/eevee_data.c b/source/blender/draw/engines/eevee/eevee_data.c index dd70ee1bd4b..e586fc7b1db 100644 --- a/source/blender/draw/engines/eevee/eevee_data.c +++ b/source/blender/draw/engines/eevee/eevee_data.c @@ -54,6 +54,9 @@ void EEVEE_view_layer_data_free(void *storage) DRW_UBO_FREE_SAFE(sldata->grid_ubo); DRW_UBO_FREE_SAFE(sldata->planar_ubo); DRW_UBO_FREE_SAFE(sldata->common_ubo); + for (int i = 0; i < MAX_MATERIAL_RENDER_PASSES_UBO; i++) { + DRW_UBO_FREE_SAFE(sldata->renderpass_ubo[i]); + } } EEVEE_ViewLayerData *EEVEE_view_layer_data_get(void) diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c index a20921b639f..90bfad45f60 100644 --- a/source/blender/draw/engines/eevee/eevee_effects.c +++ b/source/blender/draw/engines/eevee/eevee_effects.c @@ -170,7 +170,7 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_subsurface_init(sldata, vedata); /* Force normal buffer creation. */ - if (!minimal && (stl->g_data->render_passes & SCE_PASS_NORMAL) != 0) { + if (!minimal && (stl->g_data->render_passes & EEVEE_RENDER_PASS_NORMAL) != 0) { effects->enabled_effects |= EFFECT_NORMAL_BUFFER; } @@ -333,6 +333,8 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) grp = DRW_shgroup_create(EEVEE_shaders_velocity_resolve_sh_get(), psl->velocity_resolve); DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &e_data.depth_src); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_block( + grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); DRW_shgroup_uniform_mat4(grp, "currPersinv", effects->velocity_curr_persinv); DRW_shgroup_uniform_mat4(grp, "pastPersmat", effects->velocity_past_persmat); DRW_shgroup_call(grp, quad, NULL); @@ -513,7 +515,7 @@ static void EEVEE_velocity_resolve(EEVEE_Data *vedata) DRW_view_persmat_get(view, effects->velocity_past_persmat, false); } -void EEVEE_draw_effects(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) +void EEVEE_draw_effects(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) { EEVEE_TextureList *txl = vedata->txl; EEVEE_FramebufferList *fbl = vedata->fbl; @@ -541,6 +543,10 @@ void EEVEE_draw_effects(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) EEVEE_temporal_sampling_draw(vedata); EEVEE_bloom_draw(vedata); + /* Post effect render passes are done here just after the drawing of the effects and just before + * the swapping of the buffers. */ + EEVEE_renderpasses_output_accumulate(sldata, vedata, true); + /* Save the final texture and framebuffer for final transformation or read. */ effects->final_tx = effects->source_buffer; effects->final_fb = (effects->target_buffer != fbl->main_color_fb) ? fbl->main_fb : diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c index e3b50bb2142..3337cbcc59d 100644 --- a/source/blender/draw/engines/eevee/eevee_engine.c +++ b/source/blender/draw/engines/eevee/eevee_engine.c @@ -151,7 +151,8 @@ void EEVEE_cache_populate(void *vedata, Object *ob) 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; + EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl; + EEVEE_PrivateData *g_data = stl->g_data; const DRWContextState *draw_ctx = DRW_context_state_get(); const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); @@ -176,6 +177,9 @@ static void eevee_cache_finish(void *vedata) if (g_data->queued_shaders_count != g_data->queued_shaders_count_prev) { g_data->queued_shaders_count_prev = g_data->queued_shaders_count; EEVEE_temporal_sampling_reset(vedata); + /* At this moment the TAA sampling will be redrawn in the next iteration. + * we set the taa_current_sample to 0 so the next iteration will use sample 1 */ + stl->effects->taa_current_sample = 0; } } @@ -307,6 +311,9 @@ static void eevee_draw_scene(void *vedata) /* Volumetrics Resolve Opaque */ EEVEE_volumes_resolve(sldata, vedata); + /* Renderpasses */ + EEVEE_renderpasses_output_accumulate(sldata, vedata, false); + /* Transparent */ /* TODO(fclem): should be its own Framebuffer. * This is needed because dualsource blending only works with 1 color buffer. */ @@ -321,8 +328,6 @@ static void eevee_draw_scene(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) && @@ -336,7 +341,7 @@ static void eevee_draw_scene(void *vedata) } } - if ((stl->g_data->render_passes & SCE_PASS_COMBINED) > 0) { + if ((stl->g_data->render_passes & EEVEE_RENDER_PASS_COMBINED) != 0) { /* Transfer result to default framebuffer. */ GPU_framebuffer_bind(dfbl->default_fb); DRW_transform_none(stl->effects->final_tx); diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c index 7da9af55330..92e36597d99 100644 --- a/source/blender/draw/engines/eevee/eevee_lightprobes.c +++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c @@ -251,6 +251,8 @@ void EEVEE_lightbake_cache_init(EEVEE_ViewLayerData *sldata, // DRW_shgroup_uniform_texture(grp, "texJitter", e_data.jitter); DRW_shgroup_uniform_texture(grp, "probeHdr", rt_color); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_block( + grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); struct GPUBatch *geom = DRW_cache_fullscreen_quad_get(); DRW_shgroup_call(grp, geom, NULL); @@ -272,6 +274,8 @@ void EEVEE_lightbake_cache_init(EEVEE_ViewLayerData *sldata, DRW_shgroup_uniform_float(grp, "intensityFac", &pinfo->intensity_fac, 1); DRW_shgroup_uniform_texture(grp, "probeHdr", rt_color); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_block( + grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); struct GPUBatch *geom = DRW_cache_fullscreen_quad_get(); DRW_shgroup_call(grp, geom, NULL); @@ -292,6 +296,8 @@ void EEVEE_lightbake_cache_init(EEVEE_ViewLayerData *sldata, DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley); DRW_shgroup_uniform_texture(grp, "probeDepth", rt_depth); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_block( + grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); struct GPUBatch *geom = DRW_cache_fullscreen_quad_get(); DRW_shgroup_call(grp, geom, NULL); @@ -360,6 +366,8 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo); DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo); DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo); + DRW_shgroup_uniform_block( + grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); DRW_shgroup_call(grp, geom, NULL); break; case GPU_MAT_QUEUED: @@ -403,6 +411,8 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat /* TODO (fclem) get rid of those UBO. */ DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo); DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo); + DRW_shgroup_uniform_block( + grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); DRW_shgroup_call_procedural_triangles(grp, NULL, cube_len * 2); } @@ -429,6 +439,8 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat DRW_shgroup_uniform_block(shgrp, "planar_block", sldata->planar_ubo); DRW_shgroup_uniform_block(shgrp, "grid_block", sldata->grid_ubo); DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_block( + shgrp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); int tri_count = egrid->resolution[0] * egrid->resolution[1] * egrid->resolution[2] * 2; DRW_shgroup_call_procedural_triangles(shgrp, NULL, tri_count); } @@ -446,6 +458,8 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat DRWShadingGroup *grp = DRW_shgroup_create(EEVEE_shaders_probe_planar_display_sh_get(), psl->probe_display); DRW_shgroup_uniform_texture_ref(grp, "probePlanars", &txl->planar_pool); + DRW_shgroup_uniform_block( + grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); stl->g_data->planar_display_shgrp = DRW_shgroup_call_buffer_instance( grp, e_data.format_probe_display_planar, DRW_cache_quad_get()); diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index 1c0a1289ba4..3c793ca0693 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -25,6 +25,7 @@ #include "BLI_dynstr.h" #include "BLI_ghash.h" #include "BLI_alloca.h" +#include "BLI_math_bits.h" #include "BLI_rand.h" #include "BLI_string_utils.h" @@ -101,9 +102,37 @@ extern char datatoc_volumetric_vert_glsl[]; extern char datatoc_volumetric_geom_glsl[]; extern char datatoc_volumetric_frag_glsl[]; extern char datatoc_volumetric_lib_glsl[]; - extern char datatoc_gpu_shader_uniform_color_frag_glsl[]; +#define DEFAULT_RENDER_PASS_FLAG 0xefffffff + +/* Iterator for render passes. This iteration will only do the material based render passes. it + * will ignore `EEVEE_RENDER_PASS_ENVIRONMENT`. + * + * parameters: + * - `render_passes_` is a bitflag for render_passes that needs to be iterated over. + * - `render_pass_index_` is a parameter name where the index of the render_pass will be available + * during iteration. This index can be used to select the right pass in the `psl`. + * - `render_pass_` is the bitflag of the render_pass of the current iteration. + * + * The `render_pass_index_` parameter needs to be the same for the `RENDER_PASS_ITER_BEGIN` and + * `RENDER_PASS_ITER_END`. + */ +#define RENDER_PASS_ITER_BEGIN(render_passes_, render_pass_index_, render_pass_) \ + const eViewLayerEEVEEPassType __filtered_##render_pass_index_ = render_passes_ & \ + EEVEE_RENDERPASSES_MATERIAL & \ + ~EEVEE_RENDER_PASS_ENVIRONMENT; \ + if (__filtered_##render_pass_index_ != 0) { \ + int render_pass_index_ = 1; \ + for (int bit_##render_pass_ = 0; bit_##render_pass_ < 32; bit_##render_pass_++) { \ + eViewLayerEEVEEPassType render_pass_ = (1 << bit_##render_pass_); \ + if ((__filtered_##render_pass_index_ & render_pass_) != 0) { +#define RENDER_PASS_ITER_END(render_pass_index_) \ + render_pass_index_ += 1; \ + } \ + } \ + } + /* *********** FUNCTIONS *********** */ #if 0 /* Used only to generate the LUT values */ @@ -337,6 +366,39 @@ static char *eevee_get_volume_defines(int options) return str; } +/* Get the default render pass ubo. This is a ubo that enables all bsdf render passes. */ +struct GPUUniformBuffer *EEVEE_material_default_render_pass_ubo_get(EEVEE_ViewLayerData *sldata) +{ + return sldata->renderpass_ubo[0]; +} + +/* Get the render pass ubo for rendering the given render_pass. */ +static struct GPUUniformBuffer *get_render_pass_ubo(EEVEE_ViewLayerData *sldata, + eViewLayerEEVEEPassType render_pass) +{ + int index; + switch (render_pass) { + case EEVEE_RENDER_PASS_DIFFUSE_COLOR: + index = 1; + break; + case EEVEE_RENDER_PASS_DIFFUSE_LIGHT: + index = 2; + break; + case EEVEE_RENDER_PASS_SPECULAR_COLOR: + index = 3; + break; + case EEVEE_RENDER_PASS_SPECULAR_LIGHT: + index = 4; + break; + case EEVEE_RENDER_PASS_EMIT: + index = 5; + break; + default: + index = 0; + break; + } + return sldata->renderpass_ubo[index]; +} /** * ssr_id can be null to disable ssr contribution. */ @@ -349,7 +411,8 @@ static void add_standard_uniforms(DRWShadingGroup *shgrp, bool use_glossy, bool use_refract, bool use_ssrefraction, - bool use_alpha_blend) + bool use_alpha_blend, + eViewLayerEEVEEPassType render_pass) { LightCache *lcache = vedata->stl->g_data->light_cache; EEVEE_EffectsInfo *effects = vedata->stl->effects; @@ -360,9 +423,9 @@ static void add_standard_uniforms(DRWShadingGroup *shgrp, DRW_shgroup_uniform_block(shgrp, "light_block", sldata->light_ubo); DRW_shgroup_uniform_block(shgrp, "shadow_block", sldata->shadow_ubo); DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_block(shgrp, "renderpass_block", get_render_pass_ubo(sldata, render_pass)); DRW_shgroup_uniform_int_copy(shgrp, "outputSssId", 1); - if (use_diffuse || use_glossy || use_refract) { DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex); DRW_shgroup_uniform_texture_ref(shgrp, "shadowCubeTexture", &sldata->shadow_cube_pool); @@ -395,6 +458,24 @@ static void add_standard_uniforms(DRWShadingGroup *shgrp, } } +/* Add the uniforms for the background shader to `shgrp`. */ +static void add_background_uniforms(DRWShadingGroup *shgrp, + EEVEE_ViewLayerData *sldata, + EEVEE_Data *vedata) +{ + EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl; + DRW_shgroup_uniform_float(shgrp, "backgroundAlpha", &stl->g_data->background_alpha, 1); + /* TODO (fclem): remove those (need to clean the GLSL files). */ + DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_block(shgrp, "grid_block", sldata->grid_ubo); + DRW_shgroup_uniform_block(shgrp, "probe_block", sldata->probe_ubo); + DRW_shgroup_uniform_block(shgrp, "planar_block", sldata->planar_ubo); + DRW_shgroup_uniform_block(shgrp, "light_block", sldata->light_ubo); + DRW_shgroup_uniform_block(shgrp, "shadow_block", sldata->shadow_ubo); + DRW_shgroup_uniform_block( + shgrp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); +} + static void create_default_shader(int options) { char *frag_str = BLI_string_joinN(e_data.frag_shader_lib, datatoc_default_frag_glsl); @@ -523,6 +604,9 @@ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata, EEVEE_StorageList *stl, EEVEE_FramebufferList *fbl) { + const DRWContextState *draw_ctx = DRW_context_state_get(); + EEVEE_PrivateData *g_data = stl->g_data; + if (!e_data.frag_shader_lib) { /* Shaders */ e_data.frag_shader_lib = BLI_string_joinN(datatoc_common_view_lib_glsl, @@ -600,7 +684,6 @@ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata, datatoc_prepass_frag_glsl, "#define HAIR_SHADER\n" "#define CLIP_PLANES\n"); - MEM_freeN(vert_str); e_data.update_noise_sh = DRW_shader_create_fullscreen(datatoc_update_noise_frag_glsl, NULL); @@ -635,6 +718,66 @@ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata, &fbl->update_noise_fb, {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE_LAYER(e_data.util_tex, 2)}); } + + { + /* Create RenderPass UBO */ + if (sldata->renderpass_ubo[0] == NULL) { + sldata->renderpass_data[0].renderPassDiffuse = true; + sldata->renderpass_data[0].renderPassDiffuseLight = true; + sldata->renderpass_data[0].renderPassGlossy = true; + sldata->renderpass_data[0].renderPassGlossyLight = true; + sldata->renderpass_data[0].renderPassEmit = true; + sldata->renderpass_data[0].renderPassSSSColor = false; + sldata->renderpass_data[1].renderPassDiffuse = true; + sldata->renderpass_data[1].renderPassDiffuseLight = false; + sldata->renderpass_data[1].renderPassGlossy = false; + sldata->renderpass_data[1].renderPassGlossyLight = false; + sldata->renderpass_data[1].renderPassEmit = false; + sldata->renderpass_data[1].renderPassSSSColor = true; + sldata->renderpass_data[2].renderPassDiffuse = true; + sldata->renderpass_data[2].renderPassDiffuseLight = true; + sldata->renderpass_data[2].renderPassGlossy = false; + sldata->renderpass_data[2].renderPassGlossyLight = false; + sldata->renderpass_data[2].renderPassEmit = false; + sldata->renderpass_data[2].renderPassSSSColor = false; + sldata->renderpass_data[3].renderPassDiffuse = false; + sldata->renderpass_data[3].renderPassDiffuseLight = false; + sldata->renderpass_data[3].renderPassGlossy = true; + sldata->renderpass_data[3].renderPassGlossyLight = false; + sldata->renderpass_data[3].renderPassEmit = false; + sldata->renderpass_data[3].renderPassSSSColor = false; + sldata->renderpass_data[4].renderPassDiffuse = false; + sldata->renderpass_data[4].renderPassDiffuseLight = false; + sldata->renderpass_data[4].renderPassGlossy = true; + sldata->renderpass_data[4].renderPassGlossyLight = true; + sldata->renderpass_data[4].renderPassEmit = false; + sldata->renderpass_data[4].renderPassSSSColor = false; + sldata->renderpass_data[5].renderPassDiffuse = false; + sldata->renderpass_data[5].renderPassDiffuseLight = false; + sldata->renderpass_data[5].renderPassGlossy = false; + sldata->renderpass_data[5].renderPassGlossyLight = false; + sldata->renderpass_data[5].renderPassEmit = true; + sldata->renderpass_data[5].renderPassSSSColor = false; + + for (int i = 0; i < MAX_MATERIAL_RENDER_PASSES_UBO; i++) { + sldata->renderpass_ubo[i] = DRW_uniformbuffer_create(sizeof(EEVEE_RenderPassData), + &sldata->renderpass_data[i]); + } + } + + /* HACK: EEVEE_material_world_background_get can create a new context. This can only be + * done when there is no active framebuffer. We do this here otherwise + * `EEVEE_renderpasses_output_init` will fail. It cannot be done in + * `EEVEE_renderpasses_init` as the `e_data.vertcode` can be uninitialized. + */ + if (g_data->render_passes & EEVEE_RENDER_PASS_ENVIRONMENT) { + struct Scene *scene = draw_ctx->scene; + struct World *wo = scene->world; + if (wo && wo->use_nodes) { + EEVEE_material_world_background_get(scene, wo); + } + } + } } struct GPUMaterial *EEVEE_material_world_lightprobe_get(struct Scene *scene, World *wo) @@ -852,7 +995,17 @@ static struct DRWShadingGroup *EEVEE_default_shading_group_create(EEVEE_ViewLaye } DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit[options], pass); - add_standard_uniforms(shgrp, sldata, vedata, &ssr_id, NULL, true, true, false, false, use_blend); + add_standard_uniforms(shgrp, + sldata, + vedata, + &ssr_id, + NULL, + true, + true, + false, + false, + use_blend, + DEFAULT_RENDER_PASS_FLAG); return shgrp; } @@ -894,14 +1047,34 @@ static struct DRWShadingGroup *EEVEE_default_shading_group_get(EEVEE_ViewLayerDa if (!is_hair) { DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit[options], psl->default_pass[options]); - add_standard_uniforms(shgrp, sldata, vedata, &ssr_id, NULL, true, true, false, false, false); + add_standard_uniforms(shgrp, + sldata, + vedata, + &ssr_id, + NULL, + true, + true, + false, + false, + false, + DEFAULT_RENDER_PASS_FLAG); } } if (is_hair) { DRWShadingGroup *shgrp = DRW_shgroup_hair_create( ob, psys, md, vedata->psl->default_pass[options], e_data.default_lit[options]); - add_standard_uniforms(shgrp, sldata, vedata, &ssr_id, NULL, true, true, false, false, false); + add_standard_uniforms(shgrp, + sldata, + vedata, + &ssr_id, + NULL, + true, + true, + false, + false, + false, + DEFAULT_RENDER_PASS_FLAG); return shgrp; } else { @@ -909,6 +1082,60 @@ static struct DRWShadingGroup *EEVEE_default_shading_group_get(EEVEE_ViewLayerDa } } +static struct DRWShadingGroup *EEVEE_default_render_pass_shading_group_get( + EEVEE_ViewLayerData *sldata, + EEVEE_Data *vedata, + bool holdout, + bool use_ssr, + DRWPass *pass, + eViewLayerEEVEEPassType render_pass_flag) +{ + static int ssr_id; + ssr_id = (use_ssr) ? 1 : -1; + int options = VAR_MAT_MESH; + + SET_FLAG_FROM_TEST(options, holdout, VAR_MAT_HOLDOUT); + + if (e_data.default_lit[options] == NULL) { + create_default_shader(options); + } + + DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit[options], pass); + add_standard_uniforms( + shgrp, sldata, vedata, &ssr_id, NULL, true, true, false, false, false, render_pass_flag); + return shgrp; +} + +static struct DRWShadingGroup *EEVEE_default_hair_render_pass_shading_group_get( + EEVEE_ViewLayerData *sldata, + EEVEE_Data *vedata, + Object *ob, + ParticleSystem *psys, + ModifierData *md, + bool holdout, + bool use_ssr, + DRWPass *pass, + eViewLayerEEVEEPassType render_pass_flag) +{ + static int ssr_id; + ssr_id = (use_ssr) ? 1 : -1; + int options = VAR_MAT_MESH | VAR_MAT_HAIR; + + BLI_assert((ob && psys && md)); + + SET_FLAG_FROM_TEST(options, holdout, VAR_MAT_HOLDOUT); + + if (e_data.default_lit[options] == NULL) { + create_default_shader(options); + } + + DRWShadingGroup *shgrp = DRW_shgroup_hair_create( + ob, psys, md, pass, e_data.default_lit[options]); + add_standard_uniforms( + shgrp, sldata, vedata, &ssr_id, NULL, true, true, false, false, false, render_pass_flag); + return shgrp; +} + void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) { EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl; @@ -945,14 +1172,7 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) switch (GPU_material_status(gpumat)) { case GPU_MAT_SUCCESS: grp = DRW_shgroup_material_create(gpumat, psl->background_pass); - DRW_shgroup_uniform_float(grp, "backgroundAlpha", &stl->g_data->background_alpha, 1); - /* TODO (fclem): remove those (need to clean the GLSL files). */ - DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); - DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo); - DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo); - DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo); - DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo); - DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo); + add_background_uniforms(grp, sldata, vedata); DRW_shgroup_call(grp, geom, NULL); break; case GPU_MAT_QUEUED: @@ -1071,7 +1291,17 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_PASS_CREATE(psl->lookdev_diffuse_pass, state); shgrp = DRW_shgroup_create(e_data.default_lit[options], psl->lookdev_diffuse_pass); - add_standard_uniforms(shgrp, sldata, vedata, NULL, NULL, true, true, false, false, false); + add_standard_uniforms(shgrp, + sldata, + vedata, + NULL, + NULL, + true, + true, + false, + false, + false, + DEFAULT_RENDER_PASS_FLAG); DRW_shgroup_uniform_vec3(shgrp, "basecol", color_diffuse, 1); DRW_shgroup_uniform_float_copy(shgrp, "metallic", 0.0f); DRW_shgroup_uniform_float_copy(shgrp, "specular", 0.5f); @@ -1080,12 +1310,31 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_PASS_CREATE(psl->lookdev_glossy_pass, state); shgrp = DRW_shgroup_create(e_data.default_lit[options], psl->lookdev_glossy_pass); - add_standard_uniforms(shgrp, sldata, vedata, NULL, NULL, true, true, false, false, false); + add_standard_uniforms(shgrp, + sldata, + vedata, + NULL, + NULL, + true, + true, + false, + false, + false, + DEFAULT_RENDER_PASS_FLAG); DRW_shgroup_uniform_vec3(shgrp, "basecol", color_chrome, 1); DRW_shgroup_uniform_float_copy(shgrp, "metallic", 1.0f); DRW_shgroup_uniform_float_copy(shgrp, "roughness", 0.0f); DRW_shgroup_call(shgrp, sphere, NULL); } + + { + memset(psl->material_accum_pass, 0, sizeof(psl->material_accum_pass)); + for (int pass_index = 0; pass_index < stl->g_data->render_passes_material_count; + pass_index++) { + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND_ADD; + DRW_PASS_CREATE(psl->material_accum_pass[pass_index], state); + } + } } #define ADD_SHGROUP_CALL(shgrp, ob, geom, oedata) \ @@ -1109,6 +1358,7 @@ typedef struct EeveeMaterialShadingGroups { struct DRWShadingGroup *shading_grp; struct DRWShadingGroup *depth_grp; struct DRWShadingGroup *depth_clip_grp; + struct DRWShadingGroup *material_accum_grp[MAX_MATERIAL_RENDER_PASSES]; } EeveeMaterialShadingGroups; static void material_opaque(Material *ma, @@ -1117,9 +1367,7 @@ static void material_opaque(Material *ma, EEVEE_Data *vedata, struct GPUMaterial **gpumat, struct GPUMaterial **gpumat_depth, - struct DRWShadingGroup **shgrp, - struct DRWShadingGroup **shgrp_depth, - struct DRWShadingGroup **shgrp_depth_clip, + struct EeveeMaterialShadingGroups *shgrps, bool holdout) { EEVEE_EffectsInfo *effects = vedata->stl->effects; @@ -1128,7 +1376,7 @@ static void material_opaque(Material *ma, EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl; EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl; bool use_diffuse, use_glossy, use_refract; - + bool store_material = true; float *color_p = &ma->r; float *metal_p = &ma->metallic; float *spec_p = &ma->spec; @@ -1143,9 +1391,7 @@ static void material_opaque(Material *ma, EeveeMaterialShadingGroups *emsg = BLI_ghash_lookup(material_hash, (const void *)ma); if (emsg) { - *shgrp = emsg->shading_grp; - *shgrp_depth = emsg->depth_grp; - *shgrp_depth_clip = emsg->depth_clip_grp; + memcpy(shgrps, emsg, sizeof(EeveeMaterialShadingGroups)); /* This will have been created already, just perform a lookup. */ *gpumat = (use_gpumat) ? EEVEE_material_mesh_get(scene, ma, vedata, false, use_ssrefract) : @@ -1156,6 +1402,7 @@ static void material_opaque(Material *ma, return; } + emsg = MEM_callocN(sizeof(EeveeMaterialShadingGroups), "EeveeMaterialShadingGroups"); if (use_gpumat) { static float error_col[3] = {1.0f, 0.0f, 1.0f}; static float compile_col[3] = {0.5f, 0.5f, 0.5f}; @@ -1179,25 +1426,25 @@ static void material_opaque(Material *ma, status_mat_surface = status_mat_depth; } else if (use_ssrefract) { - *shgrp_depth = DRW_shgroup_material_create( + emsg->depth_grp = DRW_shgroup_material_create( *gpumat_depth, (do_cull) ? psl->refract_depth_pass_cull : psl->refract_depth_pass); - *shgrp_depth_clip = DRW_shgroup_material_create( + emsg->depth_clip_grp = DRW_shgroup_material_create( *gpumat_depth, (do_cull) ? psl->refract_depth_pass_clip_cull : psl->refract_depth_pass_clip); } else { - *shgrp_depth = DRW_shgroup_material_create( + emsg->depth_grp = DRW_shgroup_material_create( *gpumat_depth, (do_cull) ? psl->depth_pass_cull : psl->depth_pass); - *shgrp_depth_clip = DRW_shgroup_material_create( + emsg->depth_clip_grp = DRW_shgroup_material_create( *gpumat_depth, (do_cull) ? psl->depth_pass_clip_cull : psl->depth_pass_clip); } - if (*shgrp_depth != NULL) { + if (emsg->depth_grp != NULL) { use_diffuse = GPU_material_flag_get(*gpumat_depth, GPU_MATFLAG_DIFFUSE); use_glossy = GPU_material_flag_get(*gpumat_depth, GPU_MATFLAG_GLOSSY); use_refract = GPU_material_flag_get(*gpumat_depth, GPU_MATFLAG_REFRACT); - add_standard_uniforms(*shgrp_depth, + add_standard_uniforms(emsg->depth_grp, sldata, vedata, NULL, @@ -1206,8 +1453,9 @@ static void material_opaque(Material *ma, use_glossy, use_refract, false, - false); - add_standard_uniforms(*shgrp_depth_clip, + false, + DEFAULT_RENDER_PASS_FLAG); + add_standard_uniforms(emsg->depth_clip_grp, sldata, vedata, NULL, @@ -1216,11 +1464,13 @@ static void material_opaque(Material *ma, use_glossy, use_refract, false, - false); + false, + DEFAULT_RENDER_PASS_FLAG); if (ma->blend_method == MA_BM_CLIP) { - DRW_shgroup_uniform_float(*shgrp_depth, "alphaThreshold", &ma->alpha_threshold, 1); - DRW_shgroup_uniform_float(*shgrp_depth_clip, "alphaThreshold", &ma->alpha_threshold, 1); + DRW_shgroup_uniform_float(emsg->depth_grp, "alphaThreshold", &ma->alpha_threshold, 1); + DRW_shgroup_uniform_float( + emsg->depth_clip_grp, "alphaThreshold", &ma->alpha_threshold, 1); } } } @@ -1237,14 +1487,14 @@ static void material_opaque(Material *ma, use_glossy = GPU_material_flag_get(*gpumat, GPU_MATFLAG_GLOSSY); use_refract = GPU_material_flag_get(*gpumat, GPU_MATFLAG_REFRACT); - *shgrp = DRW_shgroup_material_create( + emsg->shading_grp = DRW_shgroup_material_create( *gpumat, (use_ssrefract) ? psl->refract_pass : (use_sss) ? ((do_cull) ? psl->sss_pass_cull : psl->sss_pass) : ((do_cull) ? psl->material_pass_cull : psl->material_pass)); - add_standard_uniforms(*shgrp, + add_standard_uniforms(emsg->shading_grp, sldata, vedata, ssr_id, @@ -1253,7 +1503,8 @@ static void material_opaque(Material *ma, use_glossy, use_refract, use_ssrefract, - false); + false, + DEFAULT_RENDER_PASS_FLAG); if (use_sss) { struct GPUTexture *sss_tex_profile = NULL; @@ -1264,7 +1515,7 @@ static void material_opaque(Material *ma, /* Limit of 8 bit stencil buffer. ID 255 is refraction. */ if (e_data.sss_count < 254) { int sss_id = e_data.sss_count + 1; - DRW_shgroup_stencil_mask(*shgrp, sss_id); + DRW_shgroup_stencil_mask(emsg->shading_grp, sss_id); EEVEE_subsurface_add_pass(sldata, vedata, sss_id, sss_profile); if (use_translucency) { EEVEE_subsurface_translucency_add_pass( @@ -1278,12 +1529,30 @@ static void material_opaque(Material *ma, } } } + + RENDER_PASS_ITER_BEGIN(stl->g_data->render_passes, render_pass_index, render_pass_flag) + emsg->material_accum_grp[render_pass_index] = DRW_shgroup_material_create( + *gpumat, psl->material_accum_pass[render_pass_index]); + add_standard_uniforms(emsg->material_accum_grp[render_pass_index], + sldata, + vedata, + ssr_id, + &ma->refract_depth, + use_diffuse, + use_glossy, + use_refract, + use_ssrefract, + false, + render_pass_flag); + RENDER_PASS_ITER_END(render_pass_index) + break; } case GPU_MAT_QUEUED: { stl->g_data->queued_shaders_count++; color_p = compile_col; metal_p = spec_p = rough_p = ½ + store_material = false; break; } case GPU_MAT_FAILED: @@ -1295,44 +1564,61 @@ static void material_opaque(Material *ma, } /* Fallback to default shader */ - if (*shgrp == NULL) { + if (emsg->shading_grp == NULL) { bool use_ssr = ((effects->enabled_effects & EFFECT_SSR) != 0); - *shgrp = EEVEE_default_shading_group_get( + emsg->shading_grp = EEVEE_default_shading_group_get( sldata, vedata, NULL, NULL, NULL, false, holdout, use_ssr); - DRW_shgroup_uniform_vec3(*shgrp, "basecol", color_p, 1); - DRW_shgroup_uniform_float(*shgrp, "metallic", metal_p, 1); - DRW_shgroup_uniform_float(*shgrp, "specular", spec_p, 1); - DRW_shgroup_uniform_float(*shgrp, "roughness", rough_p, 1); + DRW_shgroup_uniform_vec3(emsg->shading_grp, "basecol", color_p, 1); + DRW_shgroup_uniform_float(emsg->shading_grp, "metallic", metal_p, 1); + DRW_shgroup_uniform_float(emsg->shading_grp, "specular", spec_p, 1); + DRW_shgroup_uniform_float(emsg->shading_grp, "roughness", rough_p, 1); + + RENDER_PASS_ITER_BEGIN(stl->g_data->render_passes, render_pass_index, render_pass_flag) + DRWShadingGroup *shgrp = EEVEE_default_render_pass_shading_group_get( + sldata, + vedata, + holdout, + use_ssr, + psl->material_accum_pass[render_pass_index], + render_pass_flag); + + DRW_shgroup_uniform_vec3(shgrp, "basecol", color_p, 1); + DRW_shgroup_uniform_float(shgrp, "metallic", metal_p, 1); + DRW_shgroup_uniform_float(shgrp, "specular", spec_p, 1); + DRW_shgroup_uniform_float(shgrp, "roughness", rough_p, 1); + emsg->material_accum_grp[render_pass_index] = shgrp; + RENDER_PASS_ITER_END(render_pass_index) } /* Fallback default depth prepass */ - if (*shgrp_depth == NULL) { + if (emsg->depth_grp == NULL) { if (use_ssrefract) { - *shgrp_depth = (do_cull) ? stl->g_data->refract_depth_shgrp_cull : - stl->g_data->refract_depth_shgrp; - *shgrp_depth_clip = (do_cull) ? stl->g_data->refract_depth_shgrp_clip_cull : - stl->g_data->refract_depth_shgrp_clip; + emsg->depth_grp = (do_cull) ? stl->g_data->refract_depth_shgrp_cull : + stl->g_data->refract_depth_shgrp; + emsg->depth_clip_grp = (do_cull) ? stl->g_data->refract_depth_shgrp_clip_cull : + stl->g_data->refract_depth_shgrp_clip; } else { - *shgrp_depth = (do_cull) ? stl->g_data->depth_shgrp_cull : stl->g_data->depth_shgrp; - *shgrp_depth_clip = (do_cull) ? stl->g_data->depth_shgrp_clip_cull : - stl->g_data->depth_shgrp_clip; + emsg->depth_grp = (do_cull) ? stl->g_data->depth_shgrp_cull : stl->g_data->depth_shgrp; + emsg->depth_clip_grp = (do_cull) ? stl->g_data->depth_shgrp_clip_cull : + stl->g_data->depth_shgrp_clip; } } - emsg = MEM_mallocN(sizeof(EeveeMaterialShadingGroups), "EeveeMaterialShadingGroups"); - emsg->shading_grp = *shgrp; - emsg->depth_grp = *shgrp_depth; - emsg->depth_clip_grp = *shgrp_depth_clip; - BLI_ghash_insert(material_hash, ma, emsg); + memcpy(shgrps, emsg, sizeof(EeveeMaterialShadingGroups)); + if (store_material) { + BLI_ghash_insert(material_hash, ma, emsg); + } + else { + MEM_freeN(emsg); + } } static void material_transparent(Material *ma, EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, struct GPUMaterial **gpumat, - struct DRWShadingGroup **shgrp, - struct DRWShadingGroup **shgrp_depth) + struct EeveeMaterialShadingGroups *shgrps) { const DRWContextState *draw_ctx = DRW_context_state_get(); Scene *scene = draw_ctx->scene; @@ -1357,13 +1643,13 @@ static void material_transparent(Material *ma, /* Depth prepass */ if (use_prepass) { - *shgrp_depth = DRW_shgroup_create(e_data.default_prepass_clip_sh, psl->transparent_pass); + shgrps->depth_grp = DRW_shgroup_create(e_data.default_prepass_clip_sh, psl->transparent_pass); cur_state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL; cur_state |= (do_cull) ? DRW_STATE_CULL_BACK : 0; - DRW_shgroup_state_disable(*shgrp_depth, all_state); - DRW_shgroup_state_enable(*shgrp_depth, cur_state); + DRW_shgroup_state_disable(shgrps->depth_grp, all_state); + DRW_shgroup_state_enable(shgrps->depth_grp, cur_state); } if (use_gpumat) { @@ -1378,14 +1664,14 @@ static void material_transparent(Material *ma, case GPU_MAT_SUCCESS: { static int ssr_id = -1; /* TODO transparent SSR */ - *shgrp = DRW_shgroup_material_create(*gpumat, psl->transparent_pass); + shgrps->shading_grp = DRW_shgroup_material_create(*gpumat, psl->transparent_pass); bool use_blend = true; bool use_diffuse = GPU_material_flag_get(*gpumat, GPU_MATFLAG_DIFFUSE); bool use_glossy = GPU_material_flag_get(*gpumat, GPU_MATFLAG_GLOSSY); bool use_refract = GPU_material_flag_get(*gpumat, GPU_MATFLAG_REFRACT); - add_standard_uniforms(*shgrp, + add_standard_uniforms(shgrps->shading_grp, sldata, vedata, &ssr_id, @@ -1394,7 +1680,8 @@ static void material_transparent(Material *ma, use_glossy, use_refract, use_ssrefract, - use_blend); + use_blend, + DEFAULT_RENDER_PASS_FLAG); break; } case GPU_MAT_QUEUED: { @@ -1413,13 +1700,13 @@ static void material_transparent(Material *ma, } /* Fallback to default shader */ - if (*shgrp == NULL) { - *shgrp = EEVEE_default_shading_group_create( + if (shgrps->shading_grp == NULL) { + shgrps->shading_grp = EEVEE_default_shading_group_create( sldata, vedata, psl->transparent_pass, false, true, false); - DRW_shgroup_uniform_vec3(*shgrp, "basecol", color_p, 1); - DRW_shgroup_uniform_float(*shgrp, "metallic", metal_p, 1); - DRW_shgroup_uniform_float(*shgrp, "specular", spec_p, 1); - DRW_shgroup_uniform_float(*shgrp, "roughness", rough_p, 1); + DRW_shgroup_uniform_vec3(shgrps->shading_grp, "basecol", color_p, 1); + DRW_shgroup_uniform_float(shgrps->shading_grp, "metallic", metal_p, 1); + DRW_shgroup_uniform_float(shgrps->shading_grp, "specular", spec_p, 1); + DRW_shgroup_uniform_float(shgrps->shading_grp, "roughness", rough_p, 1); } cur_state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM; @@ -1427,8 +1714,8 @@ static void material_transparent(Material *ma, cur_state |= (do_cull) ? DRW_STATE_CULL_BACK : 0; /* Disable other blend modes and use the one we want. */ - DRW_shgroup_state_disable(*shgrp, all_state); - DRW_shgroup_state_enable(*shgrp, cur_state); + DRW_shgroup_state_disable(shgrps->shading_grp, all_state); + DRW_shgroup_state_enable(shgrps->shading_grp, cur_state); } /* Return correct material or empty default material if slot is empty. */ @@ -1460,10 +1747,7 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) { const int materials_len = DRW_cache_object_material_count_get(ob); - struct DRWShadingGroup **shgrp_array = BLI_array_alloca(shgrp_array, materials_len); - struct DRWShadingGroup **shgrp_depth_array = BLI_array_alloca(shgrp_depth_array, - materials_len); - struct DRWShadingGroup **shgrp_depth_clip_array = BLI_array_alloca(shgrp_depth_clip_array, + struct EeveeMaterialShadingGroups *shgrps_array = BLI_array_alloca(shgrps_array, materials_len); struct GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len); @@ -1472,11 +1756,9 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, for (int i = 0; i < materials_len; i++) { ma_array[i] = eevee_object_material_get(ob, i); + memset(&shgrps_array[i], 0, sizeof(EeveeMaterialShadingGroups)); gpumat_array[i] = NULL; gpumat_depth_array[i] = NULL; - shgrp_array[i] = NULL; - shgrp_depth_array[i] = NULL; - shgrp_depth_clip_array[i] = NULL; if (holdout) { material_opaque(ma_array[i], @@ -1485,9 +1767,7 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, vedata, &gpumat_array[i], &gpumat_depth_array[i], - &shgrp_array[i], - &shgrp_depth_array[i], - &shgrp_depth_clip_array[i], + &shgrps_array[i], true); continue; } @@ -1502,18 +1782,11 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, vedata, &gpumat_array[i], &gpumat_depth_array[i], - &shgrp_array[i], - &shgrp_depth_array[i], - &shgrp_depth_clip_array[i], + &shgrps_array[i], false); break; case MA_BM_BLEND: - material_transparent(ma_array[i], - sldata, - vedata, - &gpumat_array[i], - &shgrp_array[i], - &shgrp_depth_array[i]); + material_transparent(ma_array[i], sldata, vedata, &gpumat_array[i], &shgrps_array[i]); break; default: BLI_assert(0); @@ -1538,10 +1811,32 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, if (use_sculpt_pbvh) { /* Vcol is not supported in the modes that require PBVH drawing. */ - bool use_vcol = false; - DRW_shgroup_call_sculpt_with_materials(shgrp_array, ob, use_vcol); - DRW_shgroup_call_sculpt_with_materials(shgrp_depth_array, ob, use_vcol); - DRW_shgroup_call_sculpt_with_materials(shgrp_depth_clip_array, ob, use_vcol); + const bool use_vcol = false; + struct DRWShadingGroup **sculpt_shgrps_array = BLI_array_alloca(sculpt_shgrps_array, + materials_len); + for (int i = 0; i < materials_len; i++) { + sculpt_shgrps_array[i] = shgrps_array[i].shading_grp; + } + DRW_shgroup_call_sculpt_with_materials(sculpt_shgrps_array, ob, use_vcol); + + for (int i = 0; i < materials_len; i++) { + sculpt_shgrps_array[i] = shgrps_array[i].depth_grp; + } + DRW_shgroup_call_sculpt_with_materials(sculpt_shgrps_array, ob, use_vcol); + for (int i = 0; i < materials_len; i++) { + sculpt_shgrps_array[i] = shgrps_array[i].depth_clip_grp; + } + DRW_shgroup_call_sculpt_with_materials(sculpt_shgrps_array, ob, use_vcol); + + for (int renderpass_index = 0; + renderpass_index < stl->g_data->render_passes_material_count; + renderpass_index++) { + for (int i = 0; i < materials_len; i++) { + sculpt_shgrps_array[i] = shgrps_array[i].material_accum_grp[renderpass_index]; + } + DRW_shgroup_call_sculpt_with_materials(sculpt_shgrps_array, ob, use_vcol); + } + /* TODO(fclem): Support shadows in sculpt mode. */ } else if (mat_geom) { @@ -1565,10 +1860,16 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, oedata->ob = ob; oedata->test_data = &sldata->probes->vis_data; } - - ADD_SHGROUP_CALL(shgrp_array[i], ob, mat_geom[i], oedata); - ADD_SHGROUP_CALL_SAFE(shgrp_depth_array[i], ob, mat_geom[i], oedata); - ADD_SHGROUP_CALL_SAFE(shgrp_depth_clip_array[i], ob, mat_geom[i], oedata); + EeveeMaterialShadingGroups *shgrps = &shgrps_array[i]; + ADD_SHGROUP_CALL(shgrps->shading_grp, ob, mat_geom[i], oedata); + ADD_SHGROUP_CALL_SAFE(shgrps->depth_grp, ob, mat_geom[i], oedata); + ADD_SHGROUP_CALL_SAFE(shgrps->depth_clip_grp, ob, mat_geom[i], oedata); + for (int renderpass_index = 0; + renderpass_index < stl->g_data->render_passes_material_count; + renderpass_index++) { + ADD_SHGROUP_CALL_SAFE( + shgrps->material_accum_grp[renderpass_index], ob, mat_geom[i], oedata); + } /* Shadow Pass */ struct GPUMaterial *gpumat; @@ -1667,9 +1968,33 @@ void EEVEE_hair_cache_populate(EEVEE_Data *vedata, shgrp = DRW_shgroup_material_hair_create(ob, psys, md, psl->material_pass, gpumat); if (!use_diffuse && !use_glossy && !use_refract) { - /* FIXME: Small hack to avoid issue when utilTex is needed for + /* HACK: Small hack to avoid issue when utilTex is needed for + * world_normals_get and none of the bsdfs are present. + * This binds utilTex even if not needed. */ + DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex); + } + + add_standard_uniforms(shgrp, + sldata, + vedata, + &ssr_id, + NULL, + use_diffuse, + use_glossy, + use_refract, + false, + false, + DEFAULT_RENDER_PASS_FLAG); + + /* Add the hair to all the render_passes that are enabled */ + RENDER_PASS_ITER_BEGIN( + stl->g_data->render_passes, render_pass_index, render_pass_flag) + shgrp = DRW_shgroup_material_hair_create( + ob, psys, md, psl->material_accum_pass[render_pass_index], gpumat); + if (!use_diffuse && !use_glossy && !use_refract) { + /* Small hack to avoid issue when utilTex is needed for * world_normals_get and none of the bsdfs that need it are present. - * This can try to bind utilTex even if not needed. */ + * This binds `utilTex` even if not needed. */ DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex); } @@ -1682,7 +2007,10 @@ void EEVEE_hair_cache_populate(EEVEE_Data *vedata, use_glossy, use_refract, false, - false); + false, + render_pass_flag); + RENDER_PASS_ITER_END(render_pass_index) + break; } case GPU_MAT_QUEUED: { @@ -1707,6 +2035,24 @@ void EEVEE_hair_cache_populate(EEVEE_Data *vedata, DRW_shgroup_uniform_float(shgrp, "metallic", metal_p, 1); DRW_shgroup_uniform_float(shgrp, "specular", spec_p, 1); DRW_shgroup_uniform_float(shgrp, "roughness", rough_p, 1); + + RENDER_PASS_ITER_BEGIN(stl->g_data->render_passes, render_pass_index, render_pass_flag) + shgrp = EEVEE_default_hair_render_pass_shading_group_get( + sldata, + vedata, + ob, + psys, + md, + holdout, + use_ssr, + psl->material_accum_pass[render_pass_index], + render_pass_flag); + + DRW_shgroup_uniform_vec3(shgrp, "basecol", color_p, 1); + DRW_shgroup_uniform_float(shgrp, "metallic", metal_p, 1); + DRW_shgroup_uniform_float(shgrp, "specular", spec_p, 1); + DRW_shgroup_uniform_float(shgrp, "roughness", rough_p, 1); + RENDER_PASS_ITER_END(render_pass_index) } /* Shadows */ @@ -1762,3 +2108,180 @@ void EEVEE_materials_draw_opaque(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Pass DRW_draw_pass(psl->material_pass); DRW_draw_pass(psl->material_pass_cull); } + +/* -------------------------------------------------------------------- */ + +/** \name Render Passes + * \{ */ + +void EEVEE_material_renderpasses_init(EEVEE_Data *vedata) +{ + EEVEE_StorageList *stl = vedata->stl; + EEVEE_PrivateData *g_data = stl->g_data; + + /* For diffuse and glossy we calculate the final light + color buffer where we extract the + * light from by dividing by the color buffer. When one the light is requested we also tag + * the color buffer to do the extraction. */ + if (g_data->render_passes & EEVEE_RENDER_PASS_DIFFUSE_LIGHT) { + g_data->render_passes |= EEVEE_RENDER_PASS_DIFFUSE_COLOR; + } + if (g_data->render_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT) { + g_data->render_passes |= EEVEE_RENDER_PASS_SPECULAR_COLOR; + } + + /* Calculate the number of material based render passes */ + uint num_render_passes = count_bits_i(stl->g_data->render_passes & EEVEE_RENDERPASSES_MATERIAL); + if ((num_render_passes != 0 && stl->g_data->render_passes & EEVEE_RENDER_PASS_ENVIRONMENT) == + 0) { + num_render_passes += 1; + } + stl->g_data->render_passes_material_count = num_render_passes; +} + +void EEVEE_material_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, uint tot_samples) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + EEVEE_FramebufferList *fbl = vedata->fbl; + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + EEVEE_TextureList *txl = vedata->txl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_PassList *psl = vedata->psl; + EEVEE_EffectsInfo *effects = stl->effects; + + float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + + /* Create FrameBuffer. */ + + /* Should be enough precision for many samples. */ + const eGPUTextureFormat texture_format_material_accum = (tot_samples > 128) ? GPU_RGBA32F : + GPU_RGBA16F; + const eViewLayerEEVEEPassType render_passes = stl->g_data->render_passes & + EEVEE_RENDERPASSES_MATERIAL; + if (render_passes != 0) { + GPU_framebuffer_ensure_config(&fbl->material_accum_fb, + {GPU_ATTACHMENT_TEXTURE(dtxl->depth), GPU_ATTACHMENT_LEAVE}); + int render_pass_index = ((render_passes & EEVEE_RENDER_PASS_ENVIRONMENT) != 0) ? 0 : 1; + for (int bit = 0; bit < 32; bit++) { + eViewLayerEEVEEPassType bitflag = (1 << bit); + if ((render_passes & bitflag) != 0) { + + DRW_texture_ensure_fullscreen_2d( + &txl->material_accum[render_pass_index], texture_format_material_accum, 0); + + /* Clear texture. */ + if (DRW_state_is_image_render() || effects->taa_current_sample == 1) { + GPU_framebuffer_texture_attach( + fbl->material_accum_fb, txl->material_accum[render_pass_index], 0, 0); + GPU_framebuffer_bind(fbl->material_accum_fb); + GPU_framebuffer_clear_color(fbl->material_accum_fb, clear); + GPU_framebuffer_bind(fbl->main_fb); + GPU_framebuffer_texture_detach(fbl->material_accum_fb, + txl->material_accum[render_pass_index]); + } + render_pass_index++; + } + } + + if ((render_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT) && + (effects->enabled_effects & EFFECT_SSR)) { + EEVEE_reflection_output_init(sldata, vedata, tot_samples); + } + + if (render_passes & EEVEE_RENDER_PASS_ENVIRONMENT) { + Scene *scene = draw_ctx->scene; + World *wo = scene->world; + + if (wo && wo->use_nodes && wo->nodetree) { + struct GPUMaterial *gpumat = EEVEE_material_world_background_get(scene, wo); + if (GPU_material_status(gpumat) == GPU_MAT_SUCCESS) { + DRWShadingGroup *grp = DRW_shgroup_material_create(gpumat, psl->material_accum_pass[0]); + add_background_uniforms(grp, sldata, vedata); + DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL); + } + } + } + } +} + +void EEVEE_material_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) +{ + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_PassList *psl = vedata->psl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_TextureList *txl = vedata->txl; + + if (fbl->material_accum_fb != NULL) { + for (int renderpass_index = 0; renderpass_index < stl->g_data->render_passes_material_count; + renderpass_index++) { + if (txl->material_accum[renderpass_index] != NULL) { + GPU_framebuffer_texture_attach( + fbl->material_accum_fb, txl->material_accum[renderpass_index], 0, 0); + GPU_framebuffer_bind(fbl->material_accum_fb); + DRW_draw_pass(psl->material_accum_pass[renderpass_index]); + GPU_framebuffer_bind(fbl->main_fb); + GPU_framebuffer_texture_detach(fbl->material_accum_fb, + txl->material_accum[renderpass_index]); + } + } + if ((stl->g_data->render_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT) && + (stl->effects->enabled_effects & EFFECT_SSR)) { + EEVEE_reflection_output_accumulate(sldata, vedata); + } + } +} + +int EEVEE_material_output_pass_index_get(EEVEE_ViewLayerData *UNUSED(sldata), + EEVEE_Data *vedata, + eViewLayerEEVEEPassType renderpass_type) +{ + EEVEE_StorageList *stl = vedata->stl; + + BLI_assert((stl->g_data->render_passes & EEVEE_RENDERPASSES_MATERIAL) != 0); + BLI_assert((stl->g_data->render_passes & EEVEE_RENDERPASSES_MATERIAL & renderpass_type) != 0); + + /* pass_index 0 is reserved for the environment pass. */ + if ((stl->g_data->render_passes & EEVEE_RENDER_PASS_ENVIRONMENT & renderpass_type) != 0) { + return 0; + } + + /* pass_index 0 is reserved for the environment pass. Other passes start from index 1 */ + int index = 1; + eViewLayerEEVEEPassType active_material_passes = stl->g_data->render_passes & + EEVEE_RENDERPASSES_MATERIAL & + ~EEVEE_RENDER_PASS_ENVIRONMENT; + + for (int bitshift = 0; bitshift < 32; bitshift++) { + eViewLayerEEVEEPassType pass_flag = (1 << bitshift); + if (pass_flag == renderpass_type) { + break; + } + if (active_material_passes & pass_flag) { + index++; + } + } + + return index; +} + +/* Get the pass index that contains the color pass for the given renderpass_type. */ +int EEVEE_material_output_color_pass_index_get(EEVEE_ViewLayerData *sldata, + EEVEE_Data *vedata, + eViewLayerEEVEEPassType renderpass_type) +{ + BLI_assert( + ELEM(renderpass_type, EEVEE_RENDER_PASS_DIFFUSE_LIGHT, EEVEE_RENDER_PASS_SPECULAR_LIGHT)); + eViewLayerEEVEEPassType color_pass_type; + switch (renderpass_type) { + case EEVEE_RENDER_PASS_DIFFUSE_LIGHT: + color_pass_type = EEVEE_RENDER_PASS_DIFFUSE_COLOR; + break; + case EEVEE_RENDER_PASS_SPECULAR_LIGHT: + color_pass_type = EEVEE_RENDER_PASS_SPECULAR_COLOR; + break; + default: + color_pass_type = 0; + BLI_assert(false); + } + return EEVEE_material_output_pass_index_get(sldata, vedata, color_pass_type); +} +/* \} */ diff --git a/source/blender/draw/engines/eevee/eevee_mist.c b/source/blender/draw/engines/eevee/eevee_mist.c index c9b56a6d551..cdcfd64d995 100644 --- a/source/blender/draw/engines/eevee/eevee_mist.c +++ b/source/blender/draw/engines/eevee/eevee_mist.c @@ -114,6 +114,8 @@ void EEVEE_mist_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRWShadingGroup *grp = DRW_shgroup_create(e_data.mist_sh, psl->mist_accum_ps); DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_block( + grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); DRW_shgroup_uniform_vec3(grp, "mistSettings", &g_data->mist_start, 1); DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL); } diff --git a/source/blender/draw/engines/eevee/eevee_occlusion.c b/source/blender/draw/engines/eevee/eevee_occlusion.c index 6ba518b3a28..be4dfd07ce1 100644 --- a/source/blender/draw/engines/eevee/eevee_occlusion.c +++ b/source/blender/draw/engines/eevee/eevee_occlusion.c @@ -170,6 +170,8 @@ void EEVEE_occlusion_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata DRW_shgroup_uniform_texture_ref(grp, "normalBuffer", &effects->ssr_normal_input); DRW_shgroup_uniform_texture_ref(grp, "horizonBuffer", &effects->gtao_horizons); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_block( + grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL); } else { @@ -207,6 +209,8 @@ void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_shgroup_uniform_texture_ref(grp, "maxzBuffer", &txl->maxzbuffer); DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &effects->ao_src_depth); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_block( + grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); DRW_shgroup_call(grp, quad, NULL); DRW_PASS_CREATE(psl->ao_horizon_search_layer, DRW_STATE_WRITE_COLOR); @@ -215,6 +219,8 @@ void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_shgroup_uniform_texture_ref(grp, "maxzBuffer", &txl->maxzbuffer); DRW_shgroup_uniform_texture_ref(grp, "depthBufferLayered", &effects->ao_src_depth); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_block( + grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); DRW_shgroup_uniform_int(grp, "layer", &stl->effects->ao_depth_layer, 1); DRW_shgroup_call(grp, quad, NULL); @@ -227,6 +233,8 @@ void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_shgroup_uniform_texture_ref(grp, "normalBuffer", &effects->ssr_normal_input); DRW_shgroup_uniform_texture_ref(grp, "horizonBuffer", &effects->gtao_horizons); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_block( + grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); DRW_shgroup_call(grp, quad, NULL); } } diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index 7810de289df..db29e103226 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -141,6 +141,13 @@ extern struct DrawEngineType draw_engine_eevee_type; #define MIN_CUBE_LOD_LEVEL 3 #define MAX_PLANAR_LOD_LEVEL 9 +/* All the renderpasses that use the GPUMaterial for accumulation */ +#define EEVEE_RENDERPASSES_MATERIAL \ + (EEVEE_RENDER_PASS_EMIT | EEVEE_RENDER_PASS_DIFFUSE_COLOR | EEVEE_RENDER_PASS_DIFFUSE_LIGHT | \ + EEVEE_RENDER_PASS_SPECULAR_COLOR | EEVEE_RENDER_PASS_SPECULAR_LIGHT | \ + EEVEE_RENDER_PASS_ENVIRONMENT) +#define MAX_MATERIAL_RENDER_PASSES 6 +#define MAX_MATERIAL_RENDER_PASSES_UBO 6 /* World shader variations */ enum { VAR_WORLD_BACKGROUND = 0, @@ -198,6 +205,7 @@ typedef struct EEVEE_BoundBox { typedef struct EEVEE_PassList { /* Shadows */ struct DRWPass *shadow_pass; + struct DRWPass *shadow_accum_pass; /* Probes */ struct DRWPass *probe_background; @@ -220,6 +228,7 @@ typedef struct EEVEE_PassList { struct DRWPass *bloom_downsample; struct DRWPass *bloom_upsample; struct DRWPass *bloom_resolve; + struct DRWPass *bloom_accum_ps; struct DRWPass *dof_down; struct DRWPass *dof_scatter; struct DRWPass *dof_resolve; @@ -228,11 +237,11 @@ typedef struct EEVEE_PassList { struct DRWPass *volumetric_scatter_ps; struct DRWPass *volumetric_integration_ps; struct DRWPass *volumetric_resolve_ps; + struct DRWPass *volumetric_accum_ps; struct DRWPass *ssr_raytrace; struct DRWPass *ssr_resolve; struct DRWPass *sss_blur_ps; struct DRWPass *sss_resolve_ps; - struct DRWPass *sss_accum_ps; struct DRWPass *sss_translucency_ps; struct DRWPass *color_downsample_ps; struct DRWPass *color_downsample_cube_ps; @@ -264,6 +273,7 @@ typedef struct EEVEE_PassList { struct DRWPass *sss_pass_cull; struct DRWPass *material_pass; struct DRWPass *material_pass_cull; + struct DRWPass *material_accum_pass[MAX_MATERIAL_RENDER_PASSES]; struct DRWPass *refract_pass; struct DRWPass *transparent_pass; struct DRWPass *background_pass; @@ -281,6 +291,9 @@ typedef struct EEVEE_FramebufferList { struct GPUFrameBuffer *bloom_blit_fb; struct GPUFrameBuffer *bloom_down_fb[MAX_BLOOM_STEP]; struct GPUFrameBuffer *bloom_accum_fb[MAX_BLOOM_STEP - 1]; + struct GPUFrameBuffer *bloom_pass_accum_fb; + struct GPUFrameBuffer *shadow_accum_fb; + struct GPUFrameBuffer *ssr_accum_fb; struct GPUFrameBuffer *sss_blur_fb; struct GPUFrameBuffer *sss_blit_fb; struct GPUFrameBuffer *sss_resolve_fb; @@ -292,9 +305,11 @@ typedef struct EEVEE_FramebufferList { struct GPUFrameBuffer *volumetric_fb; struct GPUFrameBuffer *volumetric_scat_fb; struct GPUFrameBuffer *volumetric_integ_fb; + struct GPUFrameBuffer *volumetric_accum_fb; struct GPUFrameBuffer *screen_tracing_fb; struct GPUFrameBuffer *refract_fb; struct GPUFrameBuffer *mist_accum_fb; + struct GPUFrameBuffer *material_accum_fb; struct GPUFrameBuffer *renderpass_fb; struct GPUFrameBuffer *ao_accum_fb; struct GPUFrameBuffer *velocity_resolve_fb; @@ -320,8 +335,11 @@ typedef struct EEVEE_TextureList { struct GPUTexture *color_post; /* R16_G16_B16 */ struct GPUTexture *mist_accum; struct GPUTexture *ao_accum; - struct GPUTexture *sss_dir_accum; - struct GPUTexture *sss_col_accum; + struct GPUTexture *sss_accum; + struct GPUTexture *material_accum[MAX_MATERIAL_RENDER_PASSES]; + struct GPUTexture *bloom_accum; + struct GPUTexture *ssr_accum; + struct GPUTexture *shadow_accum; struct GPUTexture *refract_color; struct GPUTexture *taa_history; @@ -333,6 +351,8 @@ typedef struct EEVEE_TextureList { struct GPUTexture *volume_transmit; struct GPUTexture *volume_scatter_history; struct GPUTexture *volume_transmit_history; + struct GPUTexture *volume_scatter_accum; + struct GPUTexture *volume_transmittance_accum; struct GPUTexture *lookdev_grid_tx; struct GPUTexture *lookdev_cube_tx; @@ -361,6 +381,17 @@ typedef struct EEVEE_StorageList { LightCacheTexture *lookdev_cube_mips; } EEVEE_StorageList; +/* ************ RENDERPASS UBO ************* */ +typedef struct EEVEE_RenderPassData { + int renderPassDiffuse; + int renderPassDiffuseLight; + int renderPassGlossy; + int renderPassGlossyLight; + int renderPassEmit; + int renderPassSSSColor; + int _pad[2]; +} EEVEE_RenderPassData; + /* ************ LIGHT UBO ************* */ typedef struct EEVEE_Light { float position[3], invsqrdist; @@ -408,6 +439,7 @@ BLI_STATIC_ASSERT_ALIGN(EEVEE_Light, 16) BLI_STATIC_ASSERT_ALIGN(EEVEE_Shadow, 16) BLI_STATIC_ASSERT_ALIGN(EEVEE_ShadowCube, 16) BLI_STATIC_ASSERT_ALIGN(EEVEE_ShadowCascade, 16) +BLI_STATIC_ASSERT_ALIGN(EEVEE_RenderPassData, 16) BLI_STATIC_ASSERT(sizeof(EEVEE_Shadow) * MAX_SHADOW + sizeof(EEVEE_ShadowCascade) * MAX_SHADOW_CASCADE + @@ -708,6 +740,10 @@ typedef struct EEVEE_ViewLayerData { struct GPUUniformBuffer *grid_ubo; struct GPUUniformBuffer *planar_ubo; + /* Material Render passes */ + struct EEVEE_RenderPassData renderpass_data[MAX_MATERIAL_RENDER_PASSES_UBO]; + struct GPUUniformBuffer *renderpass_ubo[MAX_MATERIAL_RENDER_PASSES_UBO]; + /* Common Uniform Buffer */ struct EEVEE_CommonUniformBuffer common_data; struct GPUUniformBuffer *common_ubo; @@ -759,6 +795,7 @@ typedef struct EEVEE_Data { typedef struct EEVEE_PrivateData { struct DRWShadingGroup *shadow_shgrp; + struct DRWShadingGroup *shadow_accum_shgrp; struct DRWShadingGroup *depth_shgrp; struct DRWShadingGroup *depth_shgrp_cull; struct DRWShadingGroup *depth_shgrp_clip; @@ -803,12 +840,17 @@ typedef struct EEVEE_PrivateData { /* Renderpasses */ /* Bitmask containing the active render_passes */ - eScenePassType render_passes; + eViewLayerEEVEEPassType render_passes; /* Uniform references that are referenced inside the `renderpass_pass`. They are updated * to reuse the drawing pass and the shading group. */ int renderpass_type; + int renderpass_postprocess; int renderpass_current_sample; GPUTexture *renderpass_input; + GPUTexture *renderpass_col_input; + GPUTexture *renderpass_light_input; + /* The number of active material based render passes */ + uint render_passes_material_count; /** For rendering shadows. */ struct DRWView *cube_views[6]; @@ -860,11 +902,20 @@ struct GPUMaterial *EEVEE_material_mesh_depth_get(struct Scene *scene, bool use_hashed_alpha, bool is_shadow); struct GPUMaterial *EEVEE_material_hair_get(struct Scene *scene, Material *ma); +struct GPUUniformBuffer *EEVEE_material_default_render_pass_ubo_get(EEVEE_ViewLayerData *sldata); void EEVEE_materials_free(void); void EEVEE_materials_draw_opaque(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl); void EEVEE_update_noise(EEVEE_PassList *psl, EEVEE_FramebufferList *fbl, const double offsets[3]); void EEVEE_update_viewvecs(float invproj[4][4], float winmat[4][4], float (*r_viewvecs)[4]); - +void EEVEE_material_renderpasses_init(EEVEE_Data *vedata); +void EEVEE_material_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, uint tot_samples); +void EEVEE_material_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +int EEVEE_material_output_pass_index_get(EEVEE_ViewLayerData *UNUSED(sldata), + EEVEE_Data *vedata, + eViewLayerEEVEEPassType renderpass_type); +int EEVEE_material_output_color_pass_index_get(EEVEE_ViewLayerData *sldata, + EEVEE_Data *vedata, + eViewLayerEEVEEPassType renderpass_type); /* eevee_lights.c */ void eevee_light_matrix_get(const EEVEE_Light *evli, float r_mat[4][4]); void EEVEE_lights_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); @@ -896,6 +947,8 @@ void EEVEE_shadows_draw_cascades(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, DRWView *view, int cascade_index); +void EEVEE_shadow_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, uint tot_samples); +void EEVEE_shadow_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_shadows_free(void); /* eevee_sampling.c */ @@ -995,6 +1048,8 @@ void EEVEE_depth_of_field_free(void); int EEVEE_bloom_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_bloom_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_bloom_draw(EEVEE_Data *vedata); +void EEVEE_bloom_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, uint tot_samples); +void EEVEE_bloom_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_bloom_free(void); /* eevee_occlusion.c */ @@ -1016,6 +1071,11 @@ int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_refraction_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_reflection_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_reflection_output_init(EEVEE_ViewLayerData *sldata, + EEVEE_Data *vedata, + uint tot_samples); +void EEVEE_reflection_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); + void EEVEE_screen_raytrace_free(void); /* eevee_subsurface.c */ @@ -1055,10 +1115,12 @@ 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_output_accumulate(EEVEE_ViewLayerData *sldata, + EEVEE_Data *vedata, + bool post_effect); void EEVEE_renderpasses_postprocess(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, - eScenePassType renderpass_type); + eViewLayerEEVEEPassType renderpass_type); void EEVEE_renderpasses_draw(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_renderpasses_draw_debug(EEVEE_Data *vedata); void EEVEE_renderpasses_free(void); @@ -1087,6 +1149,8 @@ void EEVEE_volumes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) void EEVEE_volumes_draw_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_volumes_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_volumes_resolve(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_volumes_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, uint tot_samples); +void EEVEE_volumes_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_volumes_free_smoke_textures(void); void EEVEE_volumes_free(void); diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c index 063510d51e6..9b20f006387 100644 --- a/source/blender/draw/engines/eevee/eevee_render.c +++ b/source/blender/draw/engines/eevee/eevee_render.c @@ -230,6 +230,9 @@ static void eevee_render_color_result(RenderLayer *rl, EEVEE_Data *vedata) { RenderPass *rp = RE_pass_find_by_name(rl, render_pass_name, viewname); + if (rp == NULL) { + return; + } GPU_framebuffer_bind(framebuffer); GPU_framebuffer_read_color(framebuffer, vedata->stl->g_data->overscan_pixels + rect->xmin, @@ -251,35 +254,6 @@ static void eevee_render_result_combined(RenderLayer *rl, 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 *sldata) -{ - if (vedata->fbl->sss_accum_fb == NULL) { - /* SSS is not enabled. */ - return; - } - - 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 ((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 ((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. */ - } -} - static void eevee_render_result_normal(RenderLayer *rl, const char *viewname, const rcti *rect, @@ -293,8 +267,8 @@ static void eevee_render_result_normal(RenderLayer *rl, return; } - if ((vedata->stl->g_data->render_passes & SCE_PASS_NORMAL) != 0) { - EEVEE_renderpasses_postprocess(sldata, vedata, SCE_PASS_NORMAL); + if ((vedata->stl->g_data->render_passes & EEVEE_RENDER_PASS_NORMAL) != 0) { + EEVEE_renderpasses_postprocess(sldata, vedata, EEVEE_RENDER_PASS_NORMAL); eevee_render_color_result( rl, viewname, rect, RE_PASSNAME_NORMAL, 3, vedata->fbl->renderpass_fb, vedata); } @@ -313,8 +287,8 @@ static void eevee_render_result_z(RenderLayer *rl, return; } - if ((vedata->stl->g_data->render_passes & SCE_PASS_Z) != 0) { - EEVEE_renderpasses_postprocess(sldata, vedata, SCE_PASS_Z); + if ((vedata->stl->g_data->render_passes & EEVEE_RENDER_PASS_Z) != 0) { + EEVEE_renderpasses_postprocess(sldata, vedata, EEVEE_RENDER_PASS_Z); eevee_render_color_result( rl, viewname, rect, RE_PASSNAME_Z, 1, vedata->fbl->renderpass_fb, vedata); } @@ -326,31 +300,142 @@ static void eevee_render_result_mist(RenderLayer *rl, EEVEE_Data *vedata, EEVEE_ViewLayerData *sldata) { - if ((vedata->stl->g_data->render_passes & SCE_PASS_MIST) != 0) { - EEVEE_renderpasses_postprocess(sldata, vedata, SCE_PASS_MIST); + if ((vedata->stl->g_data->render_passes & EEVEE_RENDER_PASS_MIST) != 0) { + EEVEE_renderpasses_postprocess(sldata, vedata, EEVEE_RENDER_PASS_MIST); eevee_render_color_result( rl, viewname, rect, RE_PASSNAME_MIST, 1, vedata->fbl->renderpass_fb, vedata); } } +static void eevee_render_result_shadow(RenderLayer *rl, + const char *viewname, + const rcti *rect, + EEVEE_Data *vedata, + EEVEE_ViewLayerData *sldata) +{ + if ((vedata->stl->g_data->render_passes & EEVEE_RENDER_PASS_SHADOW) != 0) { + EEVEE_renderpasses_postprocess(sldata, vedata, EEVEE_RENDER_PASS_SHADOW); + eevee_render_color_result( + rl, viewname, rect, RE_PASSNAME_SHADOW, 3, vedata->fbl->renderpass_fb, vedata); + } +} + static void eevee_render_result_occlusion(RenderLayer *rl, const char *viewname, const rcti *rect, EEVEE_Data *vedata, EEVEE_ViewLayerData *sldata) { - if (vedata->fbl->ao_accum_fb == NULL) { + if ((vedata->stl->effects->enabled_effects & EFFECT_GTAO) == 0) { /* AO is not enabled. */ return; } - if ((vedata->stl->g_data->render_passes & SCE_PASS_AO) != 0) { - EEVEE_renderpasses_postprocess(sldata, vedata, SCE_PASS_AO); + if ((vedata->stl->g_data->render_passes & EEVEE_RENDER_PASS_AO) != 0) { + EEVEE_renderpasses_postprocess(sldata, vedata, EEVEE_RENDER_PASS_AO); eevee_render_color_result( rl, viewname, rect, RE_PASSNAME_AO, 3, vedata->fbl->renderpass_fb, vedata); } } +static void eevee_render_result_bloom(RenderLayer *rl, + const char *viewname, + const rcti *rect, + EEVEE_Data *vedata, + EEVEE_ViewLayerData *sldata) +{ + if ((vedata->stl->effects->enabled_effects & EFFECT_BLOOM) == 0) { + /* Bloom is not enabled. */ + return; + } + + if ((vedata->stl->g_data->render_passes & EEVEE_RENDER_PASS_BLOOM) != 0) { + EEVEE_renderpasses_postprocess(sldata, vedata, EEVEE_RENDER_PASS_BLOOM); + eevee_render_color_result( + rl, viewname, rect, RE_PASSNAME_BLOOM, 3, vedata->fbl->renderpass_fb, vedata); + } +} + +#define EEVEE_RENDER_RESULT_MATERIAL_PASS(pass_name, eevee_pass_type) \ + if ((vedata->stl->g_data->render_passes & EEVEE_RENDER_PASS_##eevee_pass_type) != 0) { \ + EEVEE_renderpasses_postprocess(sldata, vedata, EEVEE_RENDER_PASS_##eevee_pass_type); \ + eevee_render_color_result( \ + rl, viewname, rect, RE_PASSNAME_##pass_name, 3, vedata->fbl->renderpass_fb, vedata); \ + } + +static void eevee_render_result_diffuse_color(RenderLayer *rl, + const char *viewname, + const rcti *rect, + EEVEE_Data *vedata, + EEVEE_ViewLayerData *sldata) +{ + EEVEE_RENDER_RESULT_MATERIAL_PASS(DIFFUSE_COLOR, DIFFUSE_COLOR) +} + +static void eevee_render_result_diffuse_direct(RenderLayer *rl, + const char *viewname, + const rcti *rect, + EEVEE_Data *vedata, + EEVEE_ViewLayerData *sldata) +{ + EEVEE_RENDER_RESULT_MATERIAL_PASS(DIFFUSE_DIRECT, DIFFUSE_LIGHT) +} + +static void eevee_render_result_specular_color(RenderLayer *rl, + const char *viewname, + const rcti *rect, + EEVEE_Data *vedata, + EEVEE_ViewLayerData *sldata) +{ + EEVEE_RENDER_RESULT_MATERIAL_PASS(GLOSSY_COLOR, SPECULAR_COLOR) +} + +static void eevee_render_result_specular_direct(RenderLayer *rl, + const char *viewname, + const rcti *rect, + EEVEE_Data *vedata, + EEVEE_ViewLayerData *sldata) +{ + EEVEE_RENDER_RESULT_MATERIAL_PASS(GLOSSY_DIRECT, SPECULAR_LIGHT) +} + +static void eevee_render_result_emission(RenderLayer *rl, + const char *viewname, + const rcti *rect, + EEVEE_Data *vedata, + EEVEE_ViewLayerData *sldata) +{ + EEVEE_RENDER_RESULT_MATERIAL_PASS(EMIT, EMIT) +} + +static void eevee_render_result_environment(RenderLayer *rl, + const char *viewname, + const rcti *rect, + EEVEE_Data *vedata, + EEVEE_ViewLayerData *sldata) +{ + EEVEE_RENDER_RESULT_MATERIAL_PASS(ENVIRONMENT, ENVIRONMENT) +} + +static void eevee_render_result_volume_scatter(RenderLayer *rl, + const char *viewname, + const rcti *rect, + EEVEE_Data *vedata, + EEVEE_ViewLayerData *sldata) +{ + EEVEE_RENDER_RESULT_MATERIAL_PASS(VOLUME_SCATTER, VOLUME_SCATTER) +} +static void eevee_render_result_volume_transmittance(RenderLayer *rl, + const char *viewname, + const rcti *rect, + EEVEE_Data *vedata, + EEVEE_ViewLayerData *sldata) +{ + EEVEE_RENDER_RESULT_MATERIAL_PASS(VOLUME_TRANSMITTANCE, VOLUME_TRANSMITTANCE) +} + +#undef EEVEE_RENDER_RESULT_MATERIAL_PASS + static void eevee_render_draw_background(EEVEE_Data *vedata) { EEVEE_FramebufferList *fbl = vedata->fbl; @@ -508,7 +593,7 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl /* Volumetrics Resolve Opaque */ EEVEE_volumes_resolve(sldata, vedata); /* Subsurface output, Occlusion output, Mist output */ - EEVEE_renderpasses_output_accumulate(sldata, vedata); + EEVEE_renderpasses_output_accumulate(sldata, vedata, false); /* Transparent */ GPU_framebuffer_texture_attach(fbl->main_color_fb, dtxl->depth, 0, 0); GPU_framebuffer_bind(fbl->main_color_fb); @@ -527,9 +612,18 @@ 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); eevee_render_result_mist(rl, viewname, rect, vedata, sldata); eevee_render_result_occlusion(rl, viewname, rect, vedata, sldata); + eevee_render_result_shadow(rl, viewname, rect, vedata, sldata); + eevee_render_result_diffuse_color(rl, viewname, rect, vedata, sldata); + eevee_render_result_diffuse_direct(rl, viewname, rect, vedata, sldata); + eevee_render_result_specular_color(rl, viewname, rect, vedata, sldata); + eevee_render_result_specular_direct(rl, viewname, rect, vedata, sldata); + eevee_render_result_emission(rl, viewname, rect, vedata, sldata); + eevee_render_result_environment(rl, viewname, rect, vedata, sldata); + eevee_render_result_bloom(rl, viewname, rect, vedata, sldata); + eevee_render_result_volume_scatter(rl, viewname, rect, vedata, sldata); + eevee_render_result_volume_transmittance(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]}); @@ -537,29 +631,35 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl void EEVEE_render_update_passes(RenderEngine *engine, Scene *scene, ViewLayer *view_layer) { - int type; - RE_engine_register_pass(engine, scene, view_layer, RE_PASSNAME_COMBINED, 4, "RGBA", SOCK_RGBA); -#define CHECK_PASS(name, channels, chanid) \ +#define CHECK_PASS_LEGACY(name, type, channels, chanid) \ if (view_layer->passflag & (SCE_PASS_##name)) { \ - if (channels == 4) \ - type = SOCK_RGBA; \ - else if (channels == 3) \ - type = SOCK_VECTOR; \ - else \ - type = SOCK_FLOAT; \ + RE_engine_register_pass( \ + engine, scene, view_layer, RE_PASSNAME_##name, channels, chanid, type); \ + } \ + ((void)0) +#define CHECK_PASS_EEVEE(name, type, channels, chanid) \ + if (view_layer->eevee.render_passes & (EEVEE_RENDER_PASS_##name)) { \ RE_engine_register_pass( \ engine, scene, view_layer, RE_PASSNAME_##name, channels, chanid, type); \ } \ ((void)0) - 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"); + CHECK_PASS_LEGACY(Z, SOCK_FLOAT, 1, "Z"); + CHECK_PASS_LEGACY(MIST, SOCK_FLOAT, 1, "Z"); + CHECK_PASS_LEGACY(NORMAL, SOCK_VECTOR, 3, "XYZ"); + CHECK_PASS_LEGACY(SHADOW, SOCK_RGBA, 3, "RGB"); + CHECK_PASS_LEGACY(AO, SOCK_RGBA, 3, "RGB"); + CHECK_PASS_LEGACY(DIFFUSE_COLOR, SOCK_RGBA, 3, "RGB"); + CHECK_PASS_LEGACY(DIFFUSE_DIRECT, SOCK_RGBA, 3, "RGB"); + CHECK_PASS_LEGACY(GLOSSY_COLOR, SOCK_RGBA, 3, "RGB"); + CHECK_PASS_LEGACY(GLOSSY_DIRECT, SOCK_RGBA, 3, "RGB"); + CHECK_PASS_LEGACY(EMIT, SOCK_RGBA, 3, "RGB"); + CHECK_PASS_LEGACY(ENVIRONMENT, SOCK_RGBA, 3, "RGB"); + CHECK_PASS_EEVEE(VOLUME_SCATTER, SOCK_RGBA, 3, "RGB"); + CHECK_PASS_EEVEE(VOLUME_TRANSMITTANCE, SOCK_RGBA, 3, "RGB"); + CHECK_PASS_EEVEE(BLOOM, SOCK_RGBA, 3, "RGB"); #undef CHECK_PASS } diff --git a/source/blender/draw/engines/eevee/eevee_renderpasses.c b/source/blender/draw/engines/eevee/eevee_renderpasses.c index 44a6c41e170..2f9e8f3d555 100644 --- a/source/blender/draw/engines/eevee/eevee_renderpasses.c +++ b/source/blender/draw/engines/eevee/eevee_renderpasses.c @@ -42,19 +42,35 @@ static struct { struct GPUShader *postprocess_sh; } e_data = {NULL}; /* Engine data */ +typedef enum eRenderPassPostProcessType { + PASS_POST_UNDEFINED = 0, + PASS_POST_ACCUMULATED_COLOR = 1, + PASS_POST_ACCUMULATED_LIGHT = 2, + PASS_POST_ACCUMULATED_VALUE = 3, + PASS_POST_DEPTH = 4, + PASS_POST_AO = 5, + PASS_POST_NORMAL = 6, + PASS_POST_TWO_LIGHT_BUFFERS = 7, +} eRenderPassPostProcessType; + /* 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) + (EEVEE_RENDER_PASS_Z | EEVEE_RENDER_PASS_MIST | EEVEE_RENDER_PASS_NORMAL | \ + EEVEE_RENDER_PASS_AO | EEVEE_RENDER_PASS_BLOOM | EEVEE_RENDER_PASS_VOLUME_SCATTER | \ + EEVEE_RENDER_PASS_VOLUME_TRANSMITTANCE | EEVEE_RENDER_PASS_SHADOW | \ + EEVEE_RENDERPASSES_MATERIAL) -#define EEVEE_RENDERPASSES_ALL (EEVEE_RENDERPASSES_WITH_POST_PROCESSING | SCE_PASS_COMBINED) +#define EEVEE_RENDERPASSES_ALL \ + (EEVEE_RENDERPASSES_WITH_POST_PROCESSING | EEVEE_RENDER_PASS_COMBINED) -#define EEVEE_RENDERPASSES_POST_PROCESS_ON_FIRST_SAMPLE (SCE_PASS_Z | SCE_PASS_NORMAL) +#define EEVEE_RENDERPASSES_POST_PROCESS_ON_FIRST_SAMPLE \ + (EEVEE_RENDER_PASS_Z | EEVEE_RENDER_PASS_NORMAL) -#define EEVEE_RENDERPASSES_COLOR_PASS (SCE_PASS_SUBSURFACE_COLOR | SCE_PASS_SUBSURFACE_DIRECT) +#define EEVEE_RENDERPASSES_COLOR_PASS \ + (EEVEE_RENDER_PASS_DIFFUSE_COLOR | EEVEE_RENDER_PASS_SPECULAR_COLOR | EEVEE_RENDER_PASS_EMIT | \ + EEVEE_RENDER_PASS_BLOOM) +#define EEVEE_RENDERPASSES_LIGHT_PASS \ + (EEVEE_RENDER_PASS_DIFFUSE_LIGHT | EEVEE_RENDER_PASS_SPECULAR_LIGHT) bool EEVEE_renderpasses_only_first_sample_pass_active(EEVEE_Data *vedata) { @@ -75,8 +91,33 @@ void EEVEE_renderpasses_init(EEVEE_Data *vedata) g_data->render_passes = v3d->shading.render_pass; } else { - g_data->render_passes = (view_layer->passflag & EEVEE_RENDERPASSES_ALL) | SCE_PASS_COMBINED; + eViewLayerEEVEEPassType enabled_render_passes = view_layer->eevee.render_passes; + +#define ENABLE_FROM_LEGACY(name_legacy, name_eevee) \ + SET_FLAG_FROM_TEST(enabled_render_passes, \ + (view_layer->passflag & SCE_PASS_##name_legacy) != 0, \ + EEVEE_RENDER_PASS_##name_eevee); + + ENABLE_FROM_LEGACY(Z, Z) + ENABLE_FROM_LEGACY(MIST, MIST) + ENABLE_FROM_LEGACY(NORMAL, NORMAL) + ENABLE_FROM_LEGACY(SHADOW, SHADOW) + ENABLE_FROM_LEGACY(AO, AO) + ENABLE_FROM_LEGACY(EMIT, EMIT) + ENABLE_FROM_LEGACY(ENVIRONMENT, ENVIRONMENT) + ENABLE_FROM_LEGACY(DIFFUSE_COLOR, DIFFUSE_COLOR) + ENABLE_FROM_LEGACY(GLOSSY_COLOR, SPECULAR_COLOR) + ENABLE_FROM_LEGACY(DIFFUSE_DIRECT, DIFFUSE_LIGHT) + ENABLE_FROM_LEGACY(GLOSSY_DIRECT, SPECULAR_LIGHT) + + ENABLE_FROM_LEGACY(ENVIRONMENT, ENVIRONMENT) + +#undef ENABLE_FROM_LEGACY + g_data->render_passes = (enabled_render_passes & EEVEE_RENDERPASSES_ALL) | + EEVEE_RENDER_PASS_COMBINED; } + + EEVEE_material_renderpasses_init(vedata); } void EEVEE_renderpasses_output_init(EEVEE_ViewLayerData *sldata, @@ -87,6 +128,7 @@ void EEVEE_renderpasses_output_init(EEVEE_ViewLayerData *sldata, EEVEE_TextureList *txl = vedata->txl; EEVEE_PassList *psl = vedata->psl; EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = stl->effects; EEVEE_PrivateData *g_data = stl->g_data; DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); @@ -106,33 +148,54 @@ void EEVEE_renderpasses_output_init(EEVEE_ViewLayerData *sldata, /* 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 */ + * when renderpasses other than `EEVEE_RENDER_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 & EEVEE_RENDERPASSES_MATERIAL) != 0) { + EEVEE_material_output_init(sldata, vedata, tot_samples); } - if ((g_data->render_passes & SCE_PASS_MIST) != 0) { + if ((g_data->render_passes & EEVEE_RENDER_PASS_MIST) != 0) { EEVEE_mist_output_init(sldata, vedata); } + if ((g_data->render_passes & EEVEE_RENDER_PASS_SHADOW) != 0) { + EEVEE_shadow_output_init(sldata, vedata, tot_samples); + } - if ((g_data->render_passes & SCE_PASS_AO) != 0) { + if ((g_data->render_passes & EEVEE_RENDER_PASS_AO) != 0) { EEVEE_occlusion_output_init(sldata, vedata, tot_samples); } + if ((g_data->render_passes & EEVEE_RENDER_PASS_BLOOM) != 0 && + (effects->enabled_effects & EFFECT_BLOOM) != 0) { + EEVEE_bloom_output_init(sldata, vedata, tot_samples); + } + + if ((g_data->render_passes & + (EEVEE_RENDER_PASS_VOLUME_TRANSMITTANCE | EEVEE_RENDER_PASS_VOLUME_SCATTER)) != 0) { + EEVEE_volumes_output_init(sldata, vedata, tot_samples); + } + /* Create Pass. */ DRW_PASS_CREATE(psl->renderpass_pass, DRW_STATE_WRITE_COLOR); DRWShadingGroup *grp = DRW_shgroup_create(e_data.postprocess_sh, psl->renderpass_pass); /* We set a default texture as not all post processes uses the inputBuffer. */ g_data->renderpass_input = txl->color; + g_data->renderpass_col_input = txl->color; + g_data->renderpass_light_input = txl->color; DRW_shgroup_uniform_texture_ref(grp, "inputBuffer", &g_data->renderpass_input); + DRW_shgroup_uniform_texture_ref(grp, "inputColorBuffer", &g_data->renderpass_col_input); + DRW_shgroup_uniform_texture_ref( + grp, "inputSecondLightBuffer", &g_data->renderpass_light_input); DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_block( + grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); DRW_shgroup_uniform_int(grp, "currentSample", &g_data->renderpass_current_sample, 1); DRW_shgroup_uniform_int(grp, "renderpassType", &g_data->renderpass_type, 1); + DRW_shgroup_uniform_int(grp, "postProcessType", &g_data->renderpass_postprocess, 1); DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL); } else { @@ -152,12 +215,13 @@ void EEVEE_renderpasses_output_init(EEVEE_ViewLayerData *sldata, * 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 *UNUSED(sldata), +void EEVEE_renderpasses_postprocess(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, - eScenePassType renderpass_type) + eViewLayerEEVEEPassType renderpass_type) { EEVEE_PassList *psl = vedata->psl; EEVEE_TextureList *txl = vedata->txl; + EEVEE_FramebufferList *fbl = vedata->fbl; EEVEE_StorageList *stl = vedata->stl; EEVEE_PrivateData *g_data = stl->g_data; EEVEE_EffectsInfo *effects = stl->effects; @@ -165,51 +229,133 @@ void EEVEE_renderpasses_postprocess(EEVEE_ViewLayerData *UNUSED(sldata), const int current_sample = effects->taa_current_sample; g_data->renderpass_current_sample = current_sample; g_data->renderpass_type = renderpass_type; + g_data->renderpass_postprocess = PASS_POST_UNDEFINED; switch (renderpass_type) { - case SCE_PASS_AO: { + case EEVEE_RENDER_PASS_Z: { + g_data->renderpass_postprocess = PASS_POST_DEPTH; + break; + } + case EEVEE_RENDER_PASS_AO: { + g_data->renderpass_postprocess = PASS_POST_AO; g_data->renderpass_input = txl->ao_accum; break; } - case SCE_PASS_NORMAL: { + case EEVEE_RENDER_PASS_NORMAL: { + g_data->renderpass_postprocess = PASS_POST_NORMAL; g_data->renderpass_input = effects->ssr_normal_input; break; } - case SCE_PASS_MIST: { + case EEVEE_RENDER_PASS_MIST: { + g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_VALUE; g_data->renderpass_input = txl->mist_accum; break; } - case SCE_PASS_SUBSURFACE_DIRECT: { - g_data->renderpass_input = txl->sss_dir_accum; + case EEVEE_RENDER_PASS_VOLUME_SCATTER: { + g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_COLOR; + g_data->renderpass_input = txl->volume_scatter_accum; + break; + } + case EEVEE_RENDER_PASS_VOLUME_TRANSMITTANCE: { + g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_COLOR; + g_data->renderpass_input = txl->volume_transmittance_accum; + break; + } + case EEVEE_RENDER_PASS_SHADOW: { + g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_VALUE; + g_data->renderpass_input = txl->shadow_accum; break; } - case SCE_PASS_SUBSURFACE_COLOR: { - g_data->renderpass_input = txl->sss_col_accum; + case EEVEE_RENDER_PASS_DIFFUSE_COLOR: + case EEVEE_RENDER_PASS_SPECULAR_COLOR: + case EEVEE_RENDER_PASS_ENVIRONMENT: + case EEVEE_RENDER_PASS_EMIT: { + g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_COLOR; + int renderpass_index = EEVEE_material_output_pass_index_get(sldata, vedata, renderpass_type); + g_data->renderpass_input = txl->material_accum[renderpass_index]; + break; + } + case EEVEE_RENDER_PASS_SPECULAR_LIGHT: { + g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_LIGHT; + int renderpass_index = EEVEE_material_output_pass_index_get(sldata, vedata, renderpass_type); + int renderpass_index_color = EEVEE_material_output_color_pass_index_get( + sldata, vedata, renderpass_type); + g_data->renderpass_input = txl->material_accum[renderpass_index]; + g_data->renderpass_col_input = txl->material_accum[renderpass_index_color]; + if ((stl->effects->enabled_effects & EFFECT_SSR) != 0) { + g_data->renderpass_postprocess = PASS_POST_TWO_LIGHT_BUFFERS; + g_data->renderpass_light_input = txl->ssr_accum; + } + else { + g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_LIGHT; + } + break; + } + case EEVEE_RENDER_PASS_DIFFUSE_LIGHT: { + g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_LIGHT; + int renderpass_index = EEVEE_material_output_pass_index_get(sldata, vedata, renderpass_type); + int renderpass_index_color = EEVEE_material_output_color_pass_index_get( + sldata, vedata, renderpass_type); + g_data->renderpass_input = txl->material_accum[renderpass_index]; + g_data->renderpass_col_input = txl->material_accum[renderpass_index_color]; + if ((stl->effects->enabled_effects & EFFECT_SSS) != 0) { + g_data->renderpass_postprocess = PASS_POST_TWO_LIGHT_BUFFERS; + g_data->renderpass_light_input = txl->sss_accum; + } + else { + g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_LIGHT; + } + break; + } + case EEVEE_RENDER_PASS_BLOOM: { + g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_COLOR; + g_data->renderpass_input = txl->bloom_accum; + g_data->renderpass_current_sample = 1; break; } default: { break; } } - GPU_framebuffer_bind(vedata->fbl->renderpass_fb); + GPU_framebuffer_bind(fbl->renderpass_fb); DRW_draw_pass(psl->renderpass_pass); } -void EEVEE_renderpasses_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) +void EEVEE_renderpasses_output_accumulate(EEVEE_ViewLayerData *sldata, + EEVEE_Data *vedata, + bool post_effect) { EEVEE_StorageList *stl = vedata->stl; EEVEE_EffectsInfo *effects = stl->effects; - eScenePassType render_pass = stl->g_data->render_passes; + eViewLayerEEVEEPassType 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 (!post_effect) { + if ((render_pass & EEVEE_RENDER_PASS_MIST) != 0) { + EEVEE_mist_output_accumulate(sldata, vedata); + } + if ((render_pass & EEVEE_RENDER_PASS_DIFFUSE_LIGHT) != 0 && + (effects->enabled_effects & EFFECT_SSS) != 0) { + EEVEE_subsurface_output_accumulate(sldata, vedata); + } + if ((render_pass & EEVEE_RENDER_PASS_AO) != 0) { + EEVEE_occlusion_output_accumulate(sldata, vedata); + } + if ((render_pass & EEVEE_RENDER_PASS_SHADOW) != 0) { + EEVEE_shadow_output_accumulate(sldata, vedata); + } + if ((render_pass & EEVEE_RENDERPASSES_MATERIAL) != 0) { + EEVEE_material_output_accumulate(sldata, vedata); + } + if ((render_pass & + (EEVEE_RENDER_PASS_VOLUME_TRANSMITTANCE | EEVEE_RENDER_PASS_VOLUME_SCATTER)) != 0) { + EEVEE_volumes_output_accumulate(sldata, vedata); + } } - if ((render_pass & SCE_PASS_AO) != 0) { - EEVEE_occlusion_output_accumulate(sldata, vedata); + else { + if ((render_pass & EEVEE_RENDER_PASS_BLOOM) != 0 && + (effects->enabled_effects & EFFECT_BLOOM) != 0) { + EEVEE_bloom_output_accumulate(sldata, vedata); + } } } @@ -220,7 +366,13 @@ void EEVEE_renderpasses_draw(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) 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; + + /* We can only draw a single renderpass. Lightpasses also select their color pass (a second + pass). We mask the light pass when a light pass is selected. */ + const eViewLayerEEVEEPassType render_pass = + ((stl->g_data->render_passes & EEVEE_RENDERPASSES_LIGHT_PASS) != 0) ? + (stl->g_data->render_passes & EEVEE_RENDERPASSES_LIGHT_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); @@ -229,14 +381,14 @@ void EEVEE_renderpasses_draw(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_state_is_opengl_render(); UNUSED_VARS(needs_color_transfer); - /* 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) { + if ((render_pass & EEVEE_RENDER_PASS_BLOOM) != 0 && + (effects->enabled_effects & EFFECT_BLOOM) == 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) { + if ((render_pass & EEVEE_RENDER_PASS_AO) != 0 && + (scene_eval->eevee.flag & SCE_EEVEE_GTAO_ENABLED) == 0) { is_valid = false; } @@ -254,7 +406,7 @@ void EEVEE_renderpasses_draw(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) } 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}; + static float clear_color[4] = {0.0f, 0.0f, 0.0f, 1.0f}; GPU_framebuffer_bind(dfbl->default_fb); GPU_framebuffer_clear_color(dfbl->default_fb, clear_color); } diff --git a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c index 591ca31017c..d231edf1383 100644 --- a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c +++ b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c @@ -235,6 +235,8 @@ void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *v DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo); DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_block( + grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); if (!effects->reflection_trace_full) { DRW_shgroup_uniform_ivec2(grp, "halfresOffset", effects->ssr_halfres_ofs, 1); } @@ -255,6 +257,8 @@ void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *v DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo); DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_block( + grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); DRW_shgroup_uniform_int(grp, "neighborOffset", &effects->ssr_neighbor_ofs, 1); if ((effects->enabled_effects & EFFECT_GTAO) != 0) { DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex()); @@ -335,6 +339,43 @@ void EEVEE_reflection_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v } } +void EEVEE_reflection_output_init(EEVEE_ViewLayerData *UNUSED(sldata), + EEVEE_Data *vedata, + uint tot_samples) +{ + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_TextureList *txl = vedata->txl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = stl->effects; + + float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + + /* Create FrameBuffer. */ + const eGPUTextureFormat texture_format = (tot_samples > 256) ? GPU_RGBA32F : GPU_RGBA16F; + DRW_texture_ensure_fullscreen_2d(&txl->ssr_accum, texture_format, 0); + + GPU_framebuffer_ensure_config(&fbl->ssr_accum_fb, + {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->ssr_accum)}); + + /* Clear texture. */ + if (DRW_state_is_image_render() || effects->taa_current_sample == 1) { + GPU_framebuffer_bind(fbl->ssr_accum_fb); + GPU_framebuffer_clear_color(fbl->ssr_accum_fb, clear); + } +} + +void EEVEE_reflection_output_accumulate(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) +{ + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_PassList *psl = vedata->psl; + EEVEE_StorageList *stl = vedata->stl; + + if (stl->g_data->valid_double_buffer) { + GPU_framebuffer_bind(fbl->ssr_accum_fb); + DRW_draw_pass(psl->ssr_resolve); + } +} + void EEVEE_screen_raytrace_free(void) { for (int i = 0; i < SSR_MAX_SHADER; i++) { diff --git a/source/blender/draw/engines/eevee/eevee_shadows.c b/source/blender/draw/engines/eevee/eevee_shadows.c index 1776f535237..f5b98d464dd 100644 --- a/source/blender/draw/engines/eevee/eevee_shadows.c +++ b/source/blender/draw/engines/eevee/eevee_shadows.c @@ -21,6 +21,7 @@ */ #include "BLI_sys_types.h" /* bool */ +#include "BLI_string_utils.h" // #include "BLI_dynstr.h" // #include "BLI_rand.h" @@ -35,11 +36,17 @@ static struct { struct GPUShader *shadow_sh; + struct GPUShader *shadow_accum_sh; } e_data = {NULL}; /* Engine data */ extern char datatoc_shadow_vert_glsl[]; extern char datatoc_shadow_frag_glsl[]; +extern char datatoc_shadow_accum_frag_glsl[]; extern char datatoc_common_view_lib_glsl[]; +extern char datatoc_common_uniforms_lib_glsl[]; +extern char datatoc_bsdf_common_lib_glsl[]; +extern char datatoc_lights_lib_glsl[]; +extern char datatoc_raytrace_lib_glsl[]; void eevee_contact_shadow_setup(const Light *la, EEVEE_Shadow *evsh) { @@ -65,6 +72,18 @@ void EEVEE_shadows_init(EEVEE_ViewLayerData *sldata) NULL); } + if (!e_data.shadow_accum_sh) { + char *frag_str = BLI_string_joinN(datatoc_common_view_lib_glsl, + datatoc_common_uniforms_lib_glsl, + datatoc_bsdf_common_lib_glsl, + datatoc_raytrace_lib_glsl, + datatoc_lights_lib_glsl, + datatoc_shadow_accum_frag_glsl); + + e_data.shadow_accum_sh = DRW_shader_create_fullscreen(frag_str, SHADER_DEFINES); + MEM_freeN(frag_str); + } + if (!sldata->lights) { sldata->lights = MEM_callocN(sizeof(EEVEE_LightsInfo), "EEVEE_LightsInfo"); sldata->light_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_Light) * MAX_LIGHT, NULL); @@ -170,6 +189,8 @@ void EEVEE_shadows_caster_material_add(EEVEE_ViewLayerData *sldata, DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo); DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo); DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo); + DRW_shgroup_uniform_block( + grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); if (alpha_threshold != NULL) { @@ -406,7 +427,75 @@ void EEVEE_shadows_draw(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, DRWView } } +/* -------------------------------------------------------------------- */ + +/** \name Render Passes + * \{ */ + +void EEVEE_shadow_output_init(EEVEE_ViewLayerData *sldata, + EEVEE_Data *vedata, + uint UNUSED(tot_samples)) +{ + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_TextureList *txl = vedata->txl; + EEVEE_PassList *psl = vedata->psl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = stl->effects; + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + + float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + + /* Create FrameBuffer. */ + const eGPUTextureFormat texture_format = GPU_R32F; + DRW_texture_ensure_fullscreen_2d(&txl->shadow_accum, texture_format, 0); + + GPU_framebuffer_ensure_config(&fbl->shadow_accum_fb, + {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->shadow_accum)}); + + /* Clear texture. */ + if (DRW_state_is_image_render() || effects->taa_current_sample == 1) { + GPU_framebuffer_bind(fbl->shadow_accum_fb); + GPU_framebuffer_clear_color(fbl->shadow_accum_fb, clear); + } + + /* Create Pass and shgroup. */ + DRW_PASS_CREATE(psl->shadow_accum_pass, + DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_ALWAYS | DRW_STATE_BLEND_ADD_FULL); + DRWShadingGroup *grp = DRW_shgroup_create(e_data.shadow_accum_sh, psl->shadow_accum_pass); + DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); + DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex()); + DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo); + DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo); + DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo); + DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo); + DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo); + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_block( + grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); + DRW_shgroup_uniform_texture_ref(grp, "shadowCubeTexture", &sldata->shadow_cube_pool); + DRW_shgroup_uniform_texture_ref(grp, "shadowCascadeTexture", &sldata->shadow_cascade_pool); + + DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL); +} + +void EEVEE_shadow_output_accumulate(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) +{ + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_PassList *psl = vedata->psl; + + if (fbl->shadow_accum_fb != NULL) { + GPU_framebuffer_bind(fbl->shadow_accum_fb); + DRW_draw_pass(psl->shadow_accum_pass); + + /* Restore */ + GPU_framebuffer_bind(fbl->main_fb); + } +} + +/* \} */ + void EEVEE_shadows_free(void) { DRW_SHADER_FREE_SAFE(e_data.shadow_sh); + DRW_SHADER_FREE_SAFE(e_data.shadow_accum_sh); } diff --git a/source/blender/draw/engines/eevee/eevee_subsurface.c b/source/blender/draw/engines/eevee/eevee_subsurface.c index e94fc903694..98e799acb5e 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_extensions.h" static struct { - struct GPUShader *sss_sh[4]; + struct GPUShader *sss_sh[3]; } e_data = {{NULL}}; /* Engine data */ extern char datatoc_common_view_lib_glsl[]; @@ -64,8 +64,7 @@ static void eevee_create_shader_subsurface(void) e_data.sss_sh[0] = DRW_shader_create_fullscreen(frag_str, "#define FIRST_PASS\n"); 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 RESULT_ACCUM\n"); - e_data.sss_sh[3] = DRW_shader_create_fullscreen(frag_translucent_str, + e_data.sss_sh[2] = DRW_shader_create_fullscreen(frag_translucent_str, "#define EEVEE_TRANSLUCENCY\n" SHADER_DEFINES); MEM_freeN(frag_translucent_str); @@ -85,9 +84,10 @@ void EEVEE_subsurface_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) common_data->sss_jitter_threshold = scene_eval->eevee.sss_jitter_threshold; } -void EEVEE_subsurface_draw_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) +void EEVEE_subsurface_draw_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) { EEVEE_EffectsInfo *effects = vedata->stl->effects; + EEVEE_StorageList *stl = vedata->stl; EEVEE_FramebufferList *fbl = vedata->fbl; EEVEE_TextureList *txl = vedata->txl; DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); @@ -138,72 +138,64 @@ void EEVEE_subsurface_draw_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(effects->sss_irradiance), GPU_ATTACHMENT_TEXTURE(effects->sss_radius)}); + if ((stl->g_data->render_passes & EEVEE_RENDER_PASS_DIFFUSE_LIGHT) != 0) { + EEVEE_subsurface_output_init(sldata, vedata, 0); + } + else { + GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_accum_fb); + txl->sss_accum = NULL; + } } else { /* Cleanup to release memory */ GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_blur_fb); GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_resolve_fb); GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_clear_fb); + GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_accum_fb); effects->sss_stencil = NULL; effects->sss_blur = NULL; effects->sss_irradiance = NULL; effects->sss_radius = NULL; + txl->sss_accum = NULL; } } -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, - uint tot_samples) + uint UNUSED(tot_samples)) { 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) { - 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; + const eGPUTextureFormat texture_format_light = GPU_RGBA32F; + const bool texture_created = txl->sss_accum == NULL; + DRW_texture_ensure_fullscreen_2d(&txl->sss_accum, texture_format_light, 0); - if (GPU_depth_blitting_workaround()) { - DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); - /* Blitting stencil buffer does not work on macOS + Radeon Pro. - * Blit depth instead and use sss_stencil's depth as depth texture, - * and dtxl->depth as stencil mask. */ - stencil_tex = dtxl->depth; - } + GPUTexture *stencil_tex = effects->sss_stencil; - GPU_framebuffer_ensure_config(&fbl->sss_accum_fb, - {GPU_ATTACHMENT_TEXTURE(stencil_tex), - GPU_ATTACHMENT_TEXTURE(txl->sss_dir_accum), - GPU_ATTACHMENT_TEXTURE(txl->sss_col_accum)}); + if (GPU_depth_blitting_workaround()) { + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + /* Blitting stencil buffer does not work on macOS + Radeon Pro. + * Blit depth instead and use sss_stencil's depth as depth texture, + * and dtxl->depth as stencil mask. */ + stencil_tex = dtxl->depth; + } - /* Clear texture. */ - 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); - } + GPU_framebuffer_ensure_config( + &fbl->sss_accum_fb, + {GPU_ATTACHMENT_TEXTURE(stencil_tex), GPU_ATTACHMENT_TEXTURE(txl->sss_accum)}); - /* Make the opaque refraction pass mask the sss. */ - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES | - DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_ALWAYS; - 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); - GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_accum_fb); + /* Clear texture. + * Due to the late initialization of the SSS it can happen that the `taa_current_sample` is + * already higher than one. This is noticeable when loading a file that has the diffuse light + * pass in look dev mode active. `texture_created` will make sure that newly created textures + * are cleared. */ + if (DRW_state_is_image_render() || effects->taa_current_sample == 1 || texture_created) { + 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); } } @@ -222,7 +214,6 @@ void EEVEE_subsurface_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_EQUAL; DRW_PASS_CREATE(psl->sss_blur_ps, state); DRW_PASS_CREATE(psl->sss_resolve_ps, state | DRW_STATE_BLEND_ADD); - DRW_PASS_CREATE(psl->sss_accum_ps, state | DRW_STATE_BLEND_ADD); DRW_PASS_CREATE(psl->sss_translucency_ps, state | DRW_STATE_BLEND_ADD); } @@ -245,6 +236,8 @@ void EEVEE_subsurface_add_pass(EEVEE_ViewLayerData *sldata, DRW_shgroup_uniform_texture_ref(grp, "sssRadius", &effects->sss_radius); DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_block( + grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); DRW_shgroup_stencil_mask(grp, sss_id); DRW_shgroup_call(grp, quad, NULL); @@ -256,22 +249,10 @@ void EEVEE_subsurface_add_pass(EEVEE_ViewLayerData *sldata, DRW_shgroup_uniform_texture_ref(grp, "sssRadius", &effects->sss_radius); DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_block( + grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); DRW_shgroup_stencil_mask(grp, sss_id); DRW_shgroup_call(grp, quad, NULL); - - 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); - DRW_shgroup_uniform_texture_ref(grp, "sssIrradiance", &effects->sss_blur); - DRW_shgroup_uniform_texture_ref(grp, "sssAlbedo", &effects->sss_albedo); - DRW_shgroup_uniform_texture_ref(grp, "sssRadius", &effects->sss_radius); - 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(grp, quad, NULL); - } } void EEVEE_subsurface_translucency_add_pass(EEVEE_ViewLayerData *sldata, @@ -287,7 +268,7 @@ void EEVEE_subsurface_translucency_add_pass(EEVEE_ViewLayerData *sldata, struct GPUBatch *quad = DRW_cache_fullscreen_quad_get(); GPUTexture **depth_src = GPU_depth_blitting_workaround() ? &effects->sss_stencil : &dtxl->depth; - DRWShadingGroup *grp = DRW_shgroup_create(e_data.sss_sh[3], psl->sss_translucency_ps); + DRWShadingGroup *grp = DRW_shgroup_create(e_data.sss_sh[2], psl->sss_translucency_ps); DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex()); DRW_shgroup_uniform_texture(grp, "sssTexProfile", sss_tex_profile); DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src); @@ -298,6 +279,8 @@ void EEVEE_subsurface_translucency_add_pass(EEVEE_ViewLayerData *sldata, DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo); DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_block( + grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); DRW_shgroup_stencil_mask(grp, sss_id); DRW_shgroup_call(grp, quad, NULL); } @@ -408,11 +391,11 @@ void EEVEE_subsurface_output_accumulate(EEVEE_ViewLayerData *UNUSED(sldata), EEV if (((effects->enabled_effects & EFFECT_SSS) != 0) && (fbl->sss_accum_fb != NULL)) { /* Copy stencil channel, could be avoided (see EEVEE_subsurface_init) */ - GPU_framebuffer_blit(fbl->main_fb, 0, fbl->sss_blur_fb, 0, GPU_STENCIL_BIT); + GPU_framebuffer_blit(fbl->main_fb, 0, fbl->sss_accum_fb, 0, GPU_STENCIL_BIT); /* Only do vertical pass + Resolve */ GPU_framebuffer_bind(fbl->sss_accum_fb); - DRW_draw_pass(psl->sss_accum_ps); + DRW_draw_pass(psl->sss_resolve_ps); /* Restore */ GPU_framebuffer_bind(fbl->main_fb); @@ -424,5 +407,4 @@ 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/eevee_temporal_sampling.c b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c index 093a4780a97..bd77279eb4a 100644 --- a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c +++ b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c @@ -290,6 +290,8 @@ void EEVEE_temporal_sampling_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data DRW_shgroup_uniform_texture_ref(grp, "colorHistoryBuffer", &txl->taa_history); DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", &effects->source_buffer); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_block( + grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); if (effects->enabled_effects & EFFECT_TAA_REPROJECT) { // DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c index 7026894076a..456673c92fa 100644 --- a/source/blender/draw/engines/eevee/eevee_volumes.c +++ b/source/blender/draw/engines/eevee/eevee_volumes.c @@ -54,6 +54,7 @@ static struct { struct GPUShader *scatter_with_lights_sh; struct GPUShader *volumetric_integration_sh; struct GPUShader *volumetric_resolve_sh; + struct GPUShader *volumetric_accum_sh; GPUTexture *depth_src; @@ -73,6 +74,7 @@ extern char datatoc_common_view_lib_glsl[]; extern char datatoc_octahedron_lib_glsl[]; extern char datatoc_irradiance_lib_glsl[]; extern char datatoc_lights_lib_glsl[]; +extern char datatoc_volumetric_accum_frag_glsl[]; extern char datatoc_volumetric_frag_glsl[]; extern char datatoc_volumetric_geom_glsl[]; extern char datatoc_volumetric_vert_glsl[]; @@ -136,6 +138,8 @@ static void eevee_create_shader_volumes(void) datatoc_volumetric_resolve_frag_glsl, e_data.volumetric_common_lib, NULL); + e_data.volumetric_accum_sh = DRW_shader_create_fullscreen(datatoc_volumetric_accum_frag_glsl, + NULL); float color[4] = {1.0f, 1.0f, 1.0f, 1.0f}; e_data.dummy_density = DRW_texture_create_3d(1, 1, 1, GPU_RGBA8, DRW_TEX_WRAP, color); @@ -359,6 +363,8 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo); DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo); DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo); + DRW_shgroup_uniform_block( + grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); /* Fix principle volumetric not working with world materials. */ DRW_shgroup_uniform_texture(grp, "sampdensity", e_data.dummy_density); @@ -375,6 +381,8 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) /* If no world or volume material is present just clear the buffer with this drawcall */ grp = DRW_shgroup_create(e_data.volumetric_clear_sh, psl->volumetric_world_ps); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_block( + grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); DRW_shgroup_call_procedural_triangles(grp, NULL, common_data->vol_tex_size[2]); } @@ -430,8 +438,12 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata, DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo); DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo); DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo); + DRW_shgroup_uniform_block( + grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_block( + grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); DRW_shgroup_uniform_vec3(grp, "volumeOrcoLoc", texcoloc, 1); DRW_shgroup_uniform_vec3(grp, "volumeOrcoSize", texcosize, 1); @@ -522,6 +534,8 @@ void EEVEE_volumes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo); DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_block( + grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); DRW_shgroup_call_procedural_triangles(grp, NULL, common_data->vol_tex_size[2]); @@ -530,6 +544,8 @@ void EEVEE_volumes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_shgroup_uniform_texture_ref(grp, "volumeScattering", &txl->volume_scatter); DRW_shgroup_uniform_texture_ref(grp, "volumeExtinction", &txl->volume_transmit); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_block( + grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); DRW_shgroup_call_procedural_triangles( grp, NULL, USE_VOLUME_OPTI ? 1 : common_data->vol_tex_size[2]); @@ -540,6 +556,8 @@ void EEVEE_volumes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_shgroup_uniform_texture_ref(grp, "inTransmittance", &txl->volume_transmit); DRW_shgroup_uniform_texture_ref(grp, "inSceneDepth", &e_data.depth_src); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_block( + grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); DRW_shgroup_call_procedural_triangles(grp, NULL, 1); } @@ -729,4 +747,75 @@ void EEVEE_volumes_free(void) DRW_SHADER_FREE_SAFE(e_data.scatter_with_lights_sh); DRW_SHADER_FREE_SAFE(e_data.volumetric_integration_sh); DRW_SHADER_FREE_SAFE(e_data.volumetric_resolve_sh); + DRW_SHADER_FREE_SAFE(e_data.volumetric_accum_sh); +} + +/* -------------------------------------------------------------------- */ + +/** \name Render Passes + * \{ */ + +void EEVEE_volumes_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, uint tot_samples) +{ + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_TextureList *txl = vedata->txl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_PassList *psl = vedata->psl; + EEVEE_EffectsInfo *effects = stl->effects; + + float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + + /* Create FrameBuffer. */ + + /* Should be enough precision for many samples. */ + const eGPUTextureFormat texture_format_accum = (tot_samples > 128) ? GPU_RGBA32F : GPU_RGBA16F; + DRW_texture_ensure_fullscreen_2d(&txl->volume_scatter_accum, texture_format_accum, 0); + DRW_texture_ensure_fullscreen_2d(&txl->volume_transmittance_accum, texture_format_accum, 0); + + GPU_framebuffer_ensure_config(&fbl->volumetric_accum_fb, + {GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(txl->volume_scatter_accum), + GPU_ATTACHMENT_TEXTURE(txl->volume_transmittance_accum)}); + + /* Clear texture. */ + if (DRW_state_is_image_render() || effects->taa_current_sample == 1) { + GPU_framebuffer_bind(fbl->volumetric_accum_fb); + GPU_framebuffer_clear_color(fbl->volumetric_accum_fb, clear); + } + + /* Create Pass and shgroup. */ + DRW_PASS_CREATE(psl->volumetric_accum_ps, DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ADD_FULL); + DRWShadingGroup *grp = NULL; + if ((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) { + grp = DRW_shgroup_create(e_data.volumetric_resolve_sh, psl->volumetric_accum_ps); + DRW_shgroup_uniform_texture_ref(grp, "inScattering", &txl->volume_scatter); + DRW_shgroup_uniform_texture_ref(grp, "inTransmittance", &txl->volume_transmit); + DRW_shgroup_uniform_texture_ref(grp, "inSceneDepth", &e_data.depth_src); + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_block( + grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); + } + else { + /* There is no volumetrics in the scene. Use a shader to fill the accum textures with a default + * value. */ + grp = DRW_shgroup_create(e_data.volumetric_accum_sh, psl->volumetric_accum_ps); + } + DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL); } + +void EEVEE_volumes_output_accumulate(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) +{ + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_PassList *psl = vedata->psl; + + if (fbl->volumetric_accum_fb != NULL) { + /* Accum pass */ + GPU_framebuffer_bind(fbl->volumetric_accum_fb); + DRW_draw_pass(psl->volumetric_accum_ps); + + /* Restore */ + GPU_framebuffer_bind(fbl->main_fb); + } +} + +/* \} */ diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl index c4f815b5dd4..c3518198805 100644 --- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl @@ -85,6 +85,37 @@ struct ShadowCascadeData { #define sh_shadow_vec shadow_vec_id.xyz #define sh_tex_index shadow_vec_id.w +/* ------ Render Passes ----- */ +layout(std140) uniform renderpass_block +{ + bool renderPassDiffuse; + bool renderPassDiffuseLight; + bool renderPassGlossy; + bool renderPassGlossyLight; + bool renderPassEmit; + bool renderPassSSSColor; +}; + +vec3 render_pass_diffuse_mask(vec3 diffuse_color, vec3 diffuse_light) +{ + return renderPassDiffuse ? (renderPassDiffuseLight ? diffuse_light : diffuse_color) : vec3(0.0); +} + +vec3 render_pass_sss_mask(vec3 sss_color) +{ + return renderPassSSSColor ? sss_color : vec3(0.0); +} + +vec3 render_pass_glossy_mask(vec3 specular_color, vec3 specular_light) +{ + return renderPassGlossy ? (renderPassGlossyLight ? specular_light : specular_color) : vec3(0.0); +} + +vec3 render_pass_emission_mask(vec3 emission_light) +{ + return renderPassEmit ? emission_light : vec3(0.0); +} + /* ------- Convenience functions --------- */ vec3 mul(mat3 m, vec3 v) @@ -833,11 +864,12 @@ void closure_load_sss_data( cl.sss_radius = radius; cl.sss_albedo = sss_albedo; cl.flag |= CLOSURE_SSS_FLAG; + cl.radiance += render_pass_diffuse_mask(sss_albedo, vec3(0)); } else # endif { - cl.radiance += sss_irradiance * sss_albedo; + cl.radiance += render_pass_diffuse_mask(sss_albedo, sss_irradiance * sss_albedo); } } diff --git a/source/blender/draw/engines/eevee/shaders/default_frag.glsl b/source/blender/draw/engines/eevee/shaders/default_frag.glsl index a031ed193b6..1014b25033a 100644 --- a/source/blender/draw/engines/eevee/shaders/default_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/default_frag.glsl @@ -34,7 +34,8 @@ Closure nodetree_exec(void) eevee_closure_default(N, albedo, f0, f90, 1, roughness, 1.0, true, out_diff, out_spec, ssr_spec); Closure cl = CLOSURE_DEFAULT; - cl.radiance = out_spec + out_diff * albedo; + cl.radiance = render_pass_glossy_mask(vec3(1.0), out_spec) + + render_pass_diffuse_mask(albedo, out_diff * albedo); closure_load_ssr_data(ssr_spec, roughness, N, viewCameraVec, 1, cl); #ifdef LOOKDEV diff --git a/source/blender/draw/engines/eevee/shaders/effect_bloom_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_bloom_frag.glsl index 299cb2094c1..18f92c0dd33 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_bloom_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_bloom_frag.glsl @@ -40,6 +40,7 @@ uniform float sampleScale; /* Step Resolve */ uniform vec3 bloomColor; +uniform bool bloomAddBase; in vec4 uvcoordsvar; @@ -201,9 +202,9 @@ vec4 step_resolve(void) #else vec3 blur = upsample_filter(sourceBuffer, uvcoordsvar.xy, sourceBufferTexelSize); #endif - vec4 base = textureLod(baseBuffer, uvcoordsvar.xy, 0.0); - vec3 cout = base.rgb + blur * bloomColor; - return vec4(cout, base.a); + vec3 base = bloomAddBase ? textureLod(baseBuffer, uvcoordsvar.xy, 0.0).rgb : vec3(0.0); + vec3 cout = base + blur * bloomColor; + return vec4(cout, 1.0); } void main(void) 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 1241cf0e387..e9da49c9eb9 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl @@ -20,13 +20,7 @@ uniform sampler2DArray utilTex; # define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0) #endif /* UTIL_TEX */ -#ifdef RESULT_ACCUM -/* Render Passes Accumulation */ -layout(location = 0) out vec4 sssDirect; -layout(location = 1) out vec4 sssColor; -#else layout(location = 0) out vec4 sssRadiance; -#endif float get_view_z_from_depth(float depth) { @@ -87,10 +81,7 @@ void main(void) accum += kernel[i].rgb * mix(color, sss_irradiance, s); } -#ifdef RESULT_ACCUM - sssDirect = vec4(accum, 1.0); - sssColor = vec4(texture(sssAlbedo, uvs).rgb, 1.0); -#elif defined(FIRST_PASS) +#if defined(FIRST_PASS) sssRadiance = vec4(accum, 1.0); #else /* SECOND_PASS */ sssRadiance = vec4(accum * texture(sssAlbedo, uvs).rgb, 1.0); diff --git a/source/blender/draw/engines/eevee/shaders/lights_lib.glsl b/source/blender/draw/engines/eevee/shaders/lights_lib.glsl index 6427f02ed25..3b9d0a8f2bc 100644 --- a/source/blender/draw/engines/eevee/shaders/lights_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/lights_lib.glsl @@ -173,19 +173,17 @@ float light_attenuation(LightData ld, vec4 l_vector) return vis; } -float light_visibility(LightData ld, - vec3 W, +float light_shadowing(LightData ld, + vec3 W, #ifndef VOLUMETRICS - vec3 viewPosition, - float tracing_depth, - vec3 true_normal, - float rand_x, - const bool use_contact_shadows, + vec3 viewPosition, + float tracing_depth, + vec3 true_normal, + float rand_x, + const bool use_contact_shadows, #endif - vec4 l_vector) + float vis) { - float vis = light_attenuation(ld, l_vector); - #if !defined(VOLUMETRICS) || defined(VOLUME_SHADOW) /* shadowing */ if (ld.l_shadowid >= 0.0 && vis > 0.001) { @@ -236,6 +234,30 @@ float light_visibility(LightData ld, return vis; } +float light_visibility(LightData ld, + vec3 W, +#ifndef VOLUMETRICS + vec3 viewPosition, + float tracing_depth, + vec3 true_normal, + float rand_x, + const bool use_contact_shadows, +#endif + vec4 l_vector) +{ + float l_atten = light_attenuation(ld, l_vector); + return light_shadowing(ld, + W, +#ifndef VOLUMETRICS + viewPosition, + tracing_depth, + true_normal, + rand_x, + use_contact_shadows, +#endif + l_atten); +} + #ifdef USE_LTC float light_diffuse(LightData ld, vec3 N, vec3 V, vec4 l_vector) { diff --git a/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl b/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl index 35bfb411cb9..5214301bc03 100644 --- a/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl @@ -1,15 +1,17 @@ -#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 PASS_POST_UNDEFINED 0 +#define PASS_POST_ACCUMULATED_COLOR 1 +#define PASS_POST_ACCUMULATED_LIGHT 2 +#define PASS_POST_ACCUMULATED_VALUE 3 +#define PASS_POST_DEPTH 4 +#define PASS_POST_AO 5 +#define PASS_POST_NORMAL 6 +#define PASS_POST_TWO_LIGHT_BUFFERS 7 -#define ACCUMULATED_COLOR_PASSES (SCE_PASS_SUBSURFACE_DIRECT | SCE_PASS_SUBSURFACE_COLOR) -#define ACCUMULATED_VALUE_PASSES (SCE_PASS_MIST) -uniform int renderpassType; +uniform int postProcessType; uniform int currentSample; uniform sampler2D inputBuffer; +uniform sampler2D inputSecondLightBuffer; +uniform sampler2D inputColorBuffer; out vec4 fragColor; @@ -17,7 +19,7 @@ void main() { ivec2 texel = ivec2(gl_FragCoord.xy); - if (renderpassType == SCE_PASS_Z) { + if (postProcessType == PASS_POST_DEPTH) { float depth = texelFetch(depthBuffer, texel, 0).r; if (depth == 1.0f) { depth = 1e10; @@ -27,17 +29,15 @@ void main() } fragColor.r = depth; } - - else if (renderpassType == SCE_PASS_AO) { + else if (postProcessType == PASS_POST_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) { + else if (postProcessType == PASS_POST_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 */ + /* 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; @@ -47,18 +47,55 @@ void main() fragColor = vec4(0.0, 0.0, 0.0, 1.0); } } - - else if ((renderpassType & ACCUMULATED_VALUE_PASSES) != 0) { + else if (postProcessType == PASS_POST_ACCUMULATED_VALUE) { float accumulated_value = texelFetch(inputBuffer, texel, 0).r; fragColor = vec4(vec3(accumulated_value / currentSample), 1.0); } - - else if ((renderpassType & ACCUMULATED_COLOR_PASSES) != 0) { + else if (postProcessType == PASS_POST_ACCUMULATED_COLOR) { vec3 accumulated_color = texelFetch(inputBuffer, texel, 0).rgb; fragColor = vec4(accumulated_color / currentSample, 1.0); } + else if (postProcessType == PASS_POST_ACCUMULATED_LIGHT) { + vec3 accumulated_light = texelFetch(inputBuffer, texel, 0).rgb; + vec3 accumulated_color = texelFetch(inputColorBuffer, texel, 0).rgb; + /* Fix INF in the case a color component is 0.0 */ + if (accumulated_color.r == 0.0) { + accumulated_color.r = 1.0; + accumulated_light.r = 0.0; + } + if (accumulated_color.g == 0.0) { + accumulated_color.g = 1.0; + accumulated_light.g = 0.0; + } + if (accumulated_color.b == 0.0) { + accumulated_color.b = 1.0; + accumulated_light.b = 0.0; + } + fragColor = vec4(accumulated_light / accumulated_color, 1.0); + } + else if (postProcessType == PASS_POST_TWO_LIGHT_BUFFERS) { + vec3 accumulated_light = texelFetch(inputBuffer, texel, 0).rgb + + texelFetch(inputSecondLightBuffer, texel, 0).rgb; + vec3 accumulated_color = texelFetch(inputColorBuffer, texel, 0).rgb; + + /* Fix INF in the case a color component is 0.0 */ + if (accumulated_color.r == 0.0) { + accumulated_color.r = 1.0; + accumulated_light.r = 0.0; + } + if (accumulated_color.g == 0.0) { + accumulated_color.g = 1.0; + accumulated_light.g = 0.0; + } + if (accumulated_color.b == 0.0) { + accumulated_color.b = 1.0; + accumulated_light.b = 0.0; + } + fragColor = vec4(accumulated_light / accumulated_color, 1.0); + } else { + /* Output error color: Unknown how to post process this pass. */ fragColor = vec4(1.0, 0.0, 1.0, 1.0); } } diff --git a/source/blender/draw/engines/eevee/shaders/shadow_accum_frag.glsl b/source/blender/draw/engines/eevee/shaders/shadow_accum_frag.glsl new file mode 100644 index 00000000000..fa02bee45b7 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/shadow_accum_frag.glsl @@ -0,0 +1,58 @@ + +out vec4 fragColor; + +#ifndef UTIL_TEX +# define UTIL_TEX +uniform sampler2DArray utilTex; +# define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0) +#endif /* UTIL_TEX */ + +void main() +{ + if (laNumLight == 0) { + /* Early exit: No lights in scene */ + fragColor.r = 0.0; + return; + } + + ivec2 texel = ivec2(gl_FragCoord.xy); + float depth = texelFetch(depthBuffer, texel, 0).r; + if (depth == 1.0f) { + /* Early exit background does not receive shadows */ + fragColor.r = 1.0; + return; + } + + vec2 texel_size = 1.0 / vec2(textureSize(depthBuffer, 0)).xy; + vec2 uvs = saturate(gl_FragCoord.xy * texel_size); + vec4 rand = texelfetch_noise_tex(texel); + + float accum_light = 0.0; + float tracing_depth = depth; + /* Constant bias (due to depth buffer precision) */ + /* Magic numbers for 24bits of precision. + * From http://terathon.com/gdc07_lengyel.pdf (slide 26) */ + tracing_depth -= mix(2.4e-7, 4.8e-7, depth); + /* Convert to view Z. */ + tracing_depth = get_view_z_from_depth(tracing_depth); + + vec3 viewPosition = get_view_space_from_depth(uvs, depth); + vec3 worldPosition = transform_point(ViewMatrixInverse, viewPosition); + + vec3 true_normal = normalize(cross(dFdx(viewPosition), dFdy(viewPosition))); + + for (int i = 0; i < MAX_LIGHT && i < laNumLight; i++) { + LightData ld = lights_data[i]; + + vec4 l_vector; /* Non-Normalized Light Vector with length in last component. */ + l_vector.xyz = ld.l_position - worldPosition; + l_vector.w = length(l_vector.xyz); + + float l_vis = light_shadowing( + ld, worldPosition, viewPosition, tracing_depth, true_normal, rand.x, true, 1.0); + + accum_light += l_vis; + } + + fragColor.r = accum_light / float(laNumLight); +}
\ No newline at end of file diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_accum_frag.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_accum_frag.glsl new file mode 100644 index 00000000000..1b6a7b33f42 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/volumetric_accum_frag.glsl @@ -0,0 +1,11 @@ + +/* This shader is used to add default values to the volume accum textures. + * so it looks similar (transmittance = 1, scattering = 0) */ +layout(location = 0, index = 0) out vec4 FragColor0; +layout(location = 0, index = 1) out vec4 FragColor1; + +void main() +{ + FragColor0 = vec4(0.0); + FragColor1 = vec4(1.0); +} |