Canvas2D output
Frames land in ImageData on a standard canvas. No WebGL state or GPU lifecycle.
EASEL.js gives JavaScript teams a renderer they can read: THREE-style objects, CPU rasterization, and deterministic canvas pixels.
Frames land in ImageData on a standard canvas. No WebGL state or GPU lifecycle.
Traversal, ordering, light bake, scanline fill, CPU depth tests, and framebuffer upload stay readable.
Scene, Mesh, Camera, Light, Material, and Geometry stay readable while the renderer remains CPU-only.
Camera tradeoffs, affine UVs, sorted transparency, and discrete opacity are documented.
Zero runtime dependencies, typed surface, npm and JSR distribution.
The renderer keeps the hard parts visible: stage timing, draw order, raster output, and framebuffer state.
Flat and Gouraud shading happen before rasterization.
Orthographic keeps affine UVs exact; perspective is available with visible texture warp.
Opaque fragments use a CPU depth buffer; transparent materials still need sorted order.
Opacity uses fixed steps instead of fragile float alpha paths.
Docs, source snippets, and rendered examples stay crawlable. Live editing belongs in a separate app surface.
npmjs.com
bun install @xsyetopz/easeljsr.io
bunx jsr add @xsyetopz/easelnpmjs.com
deno add npm:@xsyetopz/easeljsr.io
deno add jsr:@xsyetopz/easelnpmjs.com
npm install @xsyetopz/easeljsr.io
npx jsr add @xsyetopz/easelnpmjs.com
pnpm add @xsyetopz/easelnpmjs.com
yarn add @xsyetopz/easelconst EASEL = require("@xsyetopz/easel");
const renderer = new EASEL.Renderer({ canvas, width: 800, height: 600 });
const scene = new EASEL.Scene();
const camera = new EASEL.PerspectiveCamera({ fov: 45, aspect: 4 / 3 });
camera.position.set(0, 2, 5);
scene.add(new EASEL.AmbientLight(0xffffff, 0.4));
const box = new EASEL.Mesh(
new EASEL.BoxGeometry(1, 1, 1),
new EASEL.LambertMaterial({ color: 0xff4444 }),
);
scene.add(box);
renderer.render(scene, camera);import * as EASEL from "@xsyetopz/easel";
const renderer = new EASEL.Renderer({ canvas, width: 800, height: 600 });
const scene = new EASEL.Scene();
const camera = new EASEL.PerspectiveCamera({ fov: 45, aspect: 4 / 3 });
camera.position.set(0, 2, 5);
scene.add(new EASEL.AmbientLight(0xffffff, 0.4));
const box = new EASEL.Mesh(
new EASEL.BoxGeometry(1, 1, 1),
new EASEL.LambertMaterial({ color: 0xff4444 }),
);
scene.add(box);
renderer.render(scene, camera);