3ds Max C++ API Reference
Loading...
Searching...
No Matches
Underlying Color Sampling System

In a 3ds Max scene, color values are defined in the linear rendering color space and stored as 32-bit floating-point values per channel. More...

Classes

struct  IColorPickerMgr::UnderlyingColorData
 Structure used to exchange underlying color data between the color picker and the window under the mouse cursor when the user is using the eyedropper tool to sample underlying scene colors. More...
class  QMaxSampleUnderlyingColorEvent
 Qt event used by the color picker system to request sampling of an underlying color. More...

Functions

static CoreExport UINT GetSampleUnderlyingColorMsgID ()
 Returns the message ID used to sample underlying colors.

Variables

static constexpr const wchar_t * SAMPLE_UNDERLYING_COLOR_MESSAGE_STR
 Name of the system-wide message used to sample the underlying color at a given screen position.

Detailed Description

In a 3ds Max scene, color values are defined in the linear rendering color space and stored as 32-bit floating-point values per channel.

All rendering computations occur in this linear space. In the legacy Gamma work flow, this space is "linear-sRGB". In OCIO modes, it may be any linear color space, with "ACEScg" being the default.

Rendering results produced in this linear, scene-referred space are not suitable for direct viewing and therefore must be transformed into a display-referred color space, which is typically non-linearly encoded. In the legacy Gamma mode this is sRGB (with 2.2 gamma encoding), and in OCIO modes the user may select different displays and view transforms available in the active OCIO configuration. These display-referred colors are usually quantized to 8-bit integers before being handed to the OS and display hardware.

When users interact with the color picker, they may enter values either in the linear, scene-referred space (left column) or in the non-linear, display-referred space (right column). Regardless of the input method, the color picker ultimately converts values into the scene-linear space, which is what it reports back to the scene element. In the legacy Gamma work flow this conversion is a simple de-gamma operation, while in OCIO modes it may require more complex transforms potentially involving 3D LUTs.

This creates a challenge for the color picker's sampling (eyedropper) tool: the eyedropper only has access to the 8-bit, clamped, display-referred colors obtained from the screen. Applying the inverse display/view transform to these quantized and clamped values produces low-fidelity scene-referred colors, making it impossible to pick colors that lie outside the display gamut or dynamic range, even when such values are fully valid in the rendering color space. Moreover, 256-level quantization further reduces the color fidelity and stability.

To overcome this limitation, starting with 3ds Max 2027 the color picker provides a system that allows UI elements to supply high-fidelity, unclamped colors directly in the scene-referred rendering space. The color picker sends either a QEvent to a Qt widget or a Windows message to the native window under the mouse cursor to query whether it can provide the underlying scene-referred color at the given position.

UI elements that support this mechanism should handle the message and return IColorPickerMgr::UnderlyingColorData::OK. Elements that do not support it may ignore the message, in which case the color picker will fall back to applying the inverse display/view transform.

When the user clicks to sample a color, the same message is sent again, this time with a valid pointer to a structure specifying the requested color space and the buffer where color values should be written. Ideally, the UI element should provide the color in the requested color space (normally the rendering space). If it can only supply the color in a different color space, it may do so by filling the values and setting the sColorSpace field appropriately. The color picker will attempt to convert the supplied color into the rendering space if possible.

Qt widgets should listen for the QEvent with the type returned by QMaxSampleUnderlyingColorEvent::type() and fill in the public data members of the QMaxSampleUnderlyingColorEvent class accordingly.

For native Windows UI, plugins can obtain the message ID by calling IColorPickerMgr::GetSampleUnderlyingColorMsgID(). External processes may obtain the registered ID using:

RegisterWindowMessage(SAMPLE_UNDERLYING_COLOR_MESSAGE_STR);
static constexpr const wchar_t * SAMPLE_UNDERLYING_COLOR_MESSAGE_STR
Name of the system-wide message used to sample the underlying color at a given screen position.
Definition ColorPicker.h:512

Windows Message Parameters:

  • WPARAM: Mouse position in client coordinates (packed in LOWORD/HIWORD).
  • LPARAM: nullptr (capability probe), or a pointer to an UnderlyingColorData structure.

Behavior:

  • If LPARAM == nullptr:
    • This is a capability probe. Return Result::OK if the pixel at the given mouse position can provide an underlying color, otherwise return Result::UNSUPPORTED.
  • If LPARAM != nullptr:
    • LPARAM points to an UnderlyingColorData instance.
    • Fill its 'rgba' array with color values.
    • If you can supply the color in the requested color space (sColorSpace), set result = OK.
    • If you can supply the color only in a different color space, fill 'rgba' accordingly, set sColorSpace to that color space's name, and return OTHER_COLOR_SPACE. 3ds Max will attempt to convert it to the rendering space; if conversion fails, it will fall back to using display colors.
    • If unsupported, leave data unchanged and return UNSUPPORTED.

Notes:

  • r,g,b,a fields must always contain values consistent with the return value.
See also
Color Management Overview
QMaxSampleUnderlyingColorEvent
IColorPickerMgr::GetSampleUnderlyingColorMsgID()
IColorPickerMgr::UnderlyingColorData

Function Documentation

◆ GetSampleUnderlyingColorMsgID()

CoreExport UINT GetSampleUnderlyingColorMsgID ( )
static

Returns the message ID used to sample underlying colors.

This is the value RegisterWindowMessage(SAMPLE_UNDERLYING_COLOR_MESSAGE_STR) would return.

Returns
The message ID used to sample underlying colors.
See also
Underlying Color Sampling System
IColorPickerMgr::SAMPLE_UNDERLYING_COLOR_MESSAGE_STR
IColorPickerMgr::UnderlyingColorData

Variable Documentation

◆ SAMPLE_UNDERLYING_COLOR_MESSAGE_STR

const wchar_t* SAMPLE_UNDERLYING_COLOR_MESSAGE_STR
inlinestaticconstexpr
Initial value:
=
L"WM_ADSK_SAMPLE_UNDERLYING_COLOR"

Name of the system-wide message used to sample the underlying color at a given screen position.

This message is sent by the color picker when the user is using the eyedropper tool to sample underlying scene colors. The window that supports this message will return the color at the specified screen position.

This name is needed only for the external processes that want to support 3ds Max's underlying color sampling system. In that case they can call RegisterWindowMessage(SAMPLE_UNDERLYING_COLOR_MESSAGE_STR) to get the message ID.

3ds Max plugins don't need to use this string, they can simply call IColorPickerMgr::GetSampleUnderlyingColorMsgID() to get the message ID that they need to respond to.

See also
Underlying Color Sampling System
IColorPickerMgr::GetSampleUnderlyingColorMsgID()
IColorPickerMgr::UnderlyingColorData