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 /source/blender/draw/engines/eevee/eevee_materials.c
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
Diffstat (limited to 'source/blender/draw/engines/eevee/eevee_materials.c')
-rw-r--r--source/blender/draw/engines/eevee/eevee_materials.c731
1 files changed, 627 insertions, 104 deletions
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);
+}
+/* \} */