We are working on babylon native for that specific goal (cc @bghgary )
How often NPM packages willl be updated?
once a week on Thursday but I will do it more often for now
thank you so much for the explanations! and the swift implementation of that api!
i’m now working full time building a game with babylon lite, and i’m hoping to share a prototype in the coming weeks. thanks so much @Deltakosh and the whole team – seeing how responsive and helpful you are assures me that i’m in good hands depending on babylon.
a question about cloning meshes and manipulating vertex colors:
- in my game, i want to take source meshes from the asset container, and then make clones of them where i can run an algorithm to manipulate the vertex colors of some of the clones (i want to recolor all [1, 0, 0] red colors to the appropriate team color, thus i’ll start with
pylon, and then producepylon_red,pylon_blue,pylon_white, etc) - is
cloneTransformNodeappropriate for this above use-case? you mentioned the clones share gpu buffers – if i produce a clone of a mesh, can i manipulate the vertex color data independently? what would be the best practice for my use-case?
as i continue to integrate babylon lite for my game, i’m interested to write a babylon lite tutorial, and also produce an npm library of my own babylon lite helpers, which i think i’ll call @benev/buddy – time to roll up my sleeves and get cracking!
it is right there if using thin instances (which is HIGHLY recommended)
If using clones, you have independent meshes so you can control everything independently
setThinInstanceColors(mesh, colors);
yes thank you, in most cases this would be preferable – however for my unique particular use-case, i need to manipulate the colors per-vertex, changing some colors but leaving others intact (whereas if my understanding is correct, setThinInstanceColors would set a singular color per whole instance – even still i will benefit by using instances, eg, my augmented pylon_red may have 15 instances and pylon_blue might have 11)
some questions,
- can i not load a gltf by directly providing the data? i see that
loadGltf(engine, url)requires a urlstring– it would seem i cannot directly pass a File/Blob/ArrayBuffer as i could in the past? - i found
renderFrame(engine, delta), but i don’t understand how it does not need to know whichsceneto render? - i would love to get a clearer understanding of the basic relationships between engines, scenes, and asset containers.
as a workaround for (1), i think i’ll do something like this for now:
// in my case i actually get a file handle via drag-and-drop
const file = exampleGetFileHandle()
const url = URL.createObjectURL(file)
try {
const assets = await loadGltf(engine, url)
exampleUsageOfAssets(assets)
}
finally {
URL.revokeObjectURL(url)
}
Great questions, and your instinct on the colors is exactly right. Let me take them in order.
1. Per-vertex colors vs. instance colors
Your understanding is correct. setThinInstanceColors / setThinInstanceColor set one RGBA per instance (a separate instanceColor attribute multiplied in by the shader). They don’t touch vertex colors.
For per-vertex work, use:
updateMeshColors(engine, mesh, colors /* Float32Array, vec4/vertex */, vertexOffset = 0)
It does a zero-allocation partial re-upload of the mesh’s COLOR_0 buffer, so “change some, leave others intact” is just a matter of passing a sub-array plus the vertexOffset of the first vertex you’re touching. The mesh must have been created with a color buffer.
One caveat to plan around: thin instances share a single geometry/vertex buffer. So updateMeshColors on pylon_red re-tints the vertices for all 15 red instances together. Vertex colors can’t vary between instances of the same thin-instanced mesh; only the per-instance instanceColor can. If every red pylon shares the same per-vertex pattern, your pylon_red (15) / pylon_blue (11) grouping is exactly the right approach. If each individual pylon needs a unique per-vertex pattern, those would need to be separate meshes rather than instances.
2. Loading glTF from data instead of a URL
Today loadGltf(engine, url) only takes a string and fetch()es it internally; there’s no File / Blob / ArrayBuffer overload. Use URL.createObjectURL(blob) and pass the resulting blob: URL:
const url = URL.createObjectURL(blob);
const container = await loadGltf(engine, url);
URL.revokeObjectURL(url);
This works cleanly for self-contained .glb (a single binary fetch) and for .gltf with embedded data: URIs. It will not resolve a multi-file .gltf that references external .bin / textures by relative path, because the base-URL resolution has no directory to work from.
3. Why renderFrame(engine, delta) doesn’t take a scene
Because scenes register themselves with the engine. A scene is bound to a surface (the engine is surface index 0), and registerScene(scene) pushes it onto that surface’s rendering-context list. renderFrame then walks every surface and every registered scene, records their passes, and submits one command buffer. So the engine renders all currently-registered scenes each frame, in registration (overlay) order. You control what’s drawn with registerScene / unregisterScene rather than by passing a scene each frame. startEngine just wraps renderFrame in a requestAnimationFrame loop with auto-computed delta; call renderFrame yourself only if you want to drive your own loop.
4. Engine / Scene / AssetContainer relationships
- Engine (
createEngine): owns the WebGPU device, queue, and render loop. It’s also the primary surface (index 0): the default canvas/swapchain. Extra canvases or offscreen targets are additional surfaces viacreateSurface. - Scene (
createSceneContext(engine)): the renderable unit, holding camera, lights, meshes, clear color, and frame graph. Bound to a surface; multiple scenes can be registered on one surface as overlays. - AssetContainer: the result of a load (
loadGltfreturns one). It’s a passive bag of entities (the rootTransformNodehierarchy, plus any animation groups, lights, or cameras from the file). It is not rendered on its own; you splice it into a scene withaddToScene.
Typical lifecycle:
const engine = createEngine(canvas);
const scene = createSceneContext(engine); // engine acts as the surface
const container = await loadGltf(engine, url); // -> AssetContainer (just data)
addToScene(scene, container); // wire hierarchy + animations into the scene
addToScene(scene, camera /*, lights, etc. */);
await registerScene(scene); // join the render loop
startEngine(engine); // RAF loop calling renderFrame(engine, delta)
So: Engine = device + loop + surface, Scene = what gets drawn, AssetContainer = loaded data you pour into a scene.
this all makes good sense – truly marvelous, thanks so much @Deltakosh for the incredible support! i will report back soon about my progress integrating lite into my game ![]()
There is a stale internal VERSION string/banner
export declare const VERSION = "0.1.0";
in node_modules/@babylonjs/lite/index.d.ts.
So currrent version 1.1.0 still shows “Babylon Lite v0.1.0 - WebGPU engine”
cc @RaananW ![]()
A bit late to the party, but amazing news, big congrats ![]()
And how did you know some of my top wish list items:
Functional rather than classes
Fully shakable
Out of the box Vite support
Guess I need to get busy porting stuff like bjs-ecs over.
Would also love to help out, will maybe take a look at those glTF extras, which I really need for doing level design in Blender ![]()
After updating to https://www.npmjs.com/package/@babylonjs/lite/v/1.2.0
there are no issues in the console but there is nothing visible in the scene.
Version 1.1.0 worked without problems.
It seems we have fbx support now
That might be a vialbe option.
it turns out that the loadGltf workaround via URL.createObjectURL does not work, i created a github issue for this on the lite repo: loadGltf cannot load local data · Issue #260 · BabylonJS/Babylon-Lite · GitHub
Looking…
@labris 1.1.0 and 1.2.0 are byte-for-byte identical (the 1.2.0 release was related to the experimental compat layer, so lite itself had no changes), and I’m unable to repro any issue with any of the packages. 1.0.1, 1.1.0, and 1.2.0 all work and render the exact same thing in my tests. Can you provide a repro?
Same here. Ran all the tests. No problems
On it!
There was the breaking API change between 1.0.1 and 1.2.0.
In my case the difference was
await registerScene(engine, scene);
which now should be
await registerScene(scene);
So I updated my Babylon Lite Vite template accordingly. Now the issue is solved.
yeah and buckle up we may break it again
Until the official release with babylon 10 it may be a bit rocky ![]()
But we will document it better!