Skip to content

NativeEngine: load single-file .dds/.ktx/.ktx2 cubemaps + spherical harmonics (re-enables 6 PBR tests)#1748

Draft
bkaradzic-microsoft wants to merge 1 commit into
BabylonJS:masterfrom
bkaradzic-microsoft:native-cube-dds-ktx-loading
Draft

NativeEngine: load single-file .dds/.ktx/.ktx2 cubemaps + spherical harmonics (re-enables 6 PBR tests)#1748
bkaradzic-microsoft wants to merge 1 commit into
BabylonJS:masterfrom
bkaradzic-microsoft:native-cube-dds-ktx-loading

Conversation

@bkaradzic-microsoft

Copy link
Copy Markdown
Member

NativeEngine: load single-file .dds/.ktx/.ktx2 cubemaps + compute spherical harmonics

What

Adds native support for loading a self-contained cubemap container (.dds / .ktx / .ktx2,
the format produced by CubeTexture.CreateFromPrefilteredData(...)) and re-enables six PBR
environment validation tests.

Plugins/NativeEngine/Source/NativeEngine.cpp:

  • loadCubeTexture now accepts a single buffer (all six faces + mips in one container).
    ParseCubeImage runs it through bimg::imageParse (which decodes DDS/KTX/KTX2 cubemaps), and
    LoadCubeTextureFromContainer uploads sides 0–5 × mips.
  • ComputeCubeSphericalPolynomial derives the diffuse-IBL spherical harmonics from the top-mip
    faces (a port of Babylon's CubeMapToSphericalPolynomialTools.ConvertCubeMapToSphericalPolynomial)
    and returns the 9×3 polynomial coefficients to JS.

Apps/Playground/Scripts/config.json: re-enables the six tests this unblocks (NMEGLTF,
Anisotropic, Clear Coat, PBRMetallicRoughnessMaterial, PBRSpecularGlossinessMaterial, PBR).

Why this shape

These scenes load a prefiltered environment via a single .dds. WebGL gets the cube faces and
computes the spherical harmonics on the CPU through the texture-loader path. On native that path
is unavailable: _uploadDataToTextureDirectly / _uploadCompressedDataToTextureDirectly and cube
_readTexturePixels are unimplemented stubs. The .dds also stores no SH (Babylon computes it from
the faces). So the SH must be computed from the decoded faces, in native C++, alongside the upload —
no .env swap, no JS polyfill, no GPU readback.

Paired Babylon.js change

Draft: depends on a babylonjs dependency bump that includes #18560. CI will pass once that is in
place. Verified locally against a from-source babylon.max.js built with #18560 (see below).

Verification (local)

  • The six re-enabled tests run via the normal path (no --include-excluded) and pass, matching their
    reference images. The SH integration is correct (total solid angle = 4π).
  • Scope note: Prepass SSAO + depth of field also references a .dds env — its cube now loads, but it
    still fails on unrelated SSAO/DoF/prepass differences, so it remains excluded (separate issue).

…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.

2 participants