Colorful pixels is a work-in-progress WebGL 3D 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.
- 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)
- First, add colorful pixels to your project via
npm install colorful-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)
const canvas = document.querySelector('canvas');
const renderer = new Renderer(canvas);
renderer.setSize(innerWidth, innerHeight);
// 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);
in colorful-pixels
, 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();
const mesh = new Mesh(geometry, material);
// currently, the scene is just an array of meshes:
const scene = [mesh];
// render:
renderer.render(scene);
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.
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
);
colorful-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);
// 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);
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]
Trigger Warning: these examples can cause sickness to people with motion sensitivities.