Four
💎 Minimal three.js alternative.
Install / Use
/learn @CodyJasonBennett/FourREADME
four
Minimal three.js alternative.
Table of Contents
Installation
To install, use your preferred package manager or CDN:
npm install four@npm:fourwastaken
yarn add four@npm:fourwastaken
pnpm add four@npm:fourwastaken
<script type="module">
import * as FOUR from 'https://unpkg.com/fourwastaken'
</script>
Note: Vite may have issues consuming WebGPU code which relies on top-level await via ESM. This is well supported since 2021, but you may need to use vite-plugin-top-level-await to use this library with
vite.optimizeDeps.
Getting Started
The following creates a renderer, camera, and renders a red cube:
<details> <summary>Show WebGL example</summary>import { WebGLRenderer, PerspectiveCamera, Geometry, Material, Mesh } from 'four'
const renderer = new WebGLRenderer()
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.canvas)
const camera = new PerspectiveCamera(45, window.innerWidth / window.innerHeight)
camera.position.z = 5
const geometry = new Geometry({
position: {
size: 3,
data: new Float32Array([
0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, -0.5,
-0.5, -0.5, -0.5, -0.5, 0.5, 0.5, -0.5, -0.5, -0.5, -0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5, 0.5, -0.5, -0.5, 0.5,
0.5, 0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, -0.5, -0.5, -0.5, 0.5, -0.5, -0.5, -0.5, 0.5, -0.5,
0.5, -0.5, -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5, 0.5, -0.5,
-0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, -0.5, 0.5, -0.5, -0.5, -0.5, 0.5, -0.5, 0.5, -0.5, -0.5, -0.5,
-0.5, -0.5, -0.5, 0.5, -0.5,
]),
},
})
const material = new Material({
vertex: /* glsl */ `#version 300 es
uniform mat4 projectionMatrix;
uniform mat4 modelViewMatrix;
in vec3 position;
void main() {
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1);
}
`,
fragment: /* glsl */ `#version 300 es
out lowp vec4 color;
void main() {
color = vec4(1, 0, 0, 1);
}
`,
})
const mesh = new Mesh(geometry, material)
renderer.render(mesh, camera)
</details>
<details>
<summary>Show WebGPU example</summary>
import { WebGPURenderer, PerspectiveCamera, Geometry, Material, Mesh } from 'four'
const renderer = new WebGPURenderer()
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.canvas)
const camera = new PerspectiveCamera(45, window.innerWidth / window.innerHeight)
camera.position.z = 5
const geometry = new Geometry({
position: {
size: 3,
data: new Float32Array([
0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, -0.5,
-0.5, -0.5, -0.5, -0.5, 0.5, 0.5, -0.5, -0.5, -0.5, -0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5, 0.5, -0.5, -0.5, 0.5,
0.5, 0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, -0.5, -0.5, -0.5, 0.5, -0.5, -0.5, -0.5, 0.5, -0.5,
0.5, -0.5, -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5, 0.5, -0.5,
-0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, -0.5, 0.5, -0.5, -0.5, -0.5, 0.5, -0.5, 0.5, -0.5, -0.5, -0.5,
-0.5, -0.5, -0.5, 0.5, -0.5,
]),
},
})
const material = new Material({
vertex: /* wgsl */ `
struct Uniforms {
projectionMatrix: mat4x4<f32>,
modelViewMatrix: mat4x4<f32>,
};
@group(0) @binding(0) var<uniform> uniforms: Uniforms;
@vertex
fn main(@location(0) position: vec3<f32>) -> @builtin(position) vec4<f32> {
return uniforms.projectionMatrix * uniforms.modelViewMatrix * vec4(position, 1);
}
`,
fragment: /* wgsl */ `
@fragment
fn main() -> @location(0) vec4<f32> {
return vec4(1, 0, 0, 1);
}
`,
})
const mesh = new Mesh(geometry, material)
renderer.render(mesh, camera)
</details>
Object3D
An Object3D represents a basic 3D object and its transforms. Objects are linked via their parent and children properties, constructing a rooted scene-graph.
const object = new Object3D()
object.add(new Object3D(), new Object3D())
object.traverse((node) => {
if (node !== object) object.remove(node)
if (!node.visible) return true
})
Vector3
A Vector3 represents a three-dimensional (x, y, z) vector and describes local position in Object3D.position. It is also used to control local scale in Object3D.scale.
object.position.set(1, 2, 3)
object.position.x = 4
object.position[0] = 5
Quaternion
A Quaternion represents a four-dimensional vector with a rotation axis (x, y, z) and magnitude (w) and describes local orientation in Object3D.quaternion.
object.quaternion.set(0, 0, 0, 1)
object.quaternion.fromEuler(Math.PI / 2, 0, 0)
object.quaternion.x *= -1
object.quaternion[0] *= -1
Matrix4
A Matrix4 represents a 4x4 transformation matrix and describes world transforms in Object3D.matrix.
object.matrix.set(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 2, 3, 1)
object.matrix[12] = 4
object.matrix.invert()
object.matrix.identity()
Mesh
A Mesh contains a Geometry and Material to describe visual behavior, and can be manipulated in 3D as an Object3D.
const geometry = new Geometry({ ... })
const material = new Material({ ... })
const mesh = new Mesh(geometry, material)
Geometry
A Geometry contains an Attribute list of vertex or storage buffer data, with a GPU buffer allocated for each Attribute.
const geometry = new Geometry({
position: { size: 2, data: new Float32Array([-1, -1, 3, -1, -1, 3]) },
uv: { size: 2, data: new Float32Array([0, 0, 2, 0, 0, 2]) },
index: { size: 1, data: new Uint16Array([0, 1, 2]) },
})
A DrawRange can also be configured to control rendering without submitting vertex data. This is useful for GPU-computed geometry or vertex pulling, as demonstrated in the fullscreen demos.
const geometry = new Geometry()
geometry.drawRange = { start: 0, count: 3 } // renders 3 vertices at starting index 0
Attribute
An Attribute defines a data view, its per-vertex size, and an optional per-instance divisor (see instancing).
// Creates a 4x4 instance matrix for 2 instances
{
data: new Float32Array([
1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1,
1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1,
]),
size: 16,
divisor: 1,
}
Material
A Material describes a program or shader interface for rasterization and compute (see compute), defining a vertex and fragment or compute shader, respectively.
const material = new Material({
vertex: /* glsl */ `#version 300 es
uniform mat4 projectionMatrix;
uniform mat4 modelViewMatrix;
in vec3 position;
void main() {
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1);
}
`,
fragment: /* glsl */ `#version 300 es
out lowp vec4 color;
void main() {
color = vec4(1, 0, 0, 1);
}
`,
side: 'front',
transparent: false,
depthTest: true,
depthWrite: true,
})
</details>
<details>
<summary>Show WebGPU example</summary>
const material = new Material({
vertex: /* wgsl */ `
struct Uniforms {
projectionMatrix: mat4x4<f32>,
modelViewMatrix: mat4x4<f32>,
};
@group(0) @binding(0) var<uniform> uniforms: Uniforms;
@vertex
fn main(@location(0) position: vec3<f32>) -> @builtin(position) vec4<f32> {
return uniforms.projectionMatrix * uniforms.modelViewMatrix * vec4(position, 1);
}
`,
fragment: /* wgsl */ `
@fragment
fn main() -> @location(0) vec4<f32> {
return vec4(1, 0, 0, 1);
}
`,
side: 'front',
transparent: false,
depthTest: true,
depthWrite: true,
})
</details>
Uniforms
The following uniforms are built-in and will be automatically populated when specified:
| Type | Name | Description | Conversion |
| -------- | ---------------- | -------------------------------------------------- | -------------------------- |
| mat4x4 | modelMatrix | world-space mesh transform | local space => world space |
| mat4x4 | projectionMatrix | clip-space camera projection | view space => clip space |
| mat4x4 | viewMatrix | inverse camera transform | world space => view space |
| mat4x4 | modelViewMatrix | premultiplied model-view transform | local space => view space |
| mat4x4 | normalMatrix | isotropic inverse model-view or "normal" tra
Related Skills
node-connect
344.1kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
96.8kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
344.1kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
344.1kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
