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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeroen Bakker <jbakker>2020-02-20 16:53:53 +0300
committerJeroen Bakker <jeroen@blender.org>2020-02-21 13:13:43 +0300
commitbe2bc97eba499c48e3856c8e5ec4d869e28b4d04 (patch)
tree41d8d8fd5ec205e5fa00628aaf0f1603cb5e7825
parent1f8f4c8cfeaf02754f3259f9eb811ada0ed3499e (diff)
EEVEE: Render Passes
This patch adds new render passes to EEVEE. These passes include: * Emission * Diffuse Light * Diffuse Color * Glossy Light * Glossy Color * Environment * Volume Scattering * Volume Transmission * Bloom * Shadow With these passes it will be possible to use EEVEE effectively for compositing. During development we kept a close eye on how to get similar results compared to cycles render passes there are some differences that are related to how EEVEE works. For EEVEE we combined the passes to `Diffuse` and `Specular`. There are no transmittance or sss passes anymore. Cycles will be changed accordingly. Cycles volume transmittance is added to multiple surface col passes. For EEVEE we left the volume transmittance as a separate pass. Known Limitations * All materials that use alpha blending will not be rendered in the render passes. Other transparency modes are supported. * More GPU memory is required to store the render passes. When rendering a HD image with all render passes enabled at max extra 570MB GPU memory is required. Implementation Details An overview of render passes have been described in https://wiki.blender.org/wiki/Source/Render/EEVEE/RenderPasses Future Developments * In this implementation the materials are re-rendered for Diffuse/Glossy and Emission passes. We could use multi target rendering to improve the render speed. * Other passes can be added later * Don't render material based passes when only requesting AO or Shadow. * Add more passes to the system. These could include Cryptomatte, AOV's, Vector, ObjectID, MaterialID, UV. Reviewed By: Clément Foucault Differential Revision: https://developer.blender.org/D6331
-rw-r--r--release/scripts/startup/bl_ui/properties_view_layer.py95
-rw-r--r--source/blender/draw/CMakeLists.txt3
-rw-r--r--source/blender/draw/engines/eevee/eevee_bloom.c82
-rw-r--r--source/blender/draw/engines/eevee/eevee_data.c3
-rw-r--r--source/blender/draw/engines/eevee/eevee_effects.c10
-rw-r--r--source/blender/draw/engines/eevee/eevee_engine.c13
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightprobes.c14
-rw-r--r--source/blender/draw/engines/eevee/eevee_materials.c731
-rw-r--r--source/blender/draw/engines/eevee/eevee_mist.c2
-rw-r--r--source/blender/draw/engines/eevee/eevee_occlusion.c8
-rw-r--r--source/blender/draw/engines/eevee/eevee_private.h78
-rw-r--r--source/blender/draw/engines/eevee/eevee_render.c210
-rw-r--r--source/blender/draw/engines/eevee/eevee_renderpasses.c232
-rw-r--r--source/blender/draw/engines/eevee/eevee_screen_raytrace.c41
-rw-r--r--source/blender/draw/engines/eevee/eevee_shadows.c89
-rw-r--r--source/blender/draw/engines/eevee/eevee_subsurface.c110
-rw-r--r--source/blender/draw/engines/eevee/eevee_temporal_sampling.c2
-rw-r--r--source/blender/draw/engines/eevee/eevee_volumes.c89
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl34
-rw-r--r--source/blender/draw/engines/eevee/shaders/default_frag.glsl3
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_bloom_frag.glsl7
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl11
-rw-r--r--source/blender/draw/engines/eevee/shaders/lights_lib.glsl42
-rw-r--r--source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl77
-rw-r--r--source/blender/draw/engines/eevee/shaders/shadow_accum_frag.glsl58
-rw-r--r--source/blender/draw/engines/eevee/shaders/volumetric_accum_frag.glsl11
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_diffuse.glsl2
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_eevee_specular.glsl4
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_emission.glsl2
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_glass.glsl6
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_glossy.glsl2
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl97
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_refraction.glsl2
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_subsurface_scattering.glsl1
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_translucent.glsl2
-rw-r--r--source/blender/makesdna/DNA_layer_types.h27
-rw-r--r--source/blender/makesdna/DNA_scene_types.h3
-rw-r--r--source/blender/makesrna/RNA_access.h1
-rw-r--r--source/blender/makesrna/intern/rna_scene.c30
-rw-r--r--source/blender/makesrna/intern/rna_space.c59
-rw-r--r--source/blender/nodes/composite/node_composite_tree.c7
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_image.c19
-rw-r--r--source/blender/render/extern/include/RE_engine.h5
-rw-r--r--source/blender/render/intern/source/external_engine.c2
-rw-r--r--source/blender/render/intern/source/render_result.c9
45 files changed, 1931 insertions, 404 deletions
diff --git a/release/scripts/startup/bl_ui/properties_view_layer.py b/release/scripts/startup/bl_ui/properties_view_layer.py
index 121b8f2f401..25244b7f065 100644
--- a/release/scripts/startup/bl_ui/properties_view_layer.py
+++ b/release/scripts/startup/bl_ui/properties_view_layer.py
@@ -59,14 +59,25 @@ class VIEWLAYER_PT_eevee_layer_passes(ViewLayerButtonsPanel, Panel):
COMPAT_ENGINES = {'BLENDER_EEVEE'}
def draw(self, context):
- layout = self.layout
+ pass
- layout.use_property_split = True
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
+class VIEWLAYER_PT_eevee_layer_passes_data(ViewLayerButtonsPanel, Panel):
+ bl_label = "Data"
+ bl_parent_id = "VIEWLAYER_PT_eevee_layer_passes"
+ COMPAT_ENGINES = {'BLENDER_EEVEE'}
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ scene = context.scene
+ rd = scene.render
view_layer = context.view_layer
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
col = flow.column()
col.prop(view_layer, "use_pass_combined")
col = flow.column()
@@ -75,17 +86,83 @@ class VIEWLAYER_PT_eevee_layer_passes(ViewLayerButtonsPanel, Panel):
col.prop(view_layer, "use_pass_mist")
col = flow.column()
col.prop(view_layer, "use_pass_normal")
- col = flow.column()
- col.prop(view_layer, "use_pass_ambient_occlusion")
- col = flow.column()
- col.prop(view_layer, "use_pass_subsurface_direct", text="Subsurface Direct")
- col = flow.column()
- col.prop(view_layer, "use_pass_subsurface_color", text="Subsurface Color")
+class VIEWLAYER_PT_eevee_layer_passes_light(ViewLayerButtonsPanel, Panel):
+ bl_label = "Light"
+ bl_parent_id = "VIEWLAYER_PT_eevee_layer_passes"
+ COMPAT_ENGINES = {'BLENDER_EEVEE'}
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ view_layer = context.view_layer
+ view_layer_eevee = view_layer.eevee
+ scene = context.scene
+ scene_eevee = scene.eevee
+
+ split = layout.split(factor=0.35)
+ split.use_property_split = False
+ split.label(text="Diffuse")
+ row = split.row(align=True)
+ row.prop(view_layer, "use_pass_diffuse_direct", text="Light", toggle=True)
+ row.prop(view_layer, "use_pass_diffuse_color", text="Color", toggle=True)
+
+ split = layout.split(factor=0.35)
+ split.use_property_split = False
+ split.label(text="Specular")
+ row = split.row(align=True)
+ row.prop(view_layer, "use_pass_glossy_direct", text="Light", toggle=True)
+ row.prop(view_layer, "use_pass_glossy_color", text="Color", toggle=True)
+
+ split = layout.split(factor=0.35)
+ split.use_property_split = False
+ split.label(text="Volume")
+ row = split.row(align=True)
+ row.prop(view_layer_eevee, "use_pass_volume_transmittance", text="Transmittance", toggle=True)
+ row.prop(view_layer_eevee, "use_pass_volume_scatter", text="Scatter", toggle=True)
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
+
+ col = layout.column(align=True)
+ col.prop(view_layer, "use_pass_emit", text="Emission")
+ col.prop(view_layer, "use_pass_environment")
+ col.prop(view_layer, "use_pass_shadow")
+ row = col.row()
+ row.prop(view_layer, "use_pass_ambient_occlusion", text="Ambient Occlusion")
+ row.active = scene_eevee.use_gtao
+
+
+class VIEWLAYER_PT_eevee_layer_passes_effects(ViewLayerButtonsPanel, Panel):
+ bl_label = "Effects"
+ bl_parent_id = "VIEWLAYER_PT_eevee_layer_passes"
+ COMPAT_ENGINES = {'BLENDER_EEVEE'}
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
+
+ view_layer = context.view_layer
+ view_layer_eevee = view_layer.eevee
+ scene = context.scene
+ scene_eevee = scene.eevee
+
+ col = flow.column()
+ col.prop(view_layer_eevee, "use_pass_bloom", text="Bloom")
+ col.active = scene_eevee.use_bloom
+
classes = (
VIEWLAYER_PT_layer,
VIEWLAYER_PT_eevee_layer_passes,
+ VIEWLAYER_PT_eevee_layer_passes_data,
+ VIEWLAYER_PT_eevee_layer_passes_light,
+ VIEWLAYER_PT_eevee_layer_passes_effects,
)
if __name__ == "__main__": # only for live edit.
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 37fe04e9d8a..07a8bba5023 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -219,6 +219,8 @@ data_to_c_simple(engines/eevee/shaders/lightprobe_planar_downsample_geom.glsl SR
data_to_c_simple(engines/eevee/shaders/lightprobe_planar_downsample_vert.glsl SRC)
data_to_c_simple(engines/eevee/shaders/prepass_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/prepass_vert.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/shadow_accum_frag.glsl SRC)
+
data_to_c_simple(engines/eevee/shaders/shadow_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/shadow_vert.glsl SRC)
data_to_c_simple(engines/eevee/shaders/bsdf_lut_frag.glsl SRC)
@@ -232,6 +234,7 @@ data_to_c_simple(engines/eevee/shaders/renderpass_postprocess_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/ltc_lib.glsl SRC)
data_to_c_simple(engines/eevee/shaders/ssr_lib.glsl SRC)
data_to_c_simple(engines/eevee/shaders/update_noise_frag.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/volumetric_accum_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/volumetric_lib.glsl SRC)
data_to_c_simple(engines/eevee/shaders/volumetric_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/volumetric_geom.glsl SRC)
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 = &half;
+ 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);
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_diffuse.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_diffuse.glsl
index e029905a908..714792489f6 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_diffuse.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_diffuse.glsl
@@ -4,8 +4,8 @@ void node_bsdf_diffuse(vec4 color, float roughness, vec3 N, out Closure result)
N = normalize(N);
result = CLOSURE_DEFAULT;
eevee_closure_diffuse(N, color.rgb, 1.0, true, result.radiance);
+ result.radiance = render_pass_diffuse_mask(color.rgb, result.radiance * color.rgb);
closure_load_ssr_data(vec3(0.0), 0.0, N, viewCameraVec, -1, result);
- result.radiance *= color.rgb;
}
#else
/* Stub diffuse because it is not compatible with volumetrics. */
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_eevee_specular.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_eevee_specular.glsl
index 34062cc8d02..747395857ee 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_eevee_specular.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_eevee_specular.glsl
@@ -32,7 +32,9 @@ void node_eevee_specular(vec4 diffuse,
float alpha = 1.0 - transp;
result = CLOSURE_DEFAULT;
- result.radiance = out_diff * diffuse.rgb + out_spec + emissive.rgb;
+ result.radiance = render_pass_diffuse_mask(diffuse.rgb, out_diff * diffuse.rgb);
+ result.radiance += render_pass_glossy_mask(vec3(1.0), out_spec);
+ result.radiance += render_pass_emission_mask(emissive.rgb);
result.radiance *= alpha;
result.transmittance = vec3(transp);
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_emission.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_emission.glsl
index 092b9ed08bb..502bc7f92d6 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_emission.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_emission.glsl
@@ -2,7 +2,7 @@ void node_emission(vec4 color, float strength, vec3 vN, out Closure result)
{
result = CLOSURE_DEFAULT;
#ifndef VOLUMETRICS
- result.radiance = color.rgb * strength;
+ result.radiance = render_pass_emission_mask(color.rgb) * strength;
result.ssr_normal = normal_encode(vN, viewCameraVec);
#else
result.emission = color.rgb * strength;
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_glass.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_glass.glsl
index 5038cb3892f..ece770f0e73 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_glass.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_glass.glsl
@@ -17,12 +17,12 @@ void node_bsdf_glass(
out_spec,
out_refr,
ssr_spec);
- out_refr *= refr_color;
- out_spec *= color.rgb;
float fresnel = F_eta(ior, dot(N, cameraVec));
vec3 vN = mat3(ViewMatrix) * N;
result = CLOSURE_DEFAULT;
- result.radiance = mix(out_refr, out_spec, fresnel);
+ result.radiance = render_pass_glossy_mask(refr_color, out_refr * refr_color) * (1.0 - fresnel);
+ result.radiance += render_pass_glossy_mask(color.rgb, out_spec * color.rgb) * fresnel;
+
closure_load_ssr_data(
ssr_spec * color.rgb * fresnel, roughness, N, viewCameraVec, int(ssr_id), result);
}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_glossy.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_glossy.glsl
index 75cc2e770c5..7513c3a4edb 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_glossy.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_glossy.glsl
@@ -7,7 +7,7 @@ void node_bsdf_glossy(vec4 color, float roughness, vec3 N, float ssr_id, out Clo
N, vec3(1.0), vec3(1.0), int(ssr_id), roughness, 1.0, true, out_spec, ssr_spec);
vec3 vN = mat3(ViewMatrix) * N;
result = CLOSURE_DEFAULT;
- result.radiance = out_spec * color.rgb;
+ result.radiance = render_pass_glossy_mask(vec3(1.0), out_spec) * color.rgb;
closure_load_ssr_data(ssr_spec * color.rgb, roughness, N, viewCameraVec, int(ssr_id), result);
}
#else
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl
index 7af409dd410..3c85dc6456c 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl
@@ -18,15 +18,22 @@ void convert_metallic_to_specular_tinted(vec3 basecol,
diffuse = basecol * (1.0 - metallic);
}
-vec3 principled_sheen(float NV, vec3 basecol_tint, float sheen_tint)
+/* Output sheen is to be multiplied by sheen_color. */
+void principled_sheen(float NV,
+ vec3 basecol_tint,
+ float sheen,
+ float sheen_tint,
+ out float out_sheen,
+ out vec3 sheen_color)
{
float f = 1.0 - NV;
/* Temporary fix for T59784. Normal map seems to contain NaNs for tangent space normal maps,
* therefore we need to clamp value. */
f = clamp(f, 0.0, 1.0);
/* Empirical approximation (manual curve fitting). Can be refined. */
- float sheen = f * f * f * 0.077 + f * 0.01 + 0.00026;
- return sheen * mix(vec3(1.0), basecol_tint, sheen_tint);
+ out_sheen = f * f * f * 0.077 + f * 0.01 + 0.00026;
+
+ sheen_color = sheen * mix(vec3(1.0), basecol_tint, sheen_tint);
}
void node_bsdf_principled(vec4 base_color,
@@ -61,18 +68,23 @@ void node_bsdf_principled(vec4 base_color,
ior = max(ior, 1e-5);
metallic = saturate(metallic);
transmission = saturate(transmission);
+ float m_transmission = 1.0 - transmission;
+
float dielectric = 1.0 - metallic;
transmission *= dielectric;
sheen *= dielectric;
subsurface_color *= dielectric;
- vec3 diffuse, f0, out_diff, out_spec, out_refr, ssr_spec;
+ vec3 diffuse, f0, out_diff, out_spec, out_refr, ssr_spec, sheen_color;
+ float out_sheen;
vec3 ctint = tint_from_color(base_color.rgb);
convert_metallic_to_specular_tinted(
base_color.rgb, ctint, metallic, specular, specular_tint, diffuse, f0);
float NV = dot(N, cameraVec);
- vec3 out_sheen = sheen * principled_sheen(NV, ctint, sheen_tint);
+ principled_sheen(NV, ctint, sheen, sheen_tint, out_sheen, sheen_color);
+
+ vec3 f90 = mix(vec3(1.0), f0, (1.0 - specular) * metallic);
/* Far from being accurate, but 2 glossy evaluation is too expensive.
* Most noticeable difference is at grazing angles since the bsdf lut
@@ -81,8 +93,12 @@ void node_bsdf_principled(vec4 base_color,
float fresnel = F_eta(ior, NV);
vec3 spec_col = F_color_blend(ior, fresnel, f0_glass) * fresnel;
f0 = mix(f0, spec_col, transmission);
+ f90 = mix(f90, spec_col, transmission);
- vec3 f90 = mix(vec3(1.0), f0, (1.0 - specular) * metallic);
+ /* Really poor approximation but needed to workaround issues with renderpasses. */
+ spec_col = mix(vec3(1.0), spec_col, transmission);
+ /* Match cycles. */
+ spec_col += float(clearcoat > 1e-5);
vec3 mixed_ss_base_color = mix(diffuse, subsurface_color.rgb, subsurface);
@@ -108,19 +124,22 @@ void node_bsdf_principled(vec4 base_color,
vec3 refr_color = base_color.rgb;
refr_color *= (refractionDepth > 0.0) ? refr_color :
vec3(1.0); /* Simulate 2 transmission event */
- out_refr *= refr_color * (1.0 - fresnel) * transmission;
+ refr_color *= saturate(1.0 - fresnel) * transmission;
+
+ sheen_color *= m_transmission;
+ mixed_ss_base_color *= m_transmission;
result = CLOSURE_DEFAULT;
- result.radiance = out_spec + out_refr;
- result.radiance += out_diff * out_sheen; /* Coarse approx. */
- result.radiance += emission.rgb;
+ result.radiance = render_pass_glossy_mask(refr_color, out_refr * refr_color);
+ result.radiance += render_pass_glossy_mask(spec_col, out_spec);
+ /* Coarse approx. */
+ result.radiance += render_pass_diffuse_mask(sheen_color, out_diff * out_sheen * sheen_color);
+ result.radiance += render_pass_emission_mask(emission.rgb);
result.radiance *= alpha;
-
closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result);
- mixed_ss_base_color *= alpha * (1.0 - transmission);
+ mixed_ss_base_color *= alpha;
closure_load_sss_data(sss_scalef, out_diff, mixed_ss_base_color, int(sss_id), result);
-
result.transmittance = vec3(1.0 - alpha);
}
@@ -156,22 +175,26 @@ void node_bsdf_principled_dielectric(vec4 base_color,
metallic = saturate(metallic);
float dielectric = 1.0 - metallic;
- vec3 diffuse, f0, out_diff, out_spec, ssr_spec;
+ vec3 diffuse, f0, out_diff, out_spec, ssr_spec, sheen_color;
+ float out_sheen;
vec3 ctint = tint_from_color(base_color.rgb);
convert_metallic_to_specular_tinted(
base_color.rgb, ctint, metallic, specular, specular_tint, diffuse, f0);
+ vec3 f90 = mix(vec3(1.0), f0, (1.0 - specular) * metallic);
+
float NV = dot(N, cameraVec);
- vec3 out_sheen = sheen * principled_sheen(NV, ctint, sheen_tint);
+ principled_sheen(NV, ctint, sheen, sheen_tint, out_sheen, sheen_color);
eevee_closure_default(
- N, diffuse, f0, vec3(1.0), int(ssr_id), roughness, 1.0, true, out_diff, out_spec, ssr_spec);
+ N, diffuse, f0, f90, int(ssr_id), roughness, 1.0, true, out_diff, out_spec, ssr_spec);
result = CLOSURE_DEFAULT;
- result.radiance = out_spec + out_diff * (diffuse + out_sheen);
- result.radiance += emission.rgb;
+ result.radiance = render_pass_glossy_mask(vec3(1.0), out_spec);
+ result.radiance += render_pass_diffuse_mask(sheen_color, out_diff * out_sheen * sheen_color);
+ result.radiance += render_pass_diffuse_mask(diffuse, out_diff * diffuse);
+ result.radiance += render_pass_emission_mask(emission.rgb);
result.radiance *= alpha;
-
closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result);
result.transmittance = vec3(1.0 - alpha);
@@ -214,10 +237,9 @@ void node_bsdf_principled_metallic(vec4 base_color,
N, base_color.rgb, f90, int(ssr_id), roughness, 1.0, true, out_spec, ssr_spec);
result = CLOSURE_DEFAULT;
- result.radiance = out_spec;
- result.radiance += emission.rgb;
+ result.radiance = render_pass_glossy_mask(vec3(1.0), out_spec);
+ result.radiance += render_pass_emission_mask(emission.rgb);
result.radiance *= alpha;
-
closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result);
result.transmittance = vec3(1.0 - alpha);
@@ -268,10 +290,12 @@ void node_bsdf_principled_clearcoat(vec4 base_color,
true,
out_spec,
ssr_spec);
+ /* Match cycles. */
+ float spec_col = 1.0 + float(clearcoat > 1e-5);
result = CLOSURE_DEFAULT;
- result.radiance = out_spec;
- result.radiance += emission.rgb;
+ result.radiance = render_pass_glossy_mask(vec3(spec_col), out_spec);
+ result.radiance += render_pass_emission_mask(emission.rgb);
result.radiance *= alpha;
closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result);
@@ -310,7 +334,8 @@ void node_bsdf_principled_subsurface(vec4 base_color,
metallic = saturate(metallic);
N = normalize(N);
- vec3 diffuse, f0, out_diff, out_spec, ssr_spec;
+ vec3 diffuse, f0, out_diff, out_spec, ssr_spec, sheen_color;
+ float out_sheen;
vec3 ctint = tint_from_color(base_color.rgb);
convert_metallic_to_specular_tinted(
base_color.rgb, ctint, metallic, specular, specular_tint, diffuse, f0);
@@ -320,7 +345,7 @@ void node_bsdf_principled_subsurface(vec4 base_color,
float sss_scalef = avg(sss_scale) * subsurface;
float NV = dot(N, cameraVec);
- vec3 out_sheen = sheen * principled_sheen(NV, ctint, sheen_tint);
+ principled_sheen(NV, ctint, sheen, sheen_tint, out_sheen, sheen_color);
vec3 f90 = mix(vec3(1.0), base_color.rgb, (1.0 - specular) * metallic);
@@ -338,14 +363,14 @@ void node_bsdf_principled_subsurface(vec4 base_color,
ssr_spec);
result = CLOSURE_DEFAULT;
- result.radiance = out_spec;
- result.radiance += out_diff * out_sheen;
- result.radiance += emission.rgb;
+ result.radiance = render_pass_glossy_mask(vec3(1.0), out_spec);
+ result.radiance += render_pass_diffuse_mask(sheen_color, out_diff * out_sheen * sheen_color);
+ result.radiance += render_pass_emission_mask(emission.rgb);
result.radiance *= alpha;
closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result);
- mixed_ss_base_color *= alpha * (1.0 - transmission);
+ mixed_ss_base_color *= alpha;
closure_load_sss_data(sss_scalef, out_diff, mixed_ss_base_color, int(sss_id), result);
result.transmittance = vec3(1.0 - alpha);
@@ -400,16 +425,18 @@ void node_bsdf_principled_glass(vec4 base_color,
vec3 refr_color = base_color.rgb;
refr_color *= (refractionDepth > 0.0) ? refr_color :
vec3(1.0); /* Simulate 2 transmission events */
- out_refr *= refr_color;
float fresnel = F_eta(ior, dot(N, cameraVec));
vec3 spec_col = F_color_blend(ior, fresnel, f0);
- out_spec *= spec_col;
- ssr_spec *= spec_col * fresnel;
+ spec_col *= fresnel;
+ refr_color *= (1.0 - fresnel);
+
+ ssr_spec *= spec_col;
result = CLOSURE_DEFAULT;
- result.radiance = mix(out_refr, out_spec, fresnel);
- result.radiance += emission.rgb;
+ result.radiance = render_pass_glossy_mask(refr_color, out_refr * refr_color);
+ result.radiance += render_pass_glossy_mask(spec_col, out_spec * spec_col);
+ result.radiance += render_pass_emission_mask(emission.rgb);
result.radiance *= alpha;
closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result);
result.transmittance = vec3(1.0 - alpha);
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_refraction.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_refraction.glsl
index 906964e1539..4088d6db06a 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_refraction.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_refraction.glsl
@@ -8,7 +8,7 @@ void node_bsdf_refraction(vec4 color, float roughness, float ior, vec3 N, out Cl
vec3 vN = mat3(ViewMatrix) * N;
result = CLOSURE_DEFAULT;
result.ssr_normal = normal_encode(vN, viewCameraVec);
- result.radiance = out_refr * color.rgb;
+ result.radiance = render_pass_glossy_mask(color.rgb, out_refr * color.rgb);
}
#else
/* Stub refraction because it is not compatible with volumetrics. */
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_subsurface_scattering.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_subsurface_scattering.glsl
index 241228c0d4c..9bbbe71b206 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_subsurface_scattering.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_subsurface_scattering.glsl
@@ -19,6 +19,7 @@ void node_subsurface_scattering(vec4 color,
/* Not perfect for texture_blur not exactly equal to 0.0 or 1.0. */
vec3 sss_albedo = mix(color.rgb, vec3(1.0), texture_blur);
out_diff *= mix(vec3(1.0), color.rgb, texture_blur);
+ result.radiance = render_pass_sss_mask(sss_albedo);
closure_load_sss_data(scale, out_diff, sss_albedo, int(sss_id), result);
}
#else
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_translucent.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_translucent.glsl
index 749b3a4c11f..5c3ed81410a 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_translucent.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_translucent.glsl
@@ -5,7 +5,7 @@ void node_bsdf_translucent(vec4 color, vec3 N, out Closure result)
result = CLOSURE_DEFAULT;
eevee_closure_diffuse(-N, color.rgb, 1.0, false, result.radiance);
closure_load_ssr_data(vec3(0.0), 0.0, N, viewCameraVec, -1, result);
- result.radiance *= color.rgb;
+ result.radiance = render_pass_diffuse_mask(color.rgb, result.radiance * color.rgb);
}
#else
/* Stub translucent because it is not compatible with volumetrics. */
diff --git a/source/blender/makesdna/DNA_layer_types.h b/source/blender/makesdna/DNA_layer_types.h
index 5480bed51e8..09d02e9a375 100644
--- a/source/blender/makesdna/DNA_layer_types.h
+++ b/source/blender/makesdna/DNA_layer_types.h
@@ -28,6 +28,26 @@ extern "C" {
#include "DNA_freestyle_types.h"
#include "DNA_listBase.h"
+/* Renderpasses for EEVEE.
+ * ViewLayerEEVEE.render_passes */
+typedef enum eViewLayerEEVEEPassType {
+ EEVEE_RENDER_PASS_COMBINED = (1 << 0),
+ EEVEE_RENDER_PASS_Z = (1 << 1),
+ EEVEE_RENDER_PASS_MIST = (1 << 2),
+ EEVEE_RENDER_PASS_NORMAL = (1 << 3),
+ EEVEE_RENDER_PASS_DIFFUSE_LIGHT = (1 << 4),
+ EEVEE_RENDER_PASS_DIFFUSE_COLOR = (1 << 5),
+ EEVEE_RENDER_PASS_SPECULAR_LIGHT = (1 << 6),
+ EEVEE_RENDER_PASS_SPECULAR_COLOR = (1 << 7),
+ EEVEE_RENDER_PASS_VOLUME_TRANSMITTANCE = (1 << 8),
+ EEVEE_RENDER_PASS_VOLUME_SCATTER = (1 << 9),
+ EEVEE_RENDER_PASS_EMIT = (1 << 10),
+ EEVEE_RENDER_PASS_ENVIRONMENT = (1 << 11),
+ EEVEE_RENDER_PASS_SHADOW = (1 << 12),
+ EEVEE_RENDER_PASS_AO = (1 << 13),
+ EEVEE_RENDER_PASS_BLOOM = (1 << 14),
+} eViewLayerEEVEEPassType;
+
typedef struct Base {
struct Base *next, *prev;
@@ -76,6 +96,12 @@ typedef struct LayerCollection {
short _pad2[3];
} LayerCollection;
+/* Type containing EEVEE settings per view-layer */
+typedef struct ViewLayerEEVEE {
+ int render_passes;
+ int _pad[1];
+} ViewLayerEEVEE;
+
typedef struct ViewLayer {
struct ViewLayer *next, *prev;
/** MAX_NAME. */
@@ -106,6 +132,7 @@ typedef struct ViewLayer {
struct IDProperty *id_properties;
struct FreestyleConfig freestyle_config;
+ struct ViewLayerEEVEE eevee;
/* Runtime data */
/** ViewLayerEngineData. */
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 7cd6b5f5013..0b5ab37b5ca 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -318,6 +318,9 @@ typedef enum eScenePassType {
#define RE_PASSNAME_SUBSURFACE_COLOR "SubsurfaceCol"
#define RE_PASSNAME_FREESTYLE "Freestyle"
+#define RE_PASSNAME_BLOOM "BloomCol"
+#define RE_PASSNAME_VOLUME_TRANSMITTANCE "VolumeTransmCol"
+#define RE_PASSNAME_VOLUME_SCATTER "VolumeScatterCol"
/* View - MultiView */
typedef struct SceneRenderView {
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index 7d82b97868d..41858fffcf5 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -677,6 +677,7 @@ extern StructRNA RNA_View3DCursor;
extern StructRNA RNA_View3DOverlay;
extern StructRNA RNA_View3DShading;
extern StructRNA RNA_ViewLayer;
+extern StructRNA RNA_ViewLayerEEVEE;
extern StructRNA RNA_VoronoiTexture;
extern StructRNA RNA_WalkNavigation;
extern StructRNA RNA_WarpModifier;
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index d2a17967de9..32c6239da5a 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -3756,6 +3756,30 @@ static void rna_def_unit_settings(BlenderRNA *brna)
RNA_def_property_update(prop, NC_WINDOW, NULL);
}
+static void rna_def_view_layer_eevee(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+ srna = RNA_def_struct(brna, "ViewLayerEEVEE", NULL);
+ RNA_def_struct_ui_text(srna, "EEVEE Settings", "View layer settings for EEVEE");
+
+ prop = RNA_def_property(srna, "use_pass_volume_scatter", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "render_passes", EEVEE_RENDER_PASS_VOLUME_SCATTER);
+ RNA_def_property_ui_text(prop, "Volume Scatter", "Deliver volume scattering pass");
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update");
+
+ prop = RNA_def_property(srna, "use_pass_volume_transmittance", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(
+ prop, NULL, "render_passes", EEVEE_RENDER_PASS_VOLUME_TRANSMITTANCE);
+ RNA_def_property_ui_text(prop, "Volume Transmittance", "Deliver volume transmittance pass");
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update");
+
+ prop = RNA_def_property(srna, "use_pass_bloom", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "render_passes", EEVEE_RENDER_PASS_BLOOM);
+ RNA_def_property_ui_text(prop, "Bloom", "Deliver bloom pass");
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update");
+}
+
void rna_def_view_layer_common(StructRNA *srna, const bool scene)
{
PropertyRNA *prop;
@@ -3801,6 +3825,11 @@ void rna_def_view_layer_common(StructRNA *srna, const bool scene)
"Z, Index, normal, UV and vector passes are only affected by surfaces with "
"alpha transparency equal to or higher than this threshold");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+
+ prop = RNA_def_property(srna, "eevee", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_NEVER_NULL);
+ RNA_def_property_struct_type(prop, "ViewLayerEEVEE");
+ RNA_def_property_ui_text(prop, "EEVEE Settings", "View layer settings for EEVEE");
}
/* layer options */
@@ -7546,6 +7575,7 @@ void RNA_def_scene(BlenderRNA *brna)
rna_def_display_safe_areas(brna);
rna_def_scene_display(brna);
rna_def_scene_eevee(brna);
+ rna_def_view_layer_eevee(brna);
RNA_define_animate_sdna(true);
/* *** Animated *** */
rna_def_scene_render_data(brna);
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index fdea081d8f1..975a3bdaf2e 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -382,14 +382,32 @@ static const EnumPropertyItem rna_enum_studio_light_items[] = {
};
static const EnumPropertyItem rna_enum_view3dshading_render_pass_type_items[] = {
- {SCE_PASS_COMBINED, "COMBINED", 0, "Combined", ""},
- /* {SCE_PASS_Z, "Z", 0, "Z", ""},*/
- {SCE_PASS_AO, "AO", 0, "Ambient Occlusion", ""},
- {SCE_PASS_NORMAL, "NORMAL", 0, "Normal", ""},
- {SCE_PASS_MIST, "MIST", 0, "Mist", ""},
- {SCE_PASS_SUBSURFACE_DIRECT, "SUBSURFACE_DIRECT", 0, "Subsurface Direct", ""},
- /* {SCE_PASS_SUBSURFACE_INDIRECT, "SUBSURFACE_INDIRECT", 0, "Subsurface Indirect", ""}, */
- {SCE_PASS_SUBSURFACE_COLOR, "SUBSURFACE_COLOR", 0, "Subsurface Color", ""},
+ {0, "", ICON_NONE, "General", ""},
+ {EEVEE_RENDER_PASS_COMBINED, "COMBINED", 0, "Combined", ""},
+ {EEVEE_RENDER_PASS_EMIT, "EMISSION", 0, "Emission", ""},
+ {EEVEE_RENDER_PASS_ENVIRONMENT, "ENVIRONMENT", 0, "Environment", ""},
+ {EEVEE_RENDER_PASS_AO, "AO", 0, "Ambient Occlusion", ""},
+ {EEVEE_RENDER_PASS_SHADOW, "SHADOW", 0, "Shadow", ""},
+
+ {0, "", ICON_NONE, "Light", ""},
+ {EEVEE_RENDER_PASS_DIFFUSE_LIGHT, "DIFFUSE_LIGHT", 0, "Diffuse Light", ""},
+ {EEVEE_RENDER_PASS_DIFFUSE_COLOR, "DIFFUSE_COLOR", 0, "Diffuse Color", ""},
+ {EEVEE_RENDER_PASS_SPECULAR_LIGHT, "SPECULAR_LIGHT", 0, "Specular Light", ""},
+ {EEVEE_RENDER_PASS_SPECULAR_COLOR, "SPECULAR_COLOR", 0, "Specular Color", ""},
+ {EEVEE_RENDER_PASS_VOLUME_TRANSMITTANCE,
+ "VOLUME_TRANSMITTANCE",
+ 0,
+ "Volume Transmittance",
+ ""},
+ {EEVEE_RENDER_PASS_VOLUME_SCATTER, "VOLUME_SCATTER", 0, "Volume Scattering", ""},
+
+ {0, "", ICON_NONE, "Effects", ""},
+ {EEVEE_RENDER_PASS_BLOOM, "BLOOM", 0, "Bloom", ""},
+
+ {0, "", ICON_NONE, "Data", ""},
+ {EEVEE_RENDER_PASS_NORMAL, "NORMAL", 0, "Normal", ""},
+ {EEVEE_RENDER_PASS_MIST, "MIST", 0, "Mist", ""},
+
{0, NULL, 0, NULL, NULL},
};
@@ -1242,6 +1260,30 @@ static const EnumPropertyItem *rna_View3DShading_studio_light_itemf(bContext *UN
return item;
}
+static const EnumPropertyItem *rna_3DViewShading_render_pass_itemf(bContext *C,
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
+{
+ Scene *scene = CTX_data_scene(C);
+
+ const bool ao_enabled = scene->eevee.flag & SCE_EEVEE_GTAO_ENABLED;
+ const bool bloom_enabled = scene->eevee.flag & SCE_EEVEE_BLOOM_ENABLED;
+
+ int totitem = 0;
+ EnumPropertyItem *result = NULL;
+ for (int i = 0; rna_enum_view3dshading_render_pass_type_items[i].identifier != NULL; i++) {
+ const EnumPropertyItem *item = &rna_enum_view3dshading_render_pass_type_items[i];
+ if (!((!ao_enabled && item->value == EEVEE_RENDER_PASS_AO) ||
+ (!bloom_enabled &&
+ (item->value == EEVEE_RENDER_PASS_BLOOM || STREQ(item->name, "Effects"))))) {
+ RNA_enum_item_add(&result, &totitem, item);
+ }
+ }
+ *r_free = true;
+ return result;
+}
+
static void rna_SpaceView3D_use_local_collections_update(bContext *C, PointerRNA *ptr)
{
Main *bmain = CTX_data_main(C);
@@ -3328,6 +3370,7 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna)
RNA_def_property_enum_sdna(prop, NULL, "render_pass");
RNA_def_property_enum_items(prop, rna_enum_view3dshading_render_pass_type_items);
RNA_def_property_ui_text(prop, "Render Pass", "Render Pass to show in the viewport");
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_3DViewShading_render_pass_itemf");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
}
diff --git a/source/blender/nodes/composite/node_composite_tree.c b/source/blender/nodes/composite/node_composite_tree.c
index 89349d91f94..93f2ba44a3a 100644
--- a/source/blender/nodes/composite/node_composite_tree.c
+++ b/source/blender/nodes/composite/node_composite_tree.c
@@ -281,8 +281,11 @@ void ntreeCompositUpdateRLayers(bNodeTree *ntree)
}
}
-void ntreeCompositRegisterPass(
- bNodeTree *ntree, Scene *scene, ViewLayer *view_layer, const char *name, int type)
+void ntreeCompositRegisterPass(bNodeTree *ntree,
+ Scene *scene,
+ ViewLayer *view_layer,
+ const char *name,
+ eNodeSocketDatatype type)
{
bNode *node;
diff --git a/source/blender/nodes/composite/nodes/node_composite_image.c b/source/blender/nodes/composite/nodes/node_composite_image.c
index b74f325a3fa..f8a97868959 100644
--- a/source/blender/nodes/composite/nodes/node_composite_image.c
+++ b/source/blender/nodes/composite/nodes/node_composite_image.c
@@ -72,13 +72,14 @@ static bNodeSocketTemplate cmp_node_rlayers_out[] = {
{SOCK_RGBA, 0, N_(RE_PASSNAME_SUBSURFACE_COLOR), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{-1, 0, ""},
};
+#define MAX_LEGACY_SOCKET_INDEX 30
static void cmp_node_image_add_pass_output(bNodeTree *ntree,
bNode *node,
const char *name,
const char *passname,
int rres_index,
- int type,
+ eNodeSocketDatatype type,
int is_rlayers,
LinkNodePair *available_sockets,
int *prev_index)
@@ -94,8 +95,8 @@ static void cmp_node_image_add_pass_output(bNodeTree *ntree,
* New sockets are placed behind the previously traversed one,
* but always after the first 31. */
int after_index = *prev_index;
- if (is_rlayers && after_index < 30) {
- after_index = 30;
+ if (is_rlayers && after_index < MAX_LEGACY_SOCKET_INDEX) {
+ after_index = MAX_LEGACY_SOCKET_INDEX;
}
if (rres_index >= 0) {
@@ -238,8 +239,12 @@ typedef struct RLayerUpdateData {
int prev_index;
} RLayerUpdateData;
-void node_cmp_rlayers_register_pass(
- bNodeTree *ntree, bNode *node, Scene *scene, ViewLayer *view_layer, const char *name, int type)
+void node_cmp_rlayers_register_pass(bNodeTree *ntree,
+ bNode *node,
+ Scene *scene,
+ ViewLayer *view_layer,
+ const char *name,
+ eNodeSocketDatatype type)
{
RLayerUpdateData *data = node->storage;
@@ -389,7 +394,7 @@ static void cmp_node_image_verify_outputs(bNodeTree *ntree, bNode *node, bool rl
break;
}
}
- if (!link && (!rlayer || sock_index > 30)) {
+ if (!link && (!rlayer || sock_index > MAX_LEGACY_SOCKET_INDEX)) {
MEM_freeN(sock->storage);
nodeRemoveSocket(ntree, node, sock);
}
@@ -508,7 +513,7 @@ const char *node_cmp_rlayers_sock_to_pass(int sock_index)
RE_PASSNAME_SUBSURFACE_INDIRECT,
RE_PASSNAME_SUBSURFACE_COLOR,
};
- if (sock_index > 30) {
+ if (sock_index > MAX_LEGACY_SOCKET_INDEX) {
return NULL;
}
return sock_to_passname[sock_index];
diff --git a/source/blender/render/extern/include/RE_engine.h b/source/blender/render/extern/include/RE_engine.h
index 12e9123b5cb..88614de1641 100644
--- a/source/blender/render/extern/include/RE_engine.h
+++ b/source/blender/render/extern/include/RE_engine.h
@@ -26,6 +26,7 @@
#include "DNA_listBase.h"
#include "DNA_scene_types.h"
+#include "DNA_node_types.h"
#include "RNA_types.h"
#include "RE_bake.h"
@@ -117,7 +118,7 @@ typedef void (*update_render_passes_cb_t)(void *userdata,
const char *name,
int channels,
const char *chanid,
- int type);
+ eNodeSocketDatatype type);
typedef struct RenderEngine {
RenderEngineType *type;
@@ -212,7 +213,7 @@ void RE_engine_register_pass(struct RenderEngine *engine,
const char *name,
int channels,
const char *chanid,
- int type);
+ eNodeSocketDatatype type);
/* Engine Types */
diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c
index 90058da5f0c..598f300cf86 100644
--- a/source/blender/render/intern/source/external_engine.c
+++ b/source/blender/render/intern/source/external_engine.c
@@ -863,7 +863,7 @@ void RE_engine_register_pass(struct RenderEngine *engine,
const char *name,
int channels,
const char *chanid,
- int type)
+ eNodeSocketDatatype type)
{
if (!(scene && view_layer && engine && engine->update_render_passes_cb)) {
return;
diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c
index 120787a8d13..b2225d70eaf 100644
--- a/source/blender/render/intern/source/render_result.c
+++ b/source/blender/render/intern/source/render_result.c
@@ -442,6 +442,15 @@ RenderResult *render_result_new(Render *re,
if (view_layer->passflag & SCE_PASS_SUBSURFACE_COLOR) {
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SUBSURFACE_COLOR, view, "RGB");
}
+ if (view_layer->eevee.render_passes & EEVEE_RENDER_PASS_BLOOM) {
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_BLOOM, view, "RGB");
+ }
+ if (view_layer->eevee.render_passes & EEVEE_RENDER_PASS_VOLUME_SCATTER) {
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_VOLUME_SCATTER, view, "RGB");
+ }
+ if (view_layer->eevee.render_passes & EEVEE_RENDER_PASS_VOLUME_TRANSMITTANCE) {
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_VOLUME_TRANSMITTANCE, view, "RGB");
+ }
#undef RENDER_LAYER_ADD_PASS_SAFE
}
}