There are a couple of options to ensure textures are processed in the correct color space.
The best option is to export your textures from your painting DCC as ACEScg and import them into Unreal Engine.
However, if you have existing textures in sRGB, you can convert them directly on the Texture UAsset by using the "Color Space" setting found in the Advanced > Source Color Settings section of the Texture Details panel of that texture.
In addition, above the "Color Space" option, there is the "Encoding Override" option which exposes even more options. In most cases, you should not need to change the Encoding Override when dealing with most ACES working color spaces. When set, the texture is re-encoded into the proper color space for use in Unreal.
A couple of new parameters have been added to textures in the Texture > Advanced > Source Color Settings section that allow you to control both the color space and override the encoding of individual textures:
-
Encoding Override - Source encoding of the texture, exposing more options other than just sRGB. This corresponds to the transfer curve of the source (e.g. sRGB, Gamma 2.2, Gamma 2.4, a log curve)
-
Color Space - Source color space of the texture. This corresponds to the gamut/primaries of the source (e.g. sRGB/Rec.709, Rec.2020, ARRI Wide Gamut)
A common scenario is changing the project wide Working Color Space from sRGB/Rec.709 (engine default) to ACEScg. If by chance some assets have been already published in the project prior to the change, you can now update the textures that were originally painted in sRGB right in the engine.
In the case of sRGB/Rec.709 to ACEScg, you would change the Color Space in the texture's Source Color Settings to "sRGB/Rec.709" to flag to the engine that the texture was originally painted in sRGB. The engine will do the work of converting it to properly view in the ACEScg working color space.
How Unreal interprets imported textures (and how it gets it wrong)
When you drag a texture into Unreal, the engine guesses how it is encoded based on the file type. For an 8-bit file such as a PNG it will simply assume the texture is sRGB and tick the sRGB checkbox on the texture asset. There is generally no metadata in the file telling the engine what it actually is, so this assumption is sometimes wrong:
-
A Rec.709-encoded image (e.g. graphics prepared for broadcast) is not sRGB - it will be linearized with the wrong assumptions and typically end up looking too bright
-
A log-encoded image (e.g. a TIFF exported from a log camera workflow) is not recognized at all - it will be treated as sRGB and end up clipped and washed out
To color manage such a texture correctly:
-
Untick sRGB on the texture asset
-
This will produce an error in any material using the texture: the default texture sampler type (Color) only supports 8-bit sRGB textures. Open the material and change the sampler type of the texture node to Linear Color
-
Under Texture > Advanced > Source Color Settings, set the Encoding Override (transfer curve) and Color Space (gamut) to match how the texture was actually encoded
Textures in linear HDR formats (e.g. EXR) are recognized correctly on import - sRGB stays off, and you only need to verify the Color Space (e.g. ACES AP0/AP1).
If a customer is struggling to get the colors of an imported texture (e.g. a logo) to look correct, the texture's sRGB flag and Source Color Settings are the first place to check.
Unreal also exposes its built-in OCIO tools for converting colors in Blueprints: Converting colors in Unreal Engine Blueprints.
We have not yet verified this workflow in Pixotope, so be aware that it is untested by us, including any performance implications.
Importing ACEScg (linear) Textures
It is common to work in an ACEScg working color space in an engine - which is linear. When importing ACEScg textures (or any linear textures), use “HDR Compressed (RGB, BC6H, DX11) Compression Settings”. This will preserve the linear color lookup and full bit depth of the texture.
Compression settings and color fidelity
-
Never use 8-bit or 16-bit integer compression settings for linear/HDR textures - integer formats clip all values above 1.0, destroying HDR information. Only floating point formats preserve values above 1.0
-
HDR Compressed (BC6H) is a lossy block compression format and it is unsigned, meaning negative channel values are clipped. Color shifts have been observed with compressed formats in some engine versions, particularly with highly saturated/wide gamut content
-
When exact color fidelity matters (logos, brand colors, calibration content), use the uncompressed HDR (RGBA32F) setting. It is the safest choice, at the cost of significantly more texture memory
-
When in doubt, test: compare the texture rendered with the compressed and uncompressed setting