Repository navigation
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
📦 Bundle sizeFull ESM build including core, minified and gzipped.
🌳 Bundle size after tree-shakingMinimal build including a renderer, camera, empty scene, and dependencies.
|
| function setCubeTexture( texture ) { | ||
|
|
||
| texture.isCubeTexture = true; | ||
| texture.isCompressedCubeTexture = true; |
There was a problem hiding this comment.
We should avoid monkey-patching the is* flags.
If you want to return a compressed cube texture, use the respective CompressedCubeTexture.
There was a problem hiding this comment.
I realize now this is tricky because the loader directly hands over an instance of CompressedTexture in load(). The loader does not know at that point what type of texture is inside the texture file 🤦♂️.
We need a solution for this anyway since ideally we return instances of Texture for uncompressed data at some point, see #35082 (comment).
I think what KTX2Loader does is better. It does not return a texture in load(), only in the callback. Maybe we should do the same in CompressedTextureLoader.
There was a problem hiding this comment.
Agreed on the monkey patching. Flags don't survive clone()
Passing the texture only to the callback sounds good. But removing the return value is breaking: map: loader.load( url ) works fine for 2D textures today, and FBXLoader / MTLLoader use the return value of a .dds handler.
How about a non-breaking first step?
loadAsync()resolves with the right class,CompressedCubeTexturefor cube maps.load()stays as is and warns deprecation when it loads a cube map. It monkey-patches the texture and points toloadAsync().- The DDS and PVRTC examples load their cube maps with
loadAsync().
Dropping the return value could come next after few releases
wdyt?
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ff09c3c to
9f3029f
Compare
Description
CompressedTextureLoaderreturns cube maps (DDSLoader,PVRLoader) as aCompressedTexturewith the faces inimage, without flagging it as a cube texture. Code that checksisCubeTexturehandles it as a 2D texture:WebGLRenderer: asscene.backgroundit is bound as a 2D texture, andWebGLTexturesthrows "Cannot read properties of undefined (reading 'length')" every frame. AsenvMapof a material that samples it directly, likeMeshBasicMaterial, it is mirrored compared toCubeTexture, toCompressedCubeTextureand to the same texture onMeshStandardMaterial, sinceflipEnvMapdepends onisCubeTextureand PMREM doesn't.WebGPURendererdecides between 2D and cube textures byisCubeTexture, so it can't use these cube maps at all.Fiddle (WebGLRenderer): https://jsfiddle.net/zqnj6Lts/6/
A DDS cube map as background and as
envMapof two spheres. The canvas stays black. Withparams.background = false, the left sphere (MeshBasicMaterial) is mirrored compared to the right one (MeshStandardMaterial).background: truebackground: falseWhether the data hold a cube map is only known once the file has been parsed, so this PR turns the texture returned by
load()into a compressed cube texture at that point: it setsisCubeTextureandisCompressedCubeTexture, asCompressedCubeTexturedoes, andCubeReflectionMappingunless the app has set a mapping. With the CompressedCubeTexture PR,WebGPURendererrenders these cube maps too.The cube map reflections in
webgl_loader_texture_ddsare no longer mirrored, so this PR updates its screenshot.webgl_loader_texture_pvrtcchanges the same way where PVRTC is supported; its screenshot stays, since the E2E browser doesn't support PVRTC.