@pawel-fin, thank you for submitting the test files.
After going through the examples, there were a few things that I thought would be useful to share with the community. Understandings about how OCIO is handled in H20.0.
I hope this helps clarify some of the behaviours in H20.0.
USD/MaterialXUSD stores the color space information for MaterialX nodes as metadata on the parameter. The Hydra interface (used by Karma/husk) does not currently pass this metadata through to the renderer. So, the color space metadata doesn't make it through from VOPs to Karma.
If a renderer loads the USD directly (without Hydra), it's able to access this metadata, so behaviour might be different. Later versions of USD will have this fixed.
OpenEXR Color SpaceTo determine the source color space, Karma (and VEX) use the following rules:
a) If the color space is explicitly specified, use it (this doesn't work with USD/MaterialX, see above)
b) Match using the OCIO file rules
c) If there are no file rules, use metadata in the image
d) If there's no metadata, fall back to a default
If we get to the last stage, the default for 8-bit images is to assume the color space is sRGB. For OpenEXR, Karma assumes they are Linear Rec.709. This is according to the OpenEXR spec for files missing the chromaticities attribute (
https://openexr.com/en/latest/TechnicalIntroduction.html)
Note that OpenEXR suggests the chromaticities metadata should be used to determine the color space. However, neither OpenImageIO, OpenColorIO or the Houdini core libraries are able to determine an OCIO color space from the chromaticities.
Houdini will use the
oiio:ColorSpace
metadata. The example .exr files you included both had the
oiio:ColorSpace
set to
Linear
. Since there are multiple linear color spaces, we've found making the assumption that "linear" maps to "scene_linear" can often lead to bad results, so we don't count "linear" as being a meaningful value for
oiio:ColorSpace
.
H19.5H19.5 assumed scene_linear was Linear Rec.709 in all cases. It ignored the OCIO file. For the most part, H19.5 also ignored the OCIO config file entirely when interpreting color spaces. For 8 bit files, there was a built-in conversion from sRGB to Linear Rec.709. OpenEXR files were read as "raw", so no color space conversion happened.
As I pointed out, in your example, H19.5 rendered identical images, regardless of the OCIO config file. That's because H19.5 ignored OCIO.
H20.0As mentioned above, H20.0 obeys the OCIO scene_linear ccolor space and uses the OCIO rules to perform color space computations.
None of the textures in your example were optimized (tiled and mip-mapped). In H20, Karma XPU automatically creates an optimized texture for rendering (see the HOUDINI_TEXTURE_DISK_CACHE variable). There was a bug with this process when scene_linear was not set to Linear Rec.709. This was fixed in H20.0.633 (March 1, 2024).
It's highly recommended that you use optimized textures since they consume less memory, have better filtering and are in general more efficient. Look at HOUDINI_TEXTURE_DISK_CACHE for options to automate this process.
Your Test CasesFor those readers without access, there were three textures provided:
- textureA = JPG image
- textureB = OpenEXR in ACEScg color space
- textureC = OpenEXR in Linear Rec.709 color space
As mentioned above, none of the textures had color space metadata and were not tiled/mip-mapped.
Default OCIO ConfigScene Linear = Linear Rec.709
textureA: source space srgb_tx -> target space lin_rec_709
textureB: lin_rec_709 -> lin_rec_709
textureC: lin_rec_709 -> lin_rec_709
This matches H19.5 exactly. textureB is interpreted as being in Linear Rec.709 color space, so comes through unmodified.
RedShift OCIO ConfigScene Linear = ACES - ACEScg
textureA: Input - Generic - sRGB - Texture -> ACES - ACEScg
textureB: Linear Rec.709 -> ACES - ACEScg
textureC: Linear Rec.709 -> ACES - ACEScg
The reason textureB and textureC are assumed to be in Linear Rec.709 is:
- There are no file rules in the OCIO config
- There's no meaningful color space metadata in the .exr file
Since the output image stores its colors in ACEScg space, textureC gets converted from Linear Rec.709 to ACEScg and appears correct. textureB also gets converted and has the ACEScg colors transformed again, so it appears incorrect.
There seems to be a bug in OpenColorIO handling the FileTransform rule for the "Input - Generic - SRGB Texture" to "ACEScg". It seems the gamma is not removed. This may be because I was missing a LUT in the test.
Houdini Config - ACEScg Scene Linear = ACEScg
textureA: srgb_tx -> ACEScg
textureB: ACEScg -> ACEScg
textureC: ACEScg -> ACEScg
Before the fix for HOUDINI_TEXTURE_DISK_CACHE, XPU would generate incorrect images. This has been fixed.
Since scene_linear matches the file rules for .exr files, the .exr texture data is unmodified and the output image is written in ACEScg color space. The
oiio:ColorSpace
metadata reflects this.
Houdini Config - ACEScg - No file rules Scene Linear = ACEScg
textureA: srgb_tx -> ACEScg
textureB: Linear Rec.709 -> ACEScg
textureC: Linear Rec.709 -> ACEScg
Without OCIO file rules, this config file behaves similarly to the RedShift config file. Karma assumes the .exr files are in Linear Rec.709 color space.
Optimized TexturesYou can use imaketx or hoiiotool (or other utilities) to convert images to optimized format.
If you need to set the oiio:ColorSpace attribute on an .exr file explicitly, you can do this using
hoiiotool foo.exr --attrib oiio:ColorSpace "ACES - ACEScg" -otex fum.exr
imaketx will store color space metadata automatically, but if you have OCIO file rules, they take precedence.
Note: With HOUDINI_TEXTURE_DISK_CACHE, we considered using .exr files on output, but .rat files (like .tif/.tx files) support 8-bit and 32-bit data.