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_renderpasses.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_renderpasses.c')
-rw-r--r--source/blender/draw/engines/eevee/eevee_renderpasses.c232
1 files changed, 192 insertions, 40 deletions
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);
}