Magic pixels
Magic pixels is a WebGL 3D library, which was originally developed under the name colorful-pixels at SinnerSchrader.
As I left the company, development work will be continued in this fork.
Why yet another WebGL library?
To be honest, there really is no need to build our own 3D library. There are many of these already out there. This is actually a project by Lea, and she decided building something like that anyway, just in order to learn how all this works.
Features
- An API that is somewhat familiar to THREE
-
Vector
,Matrix
classes - a
Renderer
which rendersMesh
es - a
Mesh
contains aBufferGeometry
and aMaterial
, - a
Material
is what's aRawShaderMaterial
in THREE, it has uniform variables, vertex and fragment shaders and adrawMode
- the
drawMode
is one of those WebGL constantsgl.TRIANGLES
,gl.POINTS
,gl.LINES
... - the
BufferGeometry
API is also similar to three.js - Helpers for creating orthographic, perspective projection matrices
- A
Stopwatch
class for timing (likeperformance.now()
but with the possibility to start/stop) - One-Liners (
mix
,clamp
) - Basic geometries (plane geometry, box geometry, sphere geometry and a custom geometry)
API documentation
Getting started
- First, add it to your project via
npm install magic-pixels
. - Add a
<canvas>
element to your DOM - Initialize the WebGL renderer
- Add a resize event handler
- create a scene, consisting of Meshes (a scene is an array of meshes)
Initialize Renderer
const canvas = document.querySelector('canvas');
const renderer = new Renderer(canvas);
renderer.setSize(innerWidth, innerHeight);
Create a geometry
// creates a plane geometry of width 2x2 with 3 width segments and 3 height segments
const planeGeometry = createPlaneGeometry(2, 2, 3, 3);
// creates a box geometry of width 1x1x1 with 3 width segments, height segments and depth segments
const boxGeometry = createBoxGeometry(1, 1, 1, 2, 2, 2);
// create a sphere geometry with 16 rings and 16 sides per ring
const sphereGeometry = createSphereGeometry(1, 1, 16, 16);
Create a material
A material contains a vertexShader
, a fragmentShader
, a drawMode
and a uniforms
object.
When a mesh is initialized, the uniforms
object is wrapped by a ES6 Proxy, so the state in the gl context is automatically updated.
The default drawMode is gl.TRIANGLES
, see MDN:drawArrays for more options.
const material = createShaderMaterial(vertexShader, fragmentShader, {
time: 0,
resolution: [800, 600],
color: Color.fromHex('#ff00ff'),
});
// There are some predefined materials:
// just red
const defaultMaterial = createDefaultMaterial();
// just pink
const basicMaterial = createBasicMaterial('#ff00ff');
// the normals
const normalMaterial = createNormalMaterial();
Create a mesh and render
const mesh = new Mesh(geometry, material);
// currently, the scene is just an array of meshes:
const scene = [mesh];
// render:
renderer.render(scene);
Camera
const camera = new Camera();
camera.position.set(0, 0, 5);
camera.target.set(0, -0.5, 0);
camera.update();
console.log('camera matrix:', camera.cameraMatrix);
console.log('view matrix:', camera.viewMatrix);
// the view matrix is the inverse of the camera matrix
// you can pass these into the material.uniforms object.
Perspective projection
The camera (currently) does not do projection by itself, but you can create a perspective projection matrix:
const fieldOfView = 70;
const aspectRatio = innerWidth / innerHeight;
const near = 0.01;
const far = 100;
material.uniforms.projectionMatrix = perspective(
fieldOfView,
aspectRatio,
near,
far
);
Vector/matrix arithmetics
magic-pixels provide basic vector and matrix arithmetics classes.
You can use the mul
method on the Matrix class for matrix multiplication.
const a = new Vector(1, 0, 0);
const b = new Vector(0, 1, 0);
const c = a.cross(b);
const d = a.add(b);
Create translation Matrices
// identity matrix
const identity = Mat4.identity();
// translate object in space
const translationMatrix = Mat4.translation(tx, ty, tz);
// rotation matrix
const DEG = Math.PI / 180;
const rX = Mat4.rotX(30 * DEG);
const rZ = Mat4.rotY(45 * DEG);
const rZ = Mat4.rotZ(-5 * DEG);
const rotationMatrix = rX.mul(rY).mul(rZ);
Color helper
The color helper converts a hex color string to a GLSL-friendly vec3 or vec4 value.
const color = Color.fromHex('#ff00ff');
// returns a Color with {red = 255, green = 0, blue = 255, alpha = 255}
color.toVec3();
// returns [1, 0, 1]
color.toVec4();
// returns [1, 0, 1, 1]
Examples on Codepen
Trigger Warning: these examples can cause sickness to people with motion sensitivities.