Missing API
light.excludedMeshes and light.includedOnlyMeshes (Light base class, all light types), both as assignment (light.excludedMeshes = [...]) and in-place edits (light.excludedMeshes.push(mesh)).
Current behavior
The export is missing entirely — there is no accessor on the compat Light, so the assignment becomes a plain own property and never reaches Lite. Nothing throws, the light just stays global.
Use case
A kitchen configurator moving from Babylon.js 9 to Lite through lite-compat. Two places depend on it:
- A rim light meant for the furniture only. The room (floor, walls, ceiling) is put into
excludedMeshes, otherwise the floor catches it with its whole horizontal plane and washes out. On Lite the room was lit by it: +24 levels on the floor and +50 on a side wall in an 8-bit frame, measured with every other light switched off (Babylon.js: 0).
- LED spot lights inside cabinets are scoped to their own module with
includedOnlyMeshes. On Lite every one of them is a global light, so a kitchen with many LED modules runs into the per-mesh light limit.
Minimal example
const rim = new DirectionalLight("rim", new Vector3(-2.2, -1.2, -1.6), scene);
rim.excludedMeshes = scene.meshes.filter((m) => /^(floor$|ceiling$|wall)/.test(m.name));
scene.onNewMeshAddedObservable.add((mesh) => {
if (/^(floor$|ceiling$|wall)/.test(mesh.name)) {
rim.excludedMeshes.push(mesh);
}
});
const led = new SpotLight("led", position, direction, angle, exponent, scene);
led.includedOnlyMeshes = moduleMeshes;
Additional context
The native side already has what is needed: LightBase.excludedMeshIds / includedOnlyMeshIds, matched against mesh.id in affectsMesh (render/lights-ubo.ts). My app-side bridge maps the two arrays onto those sets and works, with two things to watch:
- Lite meshes created through compat have no
id, and affectsMesh treats an id-less mesh as always lit, so the bridge has to hand out ids.
- The per-mesh light selection is baked when the mesh's renderable is built. Lists that are set in the same tick the light is created are picked up by the rebuild that adding the light triggers anyway; changing them later for meshes that are already built needs those renderables rebuilt (I go through
material._refreshInScene()).
Missing API
light.excludedMeshesandlight.includedOnlyMeshes(Lightbase class, all light types), both as assignment (light.excludedMeshes = [...]) and in-place edits (light.excludedMeshes.push(mesh)).Current behavior
The export is missing entirely — there is no accessor on the compat
Light, so the assignment becomes a plain own property and never reaches Lite. Nothing throws, the light just stays global.Use case
A kitchen configurator moving from Babylon.js 9 to Lite through
lite-compat. Two places depend on it:excludedMeshes, otherwise the floor catches it with its whole horizontal plane and washes out. On Lite the room was lit by it: +24 levels on the floor and +50 on a side wall in an 8-bit frame, measured with every other light switched off (Babylon.js: 0).includedOnlyMeshes. On Lite every one of them is a global light, so a kitchen with many LED modules runs into the per-mesh light limit.Minimal example
Additional context
The native side already has what is needed:
LightBase.excludedMeshIds/includedOnlyMeshIds, matched againstmesh.idinaffectsMesh(render/lights-ubo.ts). My app-side bridge maps the two arrays onto those sets and works, with two things to watch:id, andaffectsMeshtreats an id-less mesh as always lit, so the bridge has to hand out ids.material._refreshInScene()).