#7557·Open3D

Filament upgrade ignores ColorGrading tone-mapper selection

Author: mstoelzleCreated Sep 9, 2026Updated Sep 9, 2026

Checklist

  • Tested the official Linux development wheel first.
  • Ran a successful Linux RGB comparison at the exact reported revision.
  • Repeated baseline and isolated-control captures in fresh processes.

Environment and revisions

Ubuntu 26.04.1 LTS, x86_64
Linux 7.0.0-31-generic
Python 3.12.13
Open3D 1a9eb990f9a20936c30c428568c602bdef760744
Filament v1.54.0, tag commit c1a3450d9c0a64c329a17bff4f3a7f68a2474214
Mesa 26.0.8 / EGL 1.7.0
DISPLAY unset; EGL_PLATFORM=surfaceless; LIBGL_ALWAYS_SOFTWARE=true

The official unmodified Linux development wheel open3d-0.19.0+1a9eb99-cp312-cp312-manylinux_2_35_x86_64.whl, SHA-256 e3368125a937fb4438276612ee46b35d56cbf4a944e4c899a2e83bacb7ac5303, currently contains no open3d/resources/ entries. It fails before graphics initialization with Could not find resource file .../open3d//resources (exit status 1). This is a separate wheel-packaging blocker.

The previously reported official macOS arm64-wheel result remains relevant platform context: the first capture aborts in Metal RGB readback before any means print. The Linux source build below reaches all captures successfully and directly tests the mapper-selection claim.

Exact runtime example

python
import numpy as np
import open3d as o3d

renderer = o3d.visualization.rendering.OffscreenRenderer(160, 90)
scene = renderer.scene
scene.show_skybox(False)
scene.view.set_post_processing(True)
grading = o3d.visualization.rendering.ColorGrading
for mode in (
    grading.ToneMapping.LINEAR,
    grading.ToneMapping.ACES,
    grading.ToneMapping.FILMIC,
):
    scene.view.set_color_grading(grading(grading.Quality.ULTRA, mode))
    scene.set_background([1.0, 1.0, 1.0, 1.0])
    pixels = np.asarray(renderer.render_to_image())
    print(mode, pixels[15:60, 15:60, :3].mean(axis=(0, 1)))

Each repetition was a fresh process:

bash
env -u DISPLAY EGL_PLATFORM=surfaceless LIBGL_ALWAYS_SOFTWARE=true \
  python -u -X faulthandler tone_mapping.py

Source-build prerequisite

Upstream Filament v1.54.0 Linux is GLX-only. Both A/B sides used the same separately recorded EGL-headless backend-selection prerequisites to make a supported surfaceless desktop-OpenGL path available. No mapper-selection change was present in the baseline. The installed baseline libOpen3D.so.0.19.0 SHA-256 was 3f33cf9a8b26d0408894390a5cba5a4ecc0cbc62b9e7cd13ad67b7bed09a975c.

Baseline result: selection is ignored

All three fresh baseline processes produced the exact same values below:

ToneMapping.LINEAR [229.77382716 225.79160494 219.53283951]
ToneMapping.ACES   [229.75753086 225.77975309 219.53777778]
ToneMapping.FILMIC [229.75012346 225.77086420 219.53975309]
run_exit=0

The sub-0.024 channel differences are deterministic capture/dither artifacts, not different tone operators. Source inspection explains the result: the entire tone-mapping switch and builder call are commented out at this revision.

Isolated mapper-selection control

The only A/B change was to include filament/ToneMapper.h, map the supported Open3D enum values to local Filament v1.54 tone-mapper objects, and pass the selected pointer to ColorGrading::Builder::toneMapper():

kLinear       -> filament::LinearToneMapper
kAcesLegacy   -> filament::ACESLegacyToneMapper
kAces         -> filament::ACESToneMapper
kFilmic       -> filament::FilmicToneMapper
kDisplayRange -> filament::DisplayRangeToneMapper

All three fresh control processes produced the exact same values:

ToneMapping.LINEAR [252.91703704 252.71209877 252.78271605]
ToneMapping.ACES   [210.35950617 207.62617284 203.38962963]
ToneMapping.FILMIC [231.59703704 231.53432099 231.63407407]
run_exit=0

Candidate wheel SHA-256: f449eb1a5dbb54955a3844aec1c3794db2c57c2a8457afe9988ab86021750b0e.

These are large, stable operator-specific differences, confirming that the public Open3D selection now reaches Filament.

API compatibility note

Filament v1.54.0 has no UchimuraToneMapper or ReinhardToneMapper class. The isolated control therefore leaves Open3D's kUchimura and kReinhard on Filament's default behavior. That is a remaining API-policy decision rather than evidence against the supported five-mode fix.

Result

Confirmed on Linux. At the reported revision the ToneMapping parameter is accepted but not applied. The modern toneMapper() API fixes LINEAR, ACES_LEGACY, ACES, FILMIC, and DISPLAY_RANGE. UCHIMURA and REINHARD need an explicit compatibility decision because the corresponding classes no longer exist in bundled Filament v1.54.0.