Skip to content

[Native] Load single-file .dds/.ktx/.ktx2 cubemaps on the native engine#18560

Closed
bkaradzic-microsoft wants to merge 2 commits into
masterfrom
native-cube-container-loading
Closed

[Native] Load single-file .dds/.ktx/.ktx2 cubemaps on the native engine#18560
bkaradzic-microsoft wants to merge 2 commits into
masterfrom
native-cube-container-loading

Conversation

@bkaradzic-microsoft

@bkaradzic-microsoft bkaradzic-microsoft commented Jun 10, 2026

Copy link
Copy Markdown
Member

[Native] Load single-file .dds/.ktx/.ktx2 cubemaps on the native engine

Problem

The native engine overrides createCubeTexture (nativeEngine.cubeTexture.pure.ts) and only
handles two cases: a single .env file, and an array of six face files. A single self-contained
cubemap container — .dds / .ktx / .ktx2, the format produced by
CubeTexture.CreateFromPrefilteredData(...) — falls through to:

throw new Error("Cannot load cubemap because 6 files were not defined");

So prefiltered-environment scenes (PBR IBL) that reference a single .dds cannot load it on
native at all.

This path was never wired because the generic WebGL loader route isn't usable on native: the
engine's _uploadDataToTextureDirectly / _uploadCompressedDataToTextureDirectly (and cube
_readTexturePixels) are unimplemented there — native uploads via its own command path, and the
.env branch worked only because .env ships pre-split faces plus baked spherical harmonics.

Fix

Route a single-URL container cubemap to the native engine, which decodes it (bimg already supports
DDS/KTX/KTX2 cube containers) and, when polynomials are requested, returns the spherical-harmonics
coefficients it computed from the top mip. The diffuse-IBL spherical polynomial is then set on the
texture from those coefficients.

  • nativeEngine.cubeTexture.pure.ts: in the non-.env branch, keep the existing six-file path,
    and add a branch for a single-URL container — fetch the bytes (or use the provided buffer),
    call engine.loadCubeTexture(resource, [buffer], ...), and on success set
    _sphericalPolynomial from the returned coefficients (when createPolynomials was requested).
  • nativeInterfaces.ts: loadCubeTexture's onSuccess now optionally carries the spherical
    polynomial coefficients ((sphericalPolynomial?: Float32Array) => void); the existing six-file
    caller ignores them.

No change to the .env or six-file paths.

Pairs with a Babylon Native NativeEngine change that implements the single-buffer cube decode
(via bimg) and the spherical-harmonics computation from the top mip. This JS change requires that
native support to be present.

Testing

Validated on Babylon Native (Win32 / D3D11) with the Playground validation suite: six previously
unloadable prefiltered-environment .dds PBR scenes now load and render correctly, matching their
reference images. The computed spherical-harmonics integration is correct (total solid angle = 4π).


Related PRs & landing order

Co-dependent; land in this order:

  1. Babylon.js [Native] Load single-file .dds/.ktx/.ktx2 cubemaps on the native engine #18560 first — adds the single-URL container cube dispatch + spherical-harmonics wiring; no WebGL behavior change.
  2. A babylonjs npm release ships that TS change.
  3. BabylonNative Canvas2D: fix Sprite2D boundingBox not updated #1748 last — bumps the bundled babylonjs and re-enables the 6 prefiltered-.dds PBR validation tests, which only pass once the paired JS is present in the bundled engine. The folded-in blur-cube-with-the-effect-renderer test additionally requires [Native] Honor depthCullingState.depthTest on the native engine #18558 to be in the same babylonjs release.

@bjsplat

bjsplat commented Jun 10, 2026

Copy link
Copy Markdown
Collaborator

Please make sure to label your PR with "bug", "new feature" or "breaking change" label(s).
To prevent this PR from going to the changelog marked it with the "skip changelog" label.

1 similar comment
@bjsplat

bjsplat commented Jun 10, 2026

Copy link
Copy Markdown
Collaborator

Please make sure to label your PR with "bug", "new feature" or "breaking change" label(s).
To prevent this PR from going to the changelog marked it with the "skip changelog" label.

@bjsplat

bjsplat commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator

Snapshot stored with reference name:
refs/pull/18560/merge

Test environment:
https://snapshots-cvgtc2eugrd3cgfd.z01.azurefd.net/refs/pull/18560/merge/index.html

To test a playground add it to the URL, for example:

https://snapshots-cvgtc2eugrd3cgfd.z01.azurefd.net/refs/pull/18560/merge/index.html#WGZLGJ#4600

Links to test your changes to core in the published versions of the Babylon tools (does not contain changes you made to the tools themselves):

https://playground.babylonjs.com/?snapshot=refs/pull/18560/merge
https://sandbox.babylonjs.com/?snapshot=refs/pull/18560/merge
https://gui.babylonjs.com/?snapshot=refs/pull/18560/merge
https://nme.babylonjs.com/?snapshot=refs/pull/18560/merge

To test the snapshot in the playground with a playground ID add it after the snapshot query string:

https://playground.babylonjs.com/?snapshot=refs/pull/18560/merge#BCU1XR#0

If you made changes to the sandbox or playground in this PR, additional comments will be generated soon containing links to the dev versions of those tools.

@bjsplat

bjsplat commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator

@bjsplat

bjsplat commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator

@bjsplat

bjsplat commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator

🟢 Memory Leak Test Results

13 passed, 0 leaked out of 13 scenarios

🟢 All memory leak tests passed — no leaks detected.

Passed Scenarios (13)
Scenario Package
Core Feature Stack @babylonjs/core
Core Rendering Materials Shadows Stack @babylonjs/core
Core Textures Render Targets PostProcess Stack @babylonjs/core
GUI Fullscreen UI Controls @babylonjs/gui
GUI Mesh ADT Controls @babylonjs/gui
Loaders Boombox Import @babylonjs/loaders
Loaders OBJ Direct Load @babylonjs/loaders
Loaders STL Direct Load @babylonjs/loaders
Materials Library Stack @babylonjs/materials
Serializers glTF Export @babylonjs/serializers
Serializers GLB Export @babylonjs/serializers
PostProcesses Digital Rain Stack @babylonjs/post-processes
Procedural Textures Stack @babylonjs/procedural-textures

@bjsplat

bjsplat commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator

@bjsplat

bjsplat commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator

⚡ Performance Test Results

🟢 All performance tests passed — no regressions detected.

bkaradzic-microsoft pushed a commit to bkaradzic-microsoft/BabylonNative that referenced this pull request Jun 12, 2026
…armonics

loadCubeTexture now accepts a single self-contained cubemap container (all six
faces + mips), decoded via bimg::imageParse, and uploads sides 0-5 x mips.
ComputeCubeSphericalPolynomial derives the diffuse-IBL spherical harmonics from
the top-mip faces (port of CubeMapToSphericalPolynomialTools) and returns the
polynomial coefficients to JS. This is done natively because the WebGL upload and
cube-readback paths are unimplemented on native and .dds stores no SH.

Re-enables 6 prefiltered-environment PBR validation tests.

Pairs with BabylonJS/Babylon.js#18560 (native createCubeTexture dispatch for
single-URL containers). Depends on a babylonjs dependency bump including it.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
bkaradzic and others added 2 commits June 16, 2026 16:51
The native createCubeTexture override only handled a single .env file or six
face files; a single self-contained cubemap container (.dds/.ktx/.ktx2, as
produced by CubeTexture.CreateFromPrefilteredData) threw "Cannot load cubemap
because 6 files were not defined". The generic WebGL loader route is unusable on
native (its texture-upload and cube-readback entry points are unimplemented).

Route a single-URL container cubemap to engine.loadCubeTexture with the raw
buffer; the native engine decodes it (bimg) and, when polynomials are requested,
returns spherical-harmonics coefficients computed from the top mip, which are set
as the texture's spherical polynomial. loadCubeTexture's onSuccess now optionally
carries those coefficients. The .env and six-file paths are unchanged.

Pairs with a Babylon Native NativeEngine change implementing the single-buffer
cube decode and spherical-harmonics computation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…d onSuccess

The six-file path passed the Promise resolve directly, which is not assignable to
the widened onSuccess signature (sphericalPolynomial?: Float32Array). Wrap with
() => resolve() / () => reject(new Error(...)).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@bkaradzic-microsoft bkaradzic-microsoft force-pushed the native-cube-container-loading branch from 09715d8 to 843f25c Compare June 16, 2026 23:51
@bjsplat

bjsplat commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

@bjsplat

bjsplat commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

@bkaradzic-microsoft

bkaradzic-microsoft commented Jun 17, 2026

Copy link
Copy Markdown
Member Author

Closing as superseded by the loader rework (the BabylonNative#218 loader rework, BabylonJS/BabylonNative#218): implementing the native _uploadDataToTextureDirectly / _uploadCompressedDataToTextureDirectly stubs lights up the stock JS loader path on native, so the generic _DDSTextureLoader handles single-file .dds/.ktx/.ktx2 cube containers end-to-end (parse + upload + spherical-harmonics computed in JS via CubeMapToSphericalPolynomialTools.ConvertCubeMapToSphericalPolynomial). That replaces this PR's bespoke single-URL cube branch and the native->JS SH-coefficient handoff entirely. See BabylonJS/BabylonNative#1748 (comment).

@bjsplat

bjsplat commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

🟢 Memory Leak Test Results

13 passed, 0 leaked out of 13 scenarios

🟢 All memory leak tests passed — no leaks detected.

Passed Scenarios (13)
Scenario Package
Core Feature Stack @babylonjs/core
Core Rendering Materials Shadows Stack @babylonjs/core
Core Textures Render Targets PostProcess Stack @babylonjs/core
GUI Fullscreen UI Controls @babylonjs/gui
GUI Mesh ADT Controls @babylonjs/gui
Loaders Boombox Import @babylonjs/loaders
Loaders OBJ Direct Load @babylonjs/loaders
Loaders STL Direct Load @babylonjs/loaders
Materials Library Stack @babylonjs/materials
Serializers glTF Export @babylonjs/serializers
Serializers GLB Export @babylonjs/serializers
PostProcesses Digital Rain Stack @babylonjs/post-processes
Procedural Textures Stack @babylonjs/procedural-textures

@bjsplat

bjsplat commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

@bjsplat

bjsplat commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

⚡ Performance Test Results

🟢 All performance tests passed — no regressions detected.

bkaradzic-microsoft pushed a commit to bkaradzic-microsoft/BabylonNative that referenced this pull request Jun 18, 2026
…armonics

loadCubeTexture now accepts a single self-contained cubemap container (all six
faces + mips), decoded via bimg::imageParse, and uploads sides 0-5 x mips.
ComputeCubeSphericalPolynomial derives the diffuse-IBL spherical harmonics from
the top-mip faces (port of CubeMapToSphericalPolynomialTools) and returns the
polynomial coefficients to JS. This is done natively because the WebGL upload and
cube-readback paths are unimplemented on native and .dds stores no SH.

Re-enables 6 prefiltered-environment PBR validation tests.

Pairs with BabylonJS/Babylon.js#18560 (native createCubeTexture dispatch for
single-URL containers). Depends on a babylonjs dependency bump including it.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
bkaradzic-microsoft pushed a commit to bkaradzic-microsoft/BabylonNative that referenced this pull request Jun 18, 2026
…armonics

loadCubeTexture now accepts a single self-contained cubemap container (all six
faces + mips), decoded via bimg::imageParse, and uploads sides 0-5 x mips.
ComputeCubeSphericalPolynomial derives the diffuse-IBL spherical harmonics from
the top-mip faces (port of CubeMapToSphericalPolynomialTools) and returns the
polynomial coefficients to JS. This is done natively because the WebGL upload and
cube-readback paths are unimplemented on native and .dds stores no SH.

Re-enables 6 prefiltered-environment PBR validation tests.

Pairs with BabylonJS/Babylon.js#18560 (native createCubeTexture dispatch for
single-URL containers). Depends on a babylonjs dependency bump including it.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants