diff options
author | Jeroen Bakker <jeroen@blender.org> | 2020-12-14 16:55:53 +0300 |
---|---|---|
committer | Jeroen Bakker <jeroen@blender.org> | 2020-12-14 17:03:29 +0300 |
commit | 6714b800d1716f7c7dec9a640d1c615bbf1a938f (patch) | |
tree | 22a9c13951a167f8044fcec3d108831d2ea5ae2f /source | |
parent | e3068f38c8c8df8cf198dc694aae9cc0c6e88633 (diff) |
Cryptomatte: apply volume transmittance to Eevee.
This patch will add volumetric transmittance to the cryptomatte coverage
data of all samples when post processing the cryptomatte passes.
It was discussed with Cycles that this is desired, but tricky to
implement in Cycles.
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/draw/engines/eevee/eevee_cryptomatte.c | 63 |
1 files changed, 48 insertions, 15 deletions
diff --git a/source/blender/draw/engines/eevee/eevee_cryptomatte.c b/source/blender/draw/engines/eevee/eevee_cryptomatte.c index 95f5aa8b628..9150de7184a 100644 --- a/source/blender/draw/engines/eevee/eevee_cryptomatte.c +++ b/source/blender/draw/engines/eevee/eevee_cryptomatte.c @@ -125,7 +125,7 @@ void EEVEE_cryptomatte_renderpasses_init(EEVEE_Data *vedata) return; } if (eevee_cryptomatte_active_layers(view_layer) != 0) { - g_data->render_passes |= EEVEE_RENDER_PASS_CRYPTOMATTE; + g_data->render_passes |= EEVEE_RENDER_PASS_CRYPTOMATTE | EEVEE_RENDER_PASS_VOLUME_LIGHT; g_data->cryptomatte_accurate_mode = (view_layer->cryptomatte_flag & VIEW_LAYER_CRYPTOMATTE_ACCURATE) != 0; } @@ -137,7 +137,8 @@ void EEVEE_cryptomatte_output_init(EEVEE_ViewLayerData *UNUSED(sldata), { EEVEE_FramebufferList *fbl = vedata->fbl; EEVEE_TextureList *txl = vedata->txl; - EEVEE_PrivateData *g_data = vedata->stl->g_data; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_PrivateData *g_data = stl->g_data; DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); const DRWContextState *draw_ctx = DRW_context_state_get(); @@ -469,6 +470,8 @@ static void eevee_cryptomatte_postprocess_weights(EEVEE_Data *vedata) { EEVEE_StorageList *stl = vedata->stl; EEVEE_PrivateData *g_data = stl->g_data; + EEVEE_EffectsInfo *effects = stl->effects; + EEVEE_TextureList *txl = vedata->txl; const DRWContextState *draw_ctx = DRW_context_state_get(); const ViewLayer *view_layer = draw_ctx->view_layer; const int num_cryptomatte_layers = eevee_cryptomatte_layers_count(view_layer); @@ -478,11 +481,25 @@ static void eevee_cryptomatte_postprocess_weights(EEVEE_Data *vedata) EEVEE_CryptomatteSample *accum_buffer = g_data->cryptomatte_accum_buffer; BLI_assert(accum_buffer); + float *volumetric_transmittance_buffer = NULL; + if ((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) { + volumetric_transmittance_buffer = GPU_texture_read( + txl->volume_transmittance_accum, GPU_DATA_FLOAT, 0); + } + const int num_samples = effects->taa_current_sample; + int accum_pixel_index = 0; int accum_pixel_stride = eevee_cryptomatte_pixel_stride(view_layer); for (int pixel_index = 0; pixel_index < buffer_size; pixel_index++, accum_pixel_index += accum_pixel_stride) { + float coverage = 1.0f; + if (volumetric_transmittance_buffer != NULL) { + coverage = (volumetric_transmittance_buffer[pixel_index * 4] + + volumetric_transmittance_buffer[pixel_index * 4 + 1] + + volumetric_transmittance_buffer[pixel_index * 4 + 2]) / + (3.0f * num_samples); + } for (int layer = 0; layer < num_cryptomatte_layers; layer++) { const int layer_offset = eevee_cryptomatte_layer_offset(view_layer, layer); /* Calculate the total weight of the sample. */ @@ -493,24 +510,40 @@ static void eevee_cryptomatte_postprocess_weights(EEVEE_Data *vedata) } BLI_assert(total_weight > 0.0f); - float total_weight_inv = 1.0f / total_weight; - for (int level = 0; level < num_levels; level++) { - EEVEE_CryptomatteSample *sample = &accum_buffer[accum_pixel_index + layer_offset + level]; - /* Remove background samples. These samples were used to determine the correct weight - * but won't be part of the final result. */ - if (sample->hash == 0.0f) { + float total_weight_inv = coverage / total_weight; + if (total_weight_inv > 0.0f) { + for (int level = 0; level < num_levels; level++) { + EEVEE_CryptomatteSample *sample = + &accum_buffer[accum_pixel_index + layer_offset + level]; + /* Remove background samples. These samples were used to determine the correct weight + * but won't be part of the final result. */ + if (sample->hash == 0.0f) { + sample->weight = 0.0f; + } + sample->weight *= total_weight_inv; + } + + /* Sort accum buffer by coverage of each sample. */ + qsort(&accum_buffer[accum_pixel_index + layer_offset], + num_levels, + sizeof(EEVEE_CryptomatteSample), + eevee_cryptomatte_sample_cmp_reverse); + } + else { + /* This pixel doesn't have any weight, so clear it fully. */ + for (int level = 0; level < num_levels; level++) { + EEVEE_CryptomatteSample *sample = + &accum_buffer[accum_pixel_index + layer_offset + level]; sample->weight = 0.0f; + sample->hash = 0.0f; } - sample->weight *= total_weight_inv; } - - /* Sort accum buffer by coverage of each sample. */ - qsort(&accum_buffer[accum_pixel_index + layer_offset], - num_levels, - sizeof(EEVEE_CryptomatteSample), - eevee_cryptomatte_sample_cmp_reverse); } } + + if (volumetric_transmittance_buffer) { + MEM_freeN(volumetric_transmittance_buffer); + } } /* Extract cryptomatte layer from the cryptomatte_accum_buffer to render passes. */ |