CPU-based computer graphics playground for JS: 2D/3D transforms, ImageData, simple projection.
npm install computer-graphicsImageData and moved with a simple translate.
base = (y width + x) 4 to access RGBA channels correctly.
shapes/shapes2d.js)
Point, Pixel
Transform base: translate, rotate, scale, shearX/Y/XY (with center compensation)
Polygon, Rectangle, Triangle (Triangle = Polygon[3])
ImageShape: builds pixels from ImageData and renders 1×1 fillRects (RGBA)
shapes/shapes3d.js)
Transform3D and Box (wireframe cube)
canvas/canvas.js)
{ canvas, ctx, dpr, clearCanvas, resize } and also sets window.__canvas__, window.__ctx__ for convenience
VectorJS/vector.js)
dot (matrix multiplication), normalize, 2D rotation helpers
bash
npm i
npm run dev
`
Vite is used only for development (devDependency). A production-ready dist/ build or alternative bundlers can be added later.
Quick Start
The snippet below adds a rectangle and a polygon to the scene and applies basic transforms:
`javascript
import { initCanvas, Rectangle, Polygon } from "computer-graphics";
const { clearCanvas } = initCanvas("canvas1", window.innerWidth, window.innerHeight);
const rect = new Rectangle(100, 100, 120, 80);
const poly = new Polygon([300, 300], [360, 220], [420, 320], [340, 360]);
function animate() {
clearCanvas();
rect.rotate(1);
poly.shearX(Math.sin(0.01));
rect.draw();
poly.draw(true);
requestAnimationFrame(animate);
}
animate();
`
Working with ImageData (Pixel Level)
- Draw the image onto the canvas, then grab the pixel buffer with getImageData.
- Correct indexing: base = (y width + x) 4 → iterate [r,g,b,a] in order.
- ImageShape converts pixels into Pixel objects and paints them with 1×1 fillRects.
`javascript
import { initCanvas, ImageShape } from "computer-graphics";
const { ctx } = initCanvas("canvas1", window.innerWidth, window.innerHeight);
const image = new Image();
image.src = "./assets/img.jpg";
image.onload = () => {
const w = image.naturalWidth, h = image.naturalHeight;
ctx.drawImage(image, 0, 0, w, h);
const { data } = ctx.getImageData(0, 0, w, h);
const img = new ImageShape(0, 0, data, w, h);
img.translate(200, 200);
img.rotate(37);
img.draw();
};
`
Note: If you want to use alpha in the 0–1 range, divide by 255 (a/255).
3D → 2D Projection (Educational)
- A Box is created in 3D space and projected to 2D before drawing.
- Rotations (rotateX/Y/Z) operate directly on 3D vertices, around the shape’s center.
- Camera model/focal length and related parameters can be extended later.
`javascript
import { initCanvas, Box } from "computer-graphics";
const { clearCanvas } = initCanvas("canvas1", window.innerWidth, window.innerHeight);
const box = new Box([500, 500, 1.5], 500);
function animate() {
clearCanvas();
box.rotateY(1);
box.draw();
requestAnimationFrame(animate);
}
animate();
`
Design Choices & Learning Notes
- As long as transforms are affine, a shape’s centroid moves linearly; center handling matters.
- For GUI slider inputs, prefer “absolute” semantics (e.g., scale relative to the original, not cumulatively per frame).
- If canvas CSS size differs from its real resolution, you might see blur; consider devicePixelRatio.
- We return ctx and also expose a global for convenience; prefer passing ctx explicitly for encapsulation/testing.
Roadmap
- [ ] Camera parameters (orthographic/perspective, f, near/far, view matrix)
- [ ] Absolute T·R·S model matrix per frame (reduce cumulative errors)
- [ ] Triangle rasterization, barycentric coordinates, z-buffer (depth test)
- [ ] Basic lighting (Lambert/Phong) — CPU-based
- [ ] OffscreenCanvas / Worker experiment for pixel rendering
- [ ] Production package (ESM/CJS) and a minimal demo page
Run / Development
`bash
npm run dev # development server
npm run build # production build (planned)
``