Cryptomatte from Blender 3.x/4.x is not Displayed in Viewer
Closed this issue · 6 comments
Version: Gaffer 1.4.X.X-(linux, windows)
Third-party tools: None
Third-party modules: None
Description
I have EXR with cryptomatte generated from blender 3.6 LTS and also 4.1.1. Whenever I load it and put cryptomatte node, the Viewer
will stay black. However I have another EXR with crypto from blender 2.93 LTS, it will load just fine.
I attached both exr and blend files.
Steps to reproduce
- Download EXR files from here https://1drv.ms/f/s!AipTDeE9i3xFh8401PPddxldrzu5Sw?e=XE6EDa
- drag and drop into Gaffer
- add cryptomatte node to both of the files
- try change layer selection
- notice that Viewer will stay black if using exr generated from blender 3 and above
Debug log
Click to Expand
To me it looks like there are a few different things going on here :
- The EXR file out of Blender has non-standard channel names, with lowercase
.r
,.g
etc where there should be uppercase.R
,.B
etc. - The EXR file out of Blender has everything nested inside a
ViewLayer
layer for some reason. This isn't technically wrong, but it is unusual in my experience. This also means there is no standardRGBA
"beauty" layer. - The Cryptomatte node has a bug when there is no RGBA layer in the input.
If you copy-paste the script below into Gaffer, you should see that things can be made to work if those problems are corrected.
import Gaffer
import GafferImage
import GafferScene
import IECore
import imath
Gaffer.Metadata.registerValue( parent, "serialiser:milestoneVersion", 1, persistent=False )
Gaffer.Metadata.registerValue( parent, "serialiser:majorVersion", 4, persistent=False )
Gaffer.Metadata.registerValue( parent, "serialiser:minorVersion", 3, persistent=False )
Gaffer.Metadata.registerValue( parent, "serialiser:patchVersion", 0, persistent=False )
__children = {}
__children["with_z_b41_0001"] = GafferImage.ImageReader( "with_z_b41_0001" )
parent.addChild( __children["with_z_b41_0001"] )
__children["with_z_b41_0001"].addChild( Gaffer.V2fPlug( "__uiPosition", defaultValue = imath.V2f( 0, 0 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) )
__children["Cryptomatte"] = GafferScene.Cryptomatte( "Cryptomatte" )
parent.addChild( __children["Cryptomatte"] )
__children["Cryptomatte"].addChild( Gaffer.V2fPlug( "__uiPosition", defaultValue = imath.V2f( 0, 0 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) )
__children["Shuffle"] = GafferImage.Shuffle( "Shuffle" )
parent.addChild( __children["Shuffle"] )
__children["Shuffle"]["shuffles"].addChild( Gaffer.ShufflePlug( "shuffle0", flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) )
__children["Shuffle"].addChild( Gaffer.V2fPlug( "__uiPosition", defaultValue = imath.V2f( 0, 0 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) )
__children["Expression"] = Gaffer.Expression( "Expression" )
parent.addChild( __children["Expression"] )
__children["Expression"]["__out"].addChild( Gaffer.StringPlug( "p0", direction = Gaffer.Plug.Direction.Out, defaultValue = '', flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, substitutions = IECore.StringAlgo.Substitutions.NoSubstitutions ) )
__children["Expression"].addChild( Gaffer.V2fPlug( "__uiPosition", defaultValue = imath.V2f( 0, 0 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) )
__children["Constant"] = GafferImage.Constant( "Constant" )
parent.addChild( __children["Constant"] )
__children["Constant"].addChild( Gaffer.V2fPlug( "__uiPosition", defaultValue = imath.V2f( 0, 0 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) )
__children["CopyChannels"] = GafferImage.CopyChannels( "CopyChannels" )
parent.addChild( __children["CopyChannels"] )
__children["CopyChannels"]["in"].addChild( GafferImage.ImagePlug( "in2", flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) )
__children["CopyChannels"].addChild( Gaffer.V2fPlug( "__uiPosition", defaultValue = imath.V2f( 0, 0 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) )
__children["with_z_b41_0001"]["fileName"].setValue( '/home/john/Downloads/cryptomatte/with_z_b41_0001.exr' )
__children["with_z_b41_0001"]["__uiPosition"].setValue( imath.V2f( 18.1511688, 33.2099152 ) )
Gaffer.Metadata.registerValue( __children["Cryptomatte"], 'annotation:user:text', 'With all those fixes applied, the Cryptomatte node can recognise the input and generate a matte appropriately.' )
Gaffer.Metadata.registerValue( __children["Cryptomatte"], 'annotation:user:color', imath.Color3f( 0.150000006, 0.25999999, 0.25999999 ) )
__children["Cryptomatte"]["in"].setInput( __children["CopyChannels"]["out"] )
__children["Cryptomatte"]["layer"].setValue( 'ViewLayer.CryptoObject' )
__children["Cryptomatte"]["matteNames"].setValue( IECore.StringVectorData( [ '/Cube', '' ] ) )
__children["Cryptomatte"]["__uiPosition"].setValue( imath.V2f( 21.1511688, 2.11772776 ) )
Gaffer.Metadata.registerValue( __children["Shuffle"], 'annotation:user:text', 'The EXR from Blender is malformed, with channels using lower-case names `r`, `g`, `b` etc instead of the expected upper-case names `R`, `G`, `B`. The Shuffle node fixes that.' )
Gaffer.Metadata.registerValue( __children["Shuffle"], 'annotation:user:color', imath.Color3f( 0.150000006, 0.25999999, 0.25999999 ) )
__children["Shuffle"]["in"].setInput( __children["with_z_b41_0001"]["out"] )
__children["Shuffle"]["shuffles"]["shuffle0"]["source"].setValue( '*.[rgba]' )
__children["Shuffle"]["shuffles"]["shuffle0"]["deleteSource"].setValue( True )
Gaffer.Metadata.registerValue( __children["Shuffle"]["shuffles"]["shuffle0"]["source"], 'channelPlugValueWidget:isCustom', True )
__children["Shuffle"]["shuffles"]["shuffle0"]["destination"].setInput( __children["Expression"]["__out"]["p0"] )
Gaffer.Metadata.registerValue( __children["Shuffle"]["shuffles"]["shuffle0"]["destination"], 'channelPlugValueWidget:isCustom', True )
__children["Shuffle"]["__uiPosition"].setValue( imath.V2f( 18.1511688, 25.0458527 ) )
__children["Expression"]["__uiPosition"].setValue( imath.V2f( 7.6503315, 25.0460129 ) )
__children["Constant"]["__uiPosition"].setValue( imath.V2f( 36.8500023, 18.4458523 ) )
Gaffer.Metadata.registerValue( __children["CopyChannels"], 'annotation:user:text', 'The Cryptomatte node seems to have a bug triggered by not having RGBA channels in the input. Copy in some channels to keep it happy.' )
Gaffer.Metadata.registerValue( __children["CopyChannels"], 'annotation:user:color', imath.Color3f( 0.150000006, 0.25999999, 0.25999999 ) )
__children["CopyChannels"]["in"][0].setInput( __children["Shuffle"]["out"] )
__children["CopyChannels"]["in"][1].setInput( __children["Constant"]["out"] )
__children["CopyChannels"]["channels"].setValue( '*' )
__children["CopyChannels"]["__uiPosition"].setValue( imath.V2f( 21.1511688, 10.2817898 ) )
__children["Expression"]["__engine"].setValue( 'python' )
__children["Expression"]["__expression"].setValue( 'source = context.get( "source", "" )\ndest = source.replace( ".r", ".R" )\ndest = dest.replace( ".g", ".G" )\ndest = dest.replace( ".b", ".B" )\ndest = dest.replace( ".a", ".A" )\n\nparent["__out"]["p0"] = dest' )
del __children
I think it's probably worth us tweaking the ImageReader so that it can conform the non-standard lowercase channels automatically - we already have loads of heuristics for dealing with dodgy EXRs from other sources. And we should fix the Cryptomatte problem too. But ideally you'd be able to get the output from Blender formatted in a more standard way as well...
The EXR file out of Blender has non-standard channel names, with lowercase .r, .g etc where there should be uppercase .R, .B etc.
Actually, I see now that the Cryptomatte specification says lowercase, but that conflicts with the EXR specification, which says uppercase... 🤷
Thank you @johnhaddon ,
Anyway I tried to run the python script but it complained about parent
not defined...so I set parent = root
and it works, but not sure if it's the correct way .
Also I tried using shuffle and copied your python expression, but it's not working as well.
I tried using the plugs and it works if manually setup.
Anyway I tried to run the python script but it complained about parent not defined
If you paste it directly into the Graph Editor it should work.
Thank you @johnhaddon