playcanvas / playcanvas/engine
V3: remove six-cubemap prefiltered IBL input (prefilteredCubemaps / skyboxPrefilteredN)
@mvaligursky is already working on this.
Since Sep 8, 2026.
- Dominant language
- JavaScript
- Stars
- 16.8k
- Forks
- 2k
- Avg merge
- 4h 32m
- Merged PRs (30d)
- 222
Description
Summary
The engine still accepts image-based lighting as a set of six prefiltered cubemaps (128, 64, 32, 16, 8, 4) and converts them on the GPU into an env atlas at assignment time. Since the env atlas is the only format the lit shaders sample, this input path is a legacy adapter carried in core. Proposal: drop it in V3 and, if needed, offer the conversion as a helper in extras.
Current state
Public entry points that accept the six-cubemap array
Scene#prefilteredCubemaps(src/scene/scene.js) – runsEnvLighting.generatePrefilteredAtlasand stores the result in an internal_internalEnvAtlas.Scene#setSkybox(cubemaps)– when element 1 is a cubemap (not an atlas), forwardscubemaps.slice(1)toprefilteredCubemaps.StandardMaterial#prefilteredCubemaps(src/scene/materials/standard-material.js) – same conversion, writesmaterial.envAtlas.- Cubemap asset handler (
src/framework/handlers/cubemap.js) – splits a legacy DDS prelit cubemap into six per-level cubemap textures and places them inasset.resources[1..6];AppBase#setSkyboxand the material handler's_assignCubemapthen feed those into the setters above.
Deprecated per-level accessors
Scene#skyboxPrefiltered128/64/32/16/8/4(@deprecated,@ignore, still emitted in the d.ts). These write straight into_prefilteredCubemaps[i]and setupdateShaders, bypassing the atlas regeneration and_resetSkyMesh(). They have no effect on lighting at all, and only affect the skybox if something else later rebuilds the sky mesh. Their getters returnundefinedon any scene set up throughenvAtlas, which is the path the Editor and asset pipeline use today.
Shader side
- No shader chunk samples the six prefiltered cubemaps. Lit shaders only read
texture_envAtlas.reflectionCubesamples a singletexture_cubeMapwith a non-LOD lookup for materialcubeMap/ bare sceneskybox. - The only unconverted use is
Scene#_getSkyboxTex, which picks one of the six as the skybox texture whenskyboxMip > 0(with the long-standing "skip the 32x32 level" quirk).
Proposal for V3
- Remove
Scene#skyboxPrefiltered128..4outright. They are already broken for lighting. - Remove
Scene#prefilteredCubemapsandStandardMaterial#prefilteredCubemaps. The engine's only IBL input becomesenvAtlas. - Simplify
Scene#setSkybox(or remove it in favour ofscene.skybox+scene.envAtlas). - In the cubemap asset handler, either stop synthesising the six per-level cubemaps from DDS, or convert them to an env atlas once at load time and expose only
[cubemap, envAtlas]inasset.resources. - Re-evaluate
skyboxMip: with no prefiltered cubemaps it would always drive the atlasmipLeveluniform, which also lets us drop the skipped-32x32 mapping quirk.
Migration
If existing users still have six-cubemap data (e.g. older DDS prefiltered assets), provide a small helper in extras that wraps EnvLighting.generatePrefilteredAtlas:
import { prefilteredCubemapsToEnvAtlas } from 'playcanvas/extras';
scene.envAtlas = prefilteredCubemapsToEnvAtlas(device, cubemaps);
This keeps the conversion available without carrying it in core Scene / StandardMaterial.
Notes
EnvLighting.generatePrefilteredAtlasitself stays; it is also used for atlas generation from a source cubemap.- Editor and
developer-sitedocs should be checked for references toprefilteredCubemaps/setSkyboxbefore removal.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.