Filament upgrade ignores ColorGrading tone-mapper selection
- Dominant language
- C++
- Stars
- 14k
- Forks
- 2.6k
- Avg merge
- 5d 18h
- Merged PRs (30d)
- 6
Description
### Checklist
- [x] Tested the official Linux development wheel first.
- [x] Ran a successful Linux RGB comparison at the exact reported revision.
- [x] Repeated baseline and isolated-control captures in fresh processes.
### Environment and revisions
```text
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:
```text
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()`:
```text
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:
```text
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.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start at the ColorGrading implementation used by scene.view.set_color_grading and inspect the commented tone-mapping switch and ColorGrading::Builder::toneMapper() call. Reproduce the Linux comparison with the provided Python script, then verify distinct results for LINEAR, ACES_LEGACY, ACES, FILMIC, and DISPLAY_RANGE; the remaining UCHIMURA and REINHARD behavior requires an explicit compatibility decision.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp, python
- Domain
- api, computer-graphics
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 58/100