Skip to content

MERTULAS/Computer_Graphics_in_JS

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

41 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Computer Graphics in JS (Canvas, CPU-Based)

Demo GIFs

1) 3D Box: wireframe rotation with simple projection

3D Box Rotation

  • Shows live 2D transformations on polygons/rectangles using a simple animation loop.
  • The center-compensation keeps objects rotating/scaling around their centroid.

2) ImageData: per-pixel rendering as a vector and transformation

ImageData Translate

  • The image is drawn pixel-by-pixel via ImageData and moved with a simple translate.
  • Indexing uses base = (y * width + x) * 4 to access RGBA channels correctly.

3) 2D Transforms: rotate, scale, shear

2D Transforms

  • A minimal 3D-to-2D pipeline renders a rotating cube in wireframe.
  • Mouse-driven rotation simulates a camera-like experience.

A playground to learn and implement core computer graphics techniques in JavaScript on the CPU, step by step.

This project aims to demonstrate matrices, vectors, transformations (translate/rotate/scale/shear), a simple 3D → 2D projection, and pixel-level operations (ImageData) with an approachable, experiment-friendly setup. Everything intentionally runs on the CPU; the goal is learning rather than performance.

Contents & Architecture

  • 2D module (shapes/shapes2d.js)
    • Types: 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)
  • 3D module (shapes/shapes3d.js)
    • Transform3D and Box (wireframe cube)
    • A simple perspective approach and 2D projection (minimal teaching pipeline)
  • Canvas bootstrap (canvas/canvas.js)
    • Returns { canvas, ctx, dpr, clearCanvas, resize } and also sets window.__canvas__, window.__ctx__ for convenience
  • Vector/Matrix helpers (VectorJS/vector.js)
    • dot (matrix multiplication), normalize, 2D rotation helpers

Installation

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:

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.
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.
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

npm run dev   # development server
# npm run build  # production build (planned)

Contributing

  • Feel free to open issues or PRs for bugs and improvements.
  • Since the goal is learning, small, focused PRs with explanatory commit messages are appreciated.

This repository is meant to be a practical toolbox for “Computer Graphics 101”. Code and comments are intentionally simple to maximize learnability and experimentation. Have fun!

About

2D/3D Computer Graphics Technics with Pure JavaScript (on CPU Calculations)

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published