canvas
buffergeometry
What this shows
160,000 random non-indexed triangles with flat face normals and position-based vertex colors fill a fogged cube that tumbles under ambient and directional light.
Side by side with the three.js r186 original: webgl_buffergeometry.html
Differences from three.js
- MeshPhongMaterial becomes LambertMaterial with Gouraud (per-vertex) lighting, so the triangles have no white specular highlight (specular 0xffffff, shininess 250).
- EASEL only reads RGB (itemSize 3) vertex colors and has no per-vertex alpha, so the random per-triangle alpha is dropped and the material is opaque instead of transparent; transparent: true would also turn off depth writes in EASEL and draw the triangles in submission order.
- Attribute.onUpload is a GPU upload hook with no EASEL equivalent, so the typed arrays stay in memory.
- Fog is sampled once per vertex from EASEL's 256-entry fog table instead of per pixel.
- All 160,000 triangles are transformed, lit and rasterized on the CPU every frame; a Bun stub-canvas run at 640x360 measured a median of about 62 ms per frame (roughly 16 fps), above the 33 ms budget, and the count is kept to match three.js.
Loading scene…Key API excerpt
Key API excerpt
import * as EASEL from "@xsyetopz/easel";
scene.fog = new EASEL.Fog({ color: 0x050505, near: 2000, far: 3500 });
const geometry = new EASEL.Geometry();
geometry.setAttribute("position", new EASEL.Attribute(new Float32Array(positions), 3));
geometry.setAttribute("normal", new EASEL.Attribute(new Float32Array(normals), 3));
geometry.setAttribute("color", new EASEL.Attribute(new Float32Array(colors), 3));
geometry.computeBoundingSphere();
const material = new EASEL.LambertMaterial({
color: 0xd5d5d5,
side: EASEL.Side.Double,
vertexColors: true,
});
const mesh = new EASEL.Mesh(geometry, material);
scene.add(mesh);
mesh.rotation.x = time * 0.25;
mesh.rotation.y = time * 0.5;
renderer.prepare(scene, camera);
renderer.render(scene, camera);