Loading...
Searching...
No Matches
Programmer's Guide to Color in OpenUSD

Overview

This guide aims to provide developers with a solid foundation in color science concepts and practical implementation details on the treatment of color within OpenUSD both in scene data and via OpenUSD's interfaces. This guide will navigate the complexities of color and is of interest to developers integrating OpenUSD into an existing renderer, building tools for artists, or creating content procedurally.

Readers should familiarize themselves with fundamental color science concepts and terminology by reading the Color User's Guide in addition to this document.

OpenUSD Color Management Architecture

OpenUSD provides a rigorous and well defined system for managing scene-referred color spaces through its API schemas. By "scene-referred" we mean specifying the source color space for any authored color attribute or asset path identifying a texture or other external color-containing asset. The primary applied schemas are:

  1. UsdColorSpaceAPI: Allows specifying color space information on prims.
  2. UsdColorSpaceDefinitionAPI: A multiple-apply schema that enables definition of custom color spaces.

Key Concepts in USD Color Management

Color Space Inheritance

In OpenUSD, color spaces can be specified at any level in the scene hierarchy and are inherited by child prims. This hierarchical approach allows for:

  • Setting a global color space at the root.
  • Providing a color space for a subgraph of the scene.
  • Specifying a color space for attributes on individual prims.
  • Authoring the color on individual attributes.

Color Space Resolution

When determining the color space for a value, OpenUSD follows a specific resolution order:

  1. Check if the attribute has an explicitly assigned color space.
  2. Check if the attribute's prim has UsdColorSpaceAPI applied.
  3. Search up the hierarchy until a prim with UsdColorSpaceAPI is found.
  4. If no color space is found, an empty token is returned. If no color space is found, an empty token is returned. In this case, the color space must be assumed to be Linear Rec.709.

Programming With UsdColorSpaceAPI

Applying Color Space Information

The colorSpaceName attribute is a uniform value applied to a prim. To apply color space information to a prim:

// Get a prim
UsdPrim prim = stage->GetPrimAtPath(SdfPath("/Root/Geom"));
// Apply the color space API
// Set the color space
VtValue(GfColorSpaceNames->LinearRec709));
A path value used to locate objects in layers or scenegraphs.
Definition: path.h:274
UsdColorSpaceAPI is an API schema that introduces a colorSpace property for authoring scene referred ...
Definition: colorSpaceAPI.h:94
USD_API UsdAttribute CreateColorSpaceNameAttr(VtValue const &defaultValue=VtValue(), bool writeSparsely=false) const
See GetColorSpaceNameAttr(), and also Create vs Get Property Methods for when to use Get vs Create.
static USD_API UsdColorSpaceAPI Apply(const UsdPrim &prim)
Applies this single-apply API schema to the given prim.
UsdPrim is the sole persistent scenegraph object on a UsdStage, and is the embodiment of a "Prim" as ...
Definition: prim.h:117
USD_API UsdPrim GetPrimAtPath(const SdfPath &path) const
Returns the prim at path on the same stage as this prim.
Provides a container which may hold any type, and provides introspection and iteration over array typ...
Definition: value.h:90

Querying Color Space Information

To determine the color space for an attribute:

// Get an attribute
UsdAttribute attr = prim.GetAttribute(TfToken("diffuseColor"));
// Compute its color space
// Convert to a GfColorSpace for transformation operations
Basic type: ColorSpace.
Definition: colorSpace.h:115
Token for efficient comparison, assignment, and hashing of known strings.
Definition: token.h:71
Scenegraph object for authoring and retrieving numeric, string, and array valued data,...
Definition: attribute.h:183
static USD_API GfColorSpace ComputeColorSpace(const UsdAttribute &attribute, ColorSpaceCache *cache=nullptr)
Computes the color space for the given attribute on this prim, using the same algorithm as ComputeCol...
static USD_API TfToken ComputeColorSpaceName(const UsdAttribute &attribute, ColorSpaceCache *cache=nullptr)
Computes the color space name for the given attribute.
USD_API UsdAttribute GetAttribute(const TfToken &attrName) const
Return a UsdAttribute with the name attrName.

Performance Optimization With Caching

For performance-critical applications, OpenUSD provides a caching mechanism to accelerate large numbers of look ups:

// Create a cache
// Use the cache when computing color spaces
TfToken colorSpaceName = UsdColorSpaceAPI::ComputeColorSpaceName(attr, &cache);
This is a simple example of a color space cache implementation.

Defining Custom Color Spaces

OpenUSD allows defining custom color spaces using the UsdColorSpaceDefinitionAPI:

// Get a prim to which we'll attach the color space definition
UsdPrim prim = stage->GetPrimAtPath(SdfPath("/Root"));
// Apply a color space definition named "customSpace"
TfToken definitionName("customSpace");
UsdColorSpaceDefinitionAPI::Apply(prim, definitionName);
// Set the name attribute
definition.CreateNameAttr(VtValue(definitionName));
// Define the color space parameters
GfVec2f redChroma(0.64, 0.33);
GfVec2f greenChroma(0.30, 0.60);
GfVec2f blueChroma(0.15, 0.06);
GfVec2f whitePoint(0.3127, 0.3290); // D65
float gamma = 1.0; // Linear
float linearBias = 0.0;
redChroma, greenChroma, blueChroma, whitePoint, gamma, linearBias);
Basic type for a vector of 2 float components.
Definition: vec2f.h:46
UsdColorSpaceDefinitionAPI is an API schema for defining a custom color space.
USD_API UsdAttribute CreateNameAttr(VtValue const &defaultValue=VtValue(), bool writeSparsely=false) const
See GetNameAttr(), and also Create vs Get Property Methods for when to use Get vs Create.
USD_API void CreateColorSpaceAttrsWithChroma(const GfVec2f &redChroma, const GfVec2f &greenChroma, const GfVec2f &blueChroma, const GfVec2f &whitePoint, float gamma, float linearBias)
Creates the color space attributes with the given values.
static USD_API UsdColorSpaceDefinitionAPI Apply(const UsdPrim &prim, const TfToken &name)
Applies this multiple-apply API schema to the given prim along with the given instance name,...

Alternatively, you can define a color space from an RGB to XYZ transformation matrix:

GfMatrix3f rgbToXYZ = /* RGB to XYZ transformation matrix */;
float gamma = 1.0;
float linearBias = 0.0;
definition.CreateColorSpaceAttrsWithMatrix(rgbToXYZ, gamma, linearBias);
Stores a 3x3 matrix of float elements.
Definition: matrix3f.h:65
USD_API void CreateColorSpaceAttrsWithMatrix(const GfMatrix3f &rgbToXYZ, float gamma, float linearBias)
Create the color space attributes by deriving the color space from the given RGB to XYZ matrix and li...

Color Space Transformations

To convert colors between spaces, use the GfColorSpace class:

// Get color spaces
GfColorSpace targetSpace = GfColorSpace(GfColorSpaceNames->LinearAP1);
// Convert a single color
GfVec3f srcColor(1.0f, 0.5f, 0.0f);
GfVec3f targetColor = srcSpace.Convert(targetSpace, srcColor);
// Convert an array of colors
std::vector<GfVec3f> colorArray = /* Array of colors */;
srcSpace.ConvertRGBSpan(targetSpace, colorArray.data(), colorArray.size());
GF_API void ConvertRGBSpan(const GfColorSpace &srcColorSpace, TfSpan< float > rgb) const
Convert in place a packed array of RGB values from one color space to "this" one.
GF_API GfColor Convert(const GfColorSpace &srcColorSpace, const GfVec3f &rgb) const
Convert a rgb triplet in a certain color space to "this" color space.
Basic type for a vector of 3 float components.
Definition: vec3f.h:46

Best Practices for USD Color Management

Establish a Clear Color Management Policy

Define which color spaces your pipeline uses for:

  • Texture inputs
  • Material parameters
  • Render outputs

Be Explicit About Color Spaces

Specify color spaces explicitly rather than relying on defaults.

A general best practice is to first ensure that the stage's root prim has the UsdColorSpaceAPI schema applied, and set the prim's color space to the studio/pipeline default (e.g. LinearRec2020).

Then, for textures or other color assets created outside the studio/pipeline using a different source color space, make sure to explicitly set the appropriate color space.

// Explicitly set the color space for attribute
UsdAttribute attr = prim.GetAttribute(TfToken("inputs:file"));
attr.SetColorSpace(GfColorSpaceNames->SRGBRec709);
USD_API void SetColorSpace(const TfToken &colorSpace) const
Sets the color space of the attribute to colorSpace.

Perform Computations in Linear Space

Ensure all lighting calculations, blending, and compositing happen in linear color space. In most scenarios, the color space to be used for these computations would be specified in RenderSettings.renderingColorSpace.

// Convert to linear if needed before computation
GfColorSpace linearSpace = GfColorSpace(GfColorSpaceNames->LinearRec2020);
GfVec3f linearColor = srcSpace.Convert(linearSpace, originalColor);
// Perform computation...
GfVec3f result = /* computation */;
// Convert back if needed
GfVec3f displayColor = linearSpace.Convert(displaySpace, result);

Cache Color Space Lookups

For render loops or other performance-critical sections:

// Later in your render loop:
for (const auto& attr : attributes) {
// Use colorSpace...
}

Clear Cache When Scene Changes

If your application caches color space information, ensure the cache is invalidated when:

  • Stage contents change
  • Layer stacks are modified