I was thinking to port my app to Babylon Lite (because its awsome ) but but i have some issues:
Missing SSAO. Are there plans to support it?
Missing Anti Aliasing (FXAA, SMAA …). I saw that you support TAA already. The problem is that it works only if the camera is not moving. For my case it would be the best to combine TAA with FXAA/SMAA or other techniques. Currently with BabylonJS i use FXAA while the camera is
moving and TAA when the camera is not moving.
How can i make sure mirrored meshes (negative scaling) are rendered correctly? I saw that the GLTF loader supports it but i need to implement a custom loader and this “reversed winding” logic seems to be internal. Could this be a public opt-in feature?
How can i remove a cloned mesh corretly from the scene. If i clone a mesh with “cloneTransformNode” and afterwards i remove the clone with “removeFromScene” the whole application breaks because of an error. I think the issue is that shared GPU data is disposed here. How can i remove only the clone? I know that i could use thin instances but this gets more complicated because of dynamic materials and mirrored meshes.
First - for missing features - we are doing our best to slowly-but-surely port all features to Babylon lite. When will SSAO move is still TBD. but eventually there is no reason that it wouldn’t. The list of features on Lite grows daily. Search for issues related to your request - if there already is an open issue, comment there. It will signal us for the need from the community.
Now, about 4 - this is a bug. or at least it sounds like one, if you can reproduce this in the lite playground it would be amazing.
And about 3 - i am not sure if it is a bug or a missing feature. maybe @ryantrem can answer here
Thank you so much! very helpful. I am making changes to removeFromScene, will make sure my upcoming PR will also include a fix for this. still identifying the issue.
Ohhh you added automatic ref-counting
I was expecting a parameter like doNotDisposeBuffers or something like that for removeFromScene and i need to keep track of the clones myself but this is much nicer
Hey @Kesshi — this is a missing opt-in feature rather than a bug, and I’ve got a proposed public API for it. Wanted to run it by you before finalizing.
Background: the “reversed winding” correction exists because a mirrored transform (an odd number of negatively-scaled axes → a negative world-matrix determinant) flips triangle winding on screen, so the default back-face cull removes the faces you actually want and the mesh renders inside-out. The glTF loader detects this and corrects it automatically; the proposal exposes the same capability for custom loaders / hand-built meshes.
Proposed API (importing from this module is what pulls the support code in — scenes that never use it stay byte-identical, so there’s no bundle-size cost for the common case):
import {
setMeshSideOrientation,
updateMeshSideOrientationFromTransform,
MeshSideOrientation,
} from "@babylonjs/lite"; // exact entry point TBD
// Option A — let it derive from the mesh's current world transform:
mesh.scaling.x = -1; // mirror it
updateMeshSideOrientationFromTransform(mesh);
// Option B — set it explicitly:
setMeshSideOrientation(mesh, MeshSideOrientation.FrontClockwise); // mirrored
setMeshSideOrientation(mesh, MeshSideOrientation.FrontCounterClockwise); // default
updateMeshSideOrientationFromTransform(mesh) reads the mesh’s world matrix and flags reversed winding when the transform is mirrored (negative determinant). Call it after the mesh’s transform (and parent, if any) are final.
setMeshSideOrientation(mesh, orientation) sets it explicitly if you already know the answer or want to override.
Call either before registerScene, since the render pipeline is built from that state.
Under the hood this is the exact same path the glTF loader uses, just made public.
Does this match what you need for your custom loader — specifically, would the auto updateMeshSideOrientationFromTransform(mesh) route cover your negative-scaling case, or do you also want the explicit setter? Want to make sure the shape is right before it lands.
Hi, the auto updateMeshSideOrientationFromTransform(mesh) should work in my case but setMeshSideOrientation would also be ok (just less convenient).
You said i need to call it before registerScene. In my case i need to dynamically add and remove meshes during runtime of the app. So i need to call it after registerScene. Would that be possible? Or do you mean i need to call it altleast once before register?
Good question — and my “before registerScene” wording was too strict. Let me correct it.
Yes, this works for your dynamic add/remove case. The winding flag is read when a mesh’s render pipeline is built, not once at registerScene. A mesh you add at runtime (after registerScene) has its pipeline built lazily when you add it to the scene, and that build reads the current orientation. So the rule is really:
Set the orientation before you add the mesh to the scene (and after its transform/parent are final).
For a mesh you’re adding dynamically that looks like:
// build/position the mesh, set negative scaling, etc.
updateMeshSideOrientationFromTransform(mesh); // or setMeshSideOrientation(mesh, ...)
scene.addMesh(mesh); // whatever your add call is — pipeline is built here, flag is picked up
You do not need to have called it before registerScene. You can add and remove mirrored meshes freely throughout the app’s lifetime.
One caveat to be aware of: the orientation is only re-evaluated when the pipeline is (re)built. If you take a mesh that’s already been added and rendered and then flip its scaling to negative in place, calling the function won’t retroactively rebuild that mesh’s pipeline, so the winding won’t update on its own. In that situation you’d remove and re-add the mesh (or otherwise trigger a rebuild). For adding/removing distinct meshes — your scenario — this never comes up. If that scenario is important to you as well, I’d be interested to know (and why).
In my case i do not need to change the orientation after the mesh was added but i think others may need it. Just imagine a level editor for a game with an interactive tool to mirror objects. This would make it necessary to dynamically update the pipeline. Maybe you could just add a rebuildMeshPipeline function or something like that. This could be used for all special cases then.
There is some other work that was happening in parallel that overlapped with this, but I should be able to merge the two together and get a PR out soon!
Hey @Kesshi — update on the mirrored-mesh question, plus a course correction on what I proposed above.
Some work that was in flight ended up covering this more completely than the setMeshSideOrientation API I sketched, so we’re shipping that instead. It’s a single scene-level opt-in:
import { enableMirroredMeshes } from "babylon-lite";
await enableMirroredMeshes(scene); // once, after your assets are added, before registerScene
No per-mesh calls. Winding is derived from each mesh’s live world determinant, so it covers your custom loader and procedural meshes, and it applies to both PBR and Standard materials. Nothing references the support code statically, so scenes that never call it keep the same bundle they have today.
Two ways this improves on what I described earlier:
Your level-editor case from post #12 already works — no rebuildMeshPipeline needed. A per-frame watcher notices when a mesh’s determinant sign actually flips and rebuilds only that mesh’s pipeline. It only examines meshes whose world matrix changed that frame, so the steady-state cost is an integer compare per mesh.
The caveat in my post #11 no longer applies: mirroring a mesh after it has been added and rendered now updates on its own.
One thing to know: the runtime tracking is scoped to the scene you pass, so call it for each scene that needs it.
This landed on master after 1.15.0, so it isn’t on npm yet — it’ll go out in the next release.