BabylonJS / BabylonJS/Babylon-Lite

PBR linear output: guidance on opt-in seam and minifier-only bundle delta

Open
#676 2 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
149
Forks
29
Avg merge
1d 5h
Merged PRs (30d)
106

Description

## Use case

We are prototyping a generic opt-in path that allows a PBR scene to render its completed linear RGB result into a floating-point render target so that the application can own post-processing and final presentation.

The intended split is:

PBR lighting / IBL / emissive / plugins / fog → linear HDR render target

Then application-owned:

exposure → tone mapping → display gamma / presentation

## Proposed API

```ts
enablePbrLinearOutput(scene: SceneContext): void;
```

Called on a fresh scene before mesh/build/registration work. It is opt-in, idempotent while fresh, and has no runtime disable; a new scene is required to return to display output.

For opted-in PBR, the final exposure, tone-mapping, display-gamma, clamp and contrast processing is omitted. Alpha is unchanged.

## Current implementation shape

The prototype follows the same general family as other optional Lite enablers:

- Lazy WeakSet owned by the enabler.
- Resolver installed only when the feature is enabled.
- Optional resolver call in the PBR build path.
- No feature work during frame rendering.

The currently open implementation in [PR #674](https://github.com/BabylonJS/Babylon-Lite/pull/674), at `441b245e215e87fd8d19f3a1de1ca24c29846e24`, uses a similar enabler/WeakSet/resolver shape.

## Functional proof

Focused fixtures pass against source, lib and dist builds:

- `rgba16float`, 4x MSAA + resolve, with linear PBR readback `[14.34375, 14.34375, 14.34375]`.
- Fog and unlit preserved.
- Alpha MASK and double-sided preserved.
- CSM and a public MaterialPlugin contribution preserved.
- Two scenes with opposite policies remain isolated on one device, in both build orders and after rebuilds.
- Default output remains unchanged.
- No WebGPU validation errors in the focused fixtures; 57 devices acquired and 57 destroyed.

## Bundle result

Fetched runtime bytes, measured with the same toolchain and lockfile against `c9958540d15e457e2f4ba2be55d17dcfb0b09e39`:

| Scene | Base | Candidate | Delta |
| --- | ---: | ---: | ---: |
| scene1 | 89481 | 89476 | -5 B |
| scene10 | 52574 | 52577 | +3 B |
| scene214 | 69338 | 69338 | 0 B |
| scene216 | 53756 | 53759 | +3 B |

For scene10 and scene216, inspection of every emitted runtime chunk found no retained linear-output feature semantics/code.

The +3 B is caused by three occurrences of an existing `baseColorMod` identifier receiving a two-character minified name (`te`) instead of a one-character name (`J` / `Y`). All other emitted edits sum to zero bytes. A complete edit list reconstructs the candidate chunks byte-for-byte.

For precision, the raw diff also contains changed chunk hashes and a historical diagnostic ID changing from 459 to 460, with the same decoded message and zero byte delta. The +3 B growth itself is entirely identifier renaming. No minifier manipulation or unrelated byte compensation was used.

## Primary questions

Does Babylon Lite consider this minifier-only byte movement an unrelated-scene bundle regression that must still be eliminated, or is the architectural requirement satisfied when no feature semantics/code remain in the unused bundle?

Is there a preferred existing PBR opt-in seam pattern we should use instead?

## Lifecycle guard

There is one API-lifecycle question still open.

The enabler can reject scenes that already contain meshes/groups or are built, but during the first registration of an otherwise empty scene there is currently no existing state we found that reliably distinguishes "fresh" from "registration already in progress" before `_built` is set.

Is there an existing scene lifecycle state/seam that optional pre-build enablers should use for this guard, or should this simply be documented as a pre-registration contract?

## Scope

- No bundle ceilings/baselines were changed.
- No fork is being proposed.
- No private API is required by callers.
- The prototype remains local and has not been pushed or submitted as a PR.
- We are asking for guidance before polishing/submitting the patch; this is an unfinished prototype.

Contributor guide

Open the contributing guide

Research direction

Start by reviewing PR #674 at commit 441b245e215e87fd8d19f3a1de1ca24c29846e24, then compare its optional Lite enabler, WeakSet, resolver, and PBR build-path pattern with the prototype. Review the focused fixtures and bundle measurements described here. Done means resolving the preferred opt-in seam, lifecycle guard, and treatment of minifier-only bundle deltas before the prototype is polished into a PR.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
computer-graphics
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
32/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.