Skip to content

Finalize ACES 2 FixedFunctions and remove warnings #2275

Description

@doug-walker

When ACES 2 was implemented, there was some uncertainty in how to decompose the overall Output Transforms into FixedFunctions, and so the YAML reader and writer issue warnings when any of these are used:

FIXED_FUNCTION_ACES_OUTPUT_TRANSFORM_20
FIXED_FUNCTION_ACES_RGB_TO_JMH_20
FIXED_FUNCTION_ACES_TONESCALE_COMPRESS_20
FIXED_FUNCTION_ACES_GAMUT_COMPRESS_20

At this point, we should try to finalize what the fixed functions are and remove the warnings.

I like having a function to convert to JMh, but there are two things I find inconvenient about the current one:

  1. The results are in the hundreds (e.g., J goes up above 800, h goes up to 360) and this makes it inconvenient to use in other tools that would prefer more of a 0 to roughly 1 normalization.
  2. The more conventional channel layout is for hue to be first and lightness to be last. For example, the existing conversions to HSV and HSY use that channel layout.

Currently, in order to use the existing RGB_TO_JMH with the GradingHueCurveTransform, I need to put a matrix on either side to rescale and reorder the channels. My proposal would be to create a new function that is ordered hMJ and has h divided by 360 and J divided by roughly 500.

Similarly, my only concern about the others is whether the inputs/outputs are normalized in a way that is convenient.

As we are currently developing LMTs that may work in JMh, it would be helpful if the optimizer was able to decompose an ACES_OUTPUT_TRANFORM into one or more fixed functions that expects JMh (from an LMT) as input so that a pair of RGB_TO_JMH and JMH_to_RGB could be dropped. Currently, is it possible to replace an ACES_OUTPUT_TRANSFORM with RGB_to_JMH + TONESCALE_COMPRESS + GAMUT_COMPRESS + JMH_to_RGB?

Tagging @KevinJW and @remia for input.

Note: When implementing this, search Config_tests.cpp for "experimental" and clean up accordingly. Likewise remove "experimental" from OpenColorTypes.h fixed function descriptions.

Activity

  1. added
    Needs DiscussionNeeds discussion before implmentation, which could result in changes, or a decision not to proceed.
    on Mar 19, 2026
  2. added this to the OCIO 2.6.0 milestone on Mar 19, 2026
  3. remia commented on Mar 31, 2026

    @remia
    Collaborator

    As we are currently developing LMTs that may work in JMh, it would be helpful if the optimizer was able to decompose an ACES_OUTPUT_TRANFORM into one or more fixed functions that expects JMh (from an LMT) as input so that a pair of RGB_TO_JMH and JMH_to_RGB could be dropped. Currently, is it possible to replace an ACES_OUTPUT_TRANSFORM with RGB_to_JMH + TONESCALE_COMPRESS + GAMUT_COMPRESS + JMH_to_RGB?

    Yeah it should already be possible, see below the 2 equivalent ways for example:

    - !<FixedFunctionTransform> {style: ACES2_OutputTransform, params: [1000, 0.680, 0.320, 0.265, 0.690, 0.150, 0.060, 0.3127, 0.3290]}
    
    - !<FixedFunctionTransform> {style: ACES2_RGB_TO_JMh, params: [0.7347, 0.2653, 0.0000, 1.0000, 0.0001, -0.0770, 0.32168, 0.33767]}
    - !<FixedFunctionTransform> {style: ACES2_TonescaleCompress, params: [1000]}
    - !<FixedFunctionTransform> {style: ACES2_GamutCompress, params: [1000, 0.680, 0.320, 0.265, 0.690, 0.150, 0.060, 0.3127, 0.3290]}
    - !<FixedFunctionTransform> {style: ACES2_RGB_TO_JMh, params: [0.680, 0.320, 0.265, 0.690, 0.150, 0.060, 0.3127, 0.3290], direction: inverse}
    

    The issue with the second approach is the Reach M texture gets duplicated on the GPU as it is used by both TonescaleCompress and GamutCompress stages and OCIO doesn't currently deduplicate textures (#1597). There are also some duplicated hue wrapping code. I measured around 5% slowdown in NSight with the second option on the GPU which is not too bad, haven't checked on CPU. But I agree it would probably be good to remove ACES2_OutputTransform FixedOp for better optimization opportunities and code simplicity.

  4. moved this from Next to Now in OpenColorIO Roadmapon Aug 30, 2026
  5. doug-walker commented on Aug 30, 2026

    @doug-walker
    CollaboratorAuthor

    At this point, I have more experience with using JMh in DCCs and want to update my proposal on scaling. For J, I propose a 1/100 scaling since J=100 corresponds to diffuse white. Since J is perceptually-encoded but scene-referred, it goes well above 100. Scaling to 100 gives a good sense of what's in the image. Anything higher starts to look too dark when viewed as if it were a video signal. For M, the raw values go above 1000, but normalizing by 1/200 gives a good sense of what's in an image. Using 1/100 gives something that is too dark to interpret for most scenes. For h, 1/360 is the clear choice.

    Here's my proposal for what will go in OCIO 2.6:

    • Add a new pair (fwd/inv) of FIXED_FUNCTION_ACES_RGB_TO_HMJ_20 transforms that produce h/360, M/200, J/100. We will use this for the new Look Transform in the built-in configs.
    • For now, leave the existing FixedFunctions, along with their warnings logged when reading as Yaml. At some later point, these could be deprecated. In the ACES configs, the ViewTransforms use BuiltinTransforms rather than calling the FixedFunctions directly, so this is why there is no warning when loading those configs. Note that there has never been a warning when loading these from CTF. It would be interesting to know if there has been any substantial use of these in that form.

    For 2.6.1, I would like to explore the optimization described above (breaking up the monolithic output transform) to provide better performance for LMTs that use JMh. To be decided: whether to implement this in the BuiltinTransform, or only in the optimizer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Needs DiscussionNeeds discussion before implmentation, which could result in changes, or a decision not to proceed.

    Type

    No type

    Projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions