Page MenuHome

EEVEE Cryptomatte
ClosedPublic

Authored by Jeroen Bakker (jbakker) on Oct 9 2020, 5:05 PM.
Tokens
"Love" token, awarded by Raimund58."Mountain of Wealth" token, awarded by Brandon777."Heartbreak" token, awarded by davinci321."Cup of Joe" token, awarded by filibis."Love" token, awarded by KINjO."Like" token, awarded by YAFU."Love" token, awarded by 295032."Love" token, awarded by mistajuliax."100" token, awarded by amonpaike."Manufacturing Defect?" token, awarded by zanqdo.

Details

Summary

Cryptomatte is a standard to efficiently create mattes for compositing. The
renderer outputs the required render passes, which can then be used in the
compositor to create masks for specified objects. Unlike the Material and Object
Index passes, the objects to isolate are selected in compositing, and mattes
will be anti-aliased.

Cryptomatte was already available in Cycles this patch adds it to the EEVEE
render engine. Original specification can be found at
https://raw.githubusercontent.com/Psyop/Cryptomatte/master/specification/IDmattes_poster.pdf

Accurate mode

Following Cycles, there are two accuracy modes. The difference between the two
modes is the number of render samples they take into account to create the
render passes. When accurate mode is off the number of levels is used. When
accuracy mode is active, the number of render samples is used.

Deviation from standard

Cryptomatte specification is based on a path trace approach where samples and
coverage are calculated at the same time. In EEVEE a sample is an exact match on
top of a prepared depth buffer. Coverage is at that moment always 1. By sampling
multiple times the number of surface hits decides the actual surface coverage
for a matte per pixel.

Implementation Overview

When drawing to the cryptomatte GPU buffer the depth of the fragment is matched
to the active depth buffer. The hashes of each cryptomatte layer is written in
the GPU buffer. The exact layout depends on the active cryptomatte layers. The
GPU buffer is downloaded and integrated into an accumulation buffer (stored in
CPU RAM).

The accumulation buffer stores the hashes + weights for a number of levels,
layers per pixel. When a hash already exists the weight will be increased. When
the hash doesn't exists it will be added to the buffer.

After all the samples have been calculated the accumulation buffer is processed.
During this phase the total pixel weights of each layer is mapped to be in a
range between 0 and 1. The hashes are also sorted (highest weight first).

Blender Kernel now has a BKE_cryptomatte header that access to common
functions for cryptomatte. This will in the future be used by the API.

Known Limitations

  • Alpha blended materials aren't supported. Alpha blended materials support in render passes needs research how to implement it in a maintainable way for any render pass.

Future work

This is a list of tasks that needs to be done for the same release that this
patch lands on (Blender 2.92)

  • T82571 Add render tests.
  • T82572 Documentation.
  • T82573 Store hashes + Object names in the render result header.
  • T82574 Use threading to increase performance in accumulation and post processing.
  • T82575 Merge the cycles and EEVEE settings as they are identical.
  • T82576 Add RNA to extract the cryptomatte hashes to use in python scripts.

Diff Detail

Repository
rB Blender
Branch
arcpatch-D9165_1 (branched from master)
Build Status
Buildable 11200
Build 11200: arc lint + arc unit

Event Timeline

There are a very large number of changes, so older changes are hidden. Show Older Changes
Jeroen Bakker (jbakker) edited the summary of this revision. (Show Details)Oct 30 2020, 2:24 PM
  • Cleanup: renamed framebuffer name
Jeroen Bakker (jbakker) retitled this revision from [WIP] EEVEE Cryptomatte to EEVEE Cryptomatte.Oct 30 2020, 2:30 PM
Jeroen Bakker (jbakker) edited the summary of this revision. (Show Details)
  • Add Support for material layer
Jeroen Bakker (jbakker) edited the summary of this revision. (Show Details)Oct 30 2020, 4:57 PM

@Jeroen Bakker (jbakker) i tested your cryptomattes patch and while it works, it doesnt work at 4k it produces bugged result here is example https://prnt.sc/vcc1xh it seems to work at fullhd resolution but as resolution increases it gets bugged

@Jeroen Bakker (jbakker) i tested your cryptomattes patch and while it works, it doesnt work at 4k it produces bugged result here is example https://prnt.sc/vcc1xh it seems to work at fullhd resolution but as resolution increases it gets bugged

Yes I saw this last week, will mention it in the open point for this task. Thanks for testing!

Jeroen Bakker (jbakker) edited the summary of this revision. (Show Details)Nov 3 2020, 9:25 AM

increasing the levels from 6 to 8 seems to fix the issue i gonna try using this for production so i let you know if i find any problems but so far so good!

  • Kernel: Added Cryptomatte hash functions
  • Add Support for particle hair
  • Added support for Object hair
  • Make sure all buffers are freed correcly
  • Moved pass init code to cache init
  • Code cleanup
  • Support for Cryptomatte Assets
  • Support for multiple cryptomatte passes
  • Cleanup: renamed framebuffer name
  • Add Support for material layer
  • Some documentation and cleanup. (incomplete)
Jeroen Bakker (jbakker) edited the summary of this revision. (Show Details)Nov 9 2020, 3:19 PM
  • Fix stripes at top of buffer in complex scenes.
Jeroen Bakker (jbakker) edited the summary of this revision. (Show Details)Nov 9 2020, 4:32 PM
Jeroen Bakker (jbakker) edited the summary of this revision. (Show Details)
  • Fix striped on top of buffer (correcting previous fix)
  • Added volumetric transmittance
  • Added volumetric transmittance
Jeroen Bakker (jbakker) edited the summary of this revision. (Show Details)
Jeroen Bakker (jbakker) edited the summary of this revision. (Show Details)Nov 10 2020, 2:19 PM

Rebased with latest master

  • Separated the hashing and float conversion according to the spec.

Fixed spelling error

I've observed some strange Antialiasing / Alpha behavoir in my test:

I don't know if it's an issue with the compositor or with the render passes / EEVEE integration.

I'm trying to think about doing the accumulation on the GPU but that might increase VRAM usage.

source/blender/blenkernel/intern/cryptomatte.c
63

Use BLI_hash_mm3 instead of code duplication.

source/blender/draw/engines/eevee/eevee_cryptomatte.c
176

Style: Use a semicolon after the second attachment for better auto-formatting.

source/blender/draw/engines/eevee/eevee_shaders.c
703

Any reason to have 3 variations here? Just have a full vec4 uniform and output it. You will likely not get any benefit from micro optimization here.

To improve accuracy you might want to store some samples (say 4 or num_cryptomatte_layers) and then resolve/sort them. This way you would discard less good samples that might in fact accumulate to significant levels after the first few iterations. However I don't know how much it matters in practice.

So if I understand, the current implementation takes the bet that the significant layers will be hit by the first few samples and just accumulate for these captured hashes, discarding any hashes that have not been captured in the initial samples.

About the a potential GPU implementation, I find it difficult to do without gl load/store extension.

Jeroen Bakker (jbakker) marked 3 inline comments as done.Dec 1 2020, 10:41 AM

To improve accuracy you might want to store some samples (say 4 or num_cryptomatte_layers) and then resolve/sort them. This way you would discard less good samples that might in fact accumulate to significant levels after the first few iterations. However I don't know how much it matters in practice.

So if I understand, the current implementation takes the bet that the significant layers will be hit by the first few samples and just accumulate for these captured hashes, discarding any hashes that have not been captured in the initial samples.

EEVEE uses the same approach as Cycles. For accurate mode all the samples are evaluated and during evaluation they are sorted and for inaccurate mode only the first few samples are used and only sorted afterwards. In Cycles the main advantage is that the occludence is already used. In EEVEE we can only do this after the last sample has been calculated. As the samples cryptomatte are stored sequential and all samples weight the same I removed the intermediate sorting as It doesn't change the outcome.

Accuracy could be improved, but I haven't seen any cases that failed. Using the default settings even 6 samples are kept and the user has the ability to increase the number of samples to keep per pixel. The chance that a single pixel has more than 6 hashes for a layer is really low.

About the a potential GPU implementation, I find it difficult to do without gl load/store extension.

I actually didn't look at extensions that could help here. I do believe that those extensions still need the CPU fallback.

I see the alpha issue, cycles doesn't have it so I think it is an error in EEVEE render pass. Will have a look.

source/blender/blenkernel/intern/cryptomatte.c
132

the cryptohash_int field is the ground truth and should be the returning value of this function. The conversion to float is an additional step that the using code can do when the hash needs to be accessed as a color.

source/blender/draw/engines/eevee/eevee_cryptomatte.c
176

Used a comma instead, not sure how to use a semicolon here.

Jeroen Bakker (jbakker) marked an inline comment as done.
  • Code style: formatting
  • Reduce number of shader variations
  • Use BLI_hash_mm3 for hashing. Code was same and already used by the compositor node
  • Revert commenting out code in depsgraph
  • Fixed crash when using hair objects without materials
  • Remove empty samples and background samples from final result
  • Fixed lines between samples (every odd samples was ignored when creating the final render passes)
  • Remove volumetric occlude. Cycles does not have it, and current implementation wasn't complete
Jeroen Bakker (jbakker) edited the summary of this revision. (Show Details)Dec 1 2020, 1:53 PM

I have a crash when using motion blur with steps > 1 :

/home/clement/Blender/build_linux/bin/blender(BLI_system_backtrace+0x35) [0x4d64f9f]
/home/clement/Blender/build_linux/bin/blender(_BLI_assert_print_backtrace+0x16) [0x4c961b0]
/home/clement/Blender/build_linux/bin/blender(EEVEE_cryptomatte_output_init+0x145) [0x29d292f]
/home/clement/Blender/build_linux/bin/blender(EEVEE_renderpasses_output_init+0x2e2) [0x29601a4]
/home/clement/Blender/build_linux/bin/blender() [0x2949c17]
/home/clement/Blender/build_linux/bin/blender(DRW_render_to_image+0x333) [0x292f756]
/home/clement/Blender/build_linux/bin/blender() [0x4ad84c8]
/home/clement/Blender/build_linux/bin/blender(RE_engine_render+0x4e2) [0x4ad8a43]
/home/clement/Blender/build_linux/bin/blender() [0x4ae094b]
/home/clement/Blender/build_linux/bin/blender() [0x4ae0c84]
/home/clement/Blender/build_linux/bin/blender() [0x4ae11e2]
/home/clement/Blender/build_linux/bin/blender() [0x4ae1eeb]
/home/clement/Blender/build_linux/bin/blender(RE_RenderFrame+0x15f) [0x4ae301a]
/home/clement/Blender/build_linux/bin/blender() [0x3fa89dc]
/home/clement/Blender/build_linux/bin/blender() [0x26d09ad]
/home/clement/Blender/build_linux/bin/blender() [0x4d700dc]
/usr/lib/libpthread.so.0(+0x93e9) [0x7f3a15c1e3e9]
/usr/lib/libc.so.6(clone+0x43) [0x7f3a11947293]
BLI_assert failed: source/blender/draw/engines/eevee/eevee_cryptomatte.c:153, EEVEE_cryptomatte_output_init(), at 'g_data->cryptomatte_accum_buffer == ((void *)0)'

Jeroen Bakker (jbakker) edited the summary of this revision. (Show Details)Dec 2 2020, 1:28 PM
  • EEVEE Cryptomatte: Add support for motion blur.
This revision is now accepted and ready to land.Dec 3 2020, 2:54 AM
Jeroen Bakker (jbakker) edited the summary of this revision. (Show Details)Dec 4 2020, 8:27 AM
This revision was automatically updated to reflect the committed changes.
Jeroen Bakker (jbakker) edited the summary of this revision. (Show Details)Dec 4 2020, 9:22 AM

I get warnings on line 306 of eevee_cryptomatte.c where NULL is sent instead of a bool. Should it be false instead maybe?

eevee_cryptomatte.c(306,42): warning C4047: 'function': 'bool' differs in levels of indirection from 'void *'
eevee_cryptomatte.c(306,38): warning C4024: 'eevee_cryptomatte_shading_group_create': different types for formal and actual parameter 5

I get warnings on line 306 of eevee_cryptomatte.c where NULL is sent instead of a bool. Should it be false instead maybe?

eevee_cryptomatte.c(306,42): warning C4047: 'function': 'bool' differs in levels of indirection from 'void *'
eevee_cryptomatte.c(306,38): warning C4024: 'eevee_cryptomatte_shading_group_create': different types for formal and actual parameter 5

D9809: Correct the order of the last two arguments in `eevee_cryptomatte_shading_group_create` 😉