Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
348 changes: 159 additions & 189 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,96 +1,191 @@
# GEngine.js

WebGPU Engine

## install
<p align="center">
<strong>A modern 3D rendering engine built on WebGPU</strong>
</p>

<p align="center">
<strong>English</strong> | <a href="./README.zh-CN.md">中文</a>
</p>

<p align="center">
<a href="https://www.npmjs.com/package/@gengine-js/gengine">
<img src="https://img.shields.io/npm/v/@gengine-js/gengine.svg" alt="npm version" />
</a>
<a href="https://github.com/hpugis/GEngine/blob/main/LICENSE">
<img src="https://img.shields.io/github/license/hpugis/GEngine" alt="license" />
</a>
<img src="https://img.shields.io/badge/WebGPU-required-blue" alt="WebGPU required" />
<img src="https://img.shields.io/badge/TypeScript-5+-3178c6?logo=typescript&logoColor=white" alt="TypeScript" />
</p>

---

## Features

- 🎨 **Forward Rendering Pipeline** — shadow pass + color pass + post-process chain
- 💡 **4 Light Types** — Ambient, Directional, Point, Spot, all with shadow support
- 🌊 **Cascaded Shadow Maps** — high-quality directional light shadows over large scenes
- 🔮 **3 Built-in Materials** — Blinn-Phong, PBR (with IBL), and fully custom ShaderMaterial
- 🧊 **Geometry Library** — Box, Plane, Sphere, TorusKnot, Point cloud, SkyBox
- 🚀 **Instance Rendering** — `InstanceMesh` for large numbers of identical objects
- ✨ **Bloom Post-Effect** — threshold-based bloom with multi-level blur
- 📦 **GLTF Loader** — meshes, materials, textures, skeletal animation
- ✂️ **Frustum Culling** — BoundingSphere / BoundingBox based culling
- ⚡ **Compute Shaders** — WebGPU compute pipeline support
- 🔧 **WGSL Preprocessor** — `#ifdef` / `#if` conditional shader compilation

## Requirements

| Requirement | Version |
|-------------|---------|
| Browser | Chrome ≥ 113 / Edge ≥ 113 |
| Node.js | ≥ 16 (for building) |

> WebGPU is enabled by default in Chrome 113+ and Edge 113+. Firefox and Safari require experimental flags.

## Installation

```shell
$ yarn add @gengine-js/gengine
npm install @gengine-js/gengine
# or
yarn add @gengine-js/gengine
```

## develop
## Quick Start

```shell
# install
$ yarn
```html
<!DOCTYPE html>
<html>
<body>
<div id="app" style="width:100vw;height:100vh;"></div>
<script type="module">
import {
Scene, Mesh, PerspectiveCamera,
BlinnPhongMaterial, SphereGeometry,
PointLight, AmbientLight,
Vector3, Color, OrbitControl
} from "@gengine-js/gengine";

// 1. Create scene (initializes WebGPU automatically)
const scene = new Scene({ container: "app" });

// 2. Camera
const camera = new PerspectiveCamera(
60, window.innerWidth / window.innerHeight, 0.01, 1000
);
camera.position.set(0, 20, 30);
camera.lookAt(0, 0, 0);
scene.setCamera(camera);

// 3. Mesh
const geometry = new SphereGeometry(10);
const material = new BlinnPhongMaterial();
material.color = new Color(1.0, 0.5, 0.0);
const mesh = new Mesh(geometry, material);
scene.add(mesh);

// 4. Lights
const light = new PointLight(new Vector3(1, 1, 1), 1.0, 100, 1.0);
light.position = new Vector3(0, 30, 0);
scene.add(light);
scene.add(new AmbientLight(new Vector3(0.2, 0.2, 0.2), 1.0));

// 5. Controls
const control = new OrbitControl(camera, document.getElementById("app"));

// 6. Render loop
function animate() {
requestAnimationFrame(animate);
control.update();
scene.render();
}
animate();

// 7. Handle resize
window.addEventListener("resize", () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
scene.resize(window.innerWidth, window.innerHeight);
});
</script>
</body>
</html>
```

# dev
$ yarn dev
## Development

# build
$ yarn build
```
```shell
# Clone
git clone https://github.com/hpugis/GEngine.git
cd GEngine

## Usage
# Install dependencies
yarn install

```html
<script type="module">
import {
Mesh,
PerspectiveCamera,
Scene,
PhongMaterial,
Vector3,
Color,
SpotLight,
PointLight,
SphereGeometry,
OrbitControl
} from "../dist/index.js";
const init = async () => {
const geometry = new SphereGeometry(10);
# Start dev server with watch
yarn dev

const phongMaterial = new PhongMaterial();
phongMaterial.color = new Color(1.0, 0.0, 0.0);
# Production build
yarn build

# Lint
yarn lint
```

const primitive = new Mesh(geometry, phongMaterial);
Serve the `example/` directory with any static file server to preview examples:

primitive.rotateX(-Math.PI / 2);
```shell
npx serve .
# then open http://localhost:3000/example/mesh/mesh.html
```

const camera = new PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.01, 1000);
## Documentation

camera.position.set(0, 20, 0);
| Doc | Description |
|-----|-------------|
| [Architecture](./ai-docs/ARCHITECTURE.md) | Render pipeline, data flow, class hierarchy |
| [API Reference](./ai-docs/API.md) | Full public API — Scene, Mesh, Material, Light, Camera, Math… |
| [Development Guide](./ai-docs/DEVELOPMENT.md) | Setup, adding new features, debugging tips |
| [Deployment](./ai-docs/DEPLOYMENT.md) | Build output, npm publishing |
| [Contributing](./ai-docs/CONTRIBUTING.md) | Branch naming, commit conventions, PR checklist |

camera.lookAt(0, 0, 0);
## Examples

const spotLight = new SpotLight(new Vector3(1.0, 1.0, 1.0), 1.0, 15, 6, 1);
spotLight.position = new Vector3(0, 20, 0);
Browse the [`example/`](./example/) directory for runnable demos:

const scene = new Scene({ container: "app" });
| Category | Examples |
|----------|----------|
| Geometry | Box, Plane, Sphere, TorusKnot |
| Materials | Blinn-Phong, PBR, ShaderMaterial |
| Lights | Ambient, Directional, Point, Spot |
| Shadows | Directional, Cascaded, Point, Spot |
| Mesh | Instance, Points, SkyBox, Sprite |
| Loaders | GLTF models, GLTF skinning |
| Effects | Bloom post-process |

axes.scale.set(10, 10, 10);
## Contributing

const control = new OrbitControl(camera, document.getElementById("app"));
Contributions are welcome! Please read the [Contributing Guide](./ai-docs/CONTRIBUTING.md) before submitting a pull request.

scene.add(primitive);
1. Fork the repository
2. Create your branch: `git checkout -b feat/your-feature`
3. Commit with conventional commits: `yarn commit`
4. Push and open a Pull Request

scene.setCamera(camera);
## License

scene.add(pointLight);
[MIT](./LICENSE)

window.addEventListener("resize", onWindowResize);
---

function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
scene.resize(window.innerWidth, window.innerHeight);
}
function animate() {
control.update();
requestAnimationFrame(animate);
scene.render();
}
animate();
};
init();
</script>
```
## Native WebGPU Usage

## Native
For advanced use cases requiring direct WebGPU access:

```html
<script type="module">
import { Model, Context, Texture, RenderTarget, Attachment } from "webgpu-gengine-js";
import { mat4, vec3 } from "gl-matrix";
import { Model, Context, Texture, RenderTarget, Attachment } from "@gengine-js/gengine";
const init = async () => {
//init context
const context = new Context({
Expand Down Expand Up @@ -118,135 +213,10 @@ $ yarn build
const depthAttachment = new Attachment(1.0, { texture: depthTexture });
//fbo
const canvasRenderTarget = new RenderTarget("render", [colorAttachment], depthAttachment);
const aspect = canvas.width / canvas.height;
const projectionMatrix = mat4.perspective([], (2 * Math.PI) / 5, aspect, 1, 100.0);
const modelViewProjectionMatrix = mat4.create();
const model = new Model({
shaderId: "model",
frag: `
@fragment
fn main(@location(0) fragPosition: vec4<f32>) -> @location(0) vec4<f32> {
return fragPosition;
}
`,
vert: `
struct Uniforms {
modelViewProjectionMatrix : mat4x4<f32>,
}
@binding(0) @group(0) var<uniform> uniforms : Uniforms;
struct VertexOutput {
@builtin(position) Position : vec4<f32>,
@location(0) fragPosition: vec4<f32>,
}
@vertex
fn main(@location(0) position : vec4<f32>,@location(1) color : vec4<f32>) -> VertexOutput {
var output : VertexOutput;
output.Position = uniforms.modelViewProjectionMatrix * position;
output.fragPosition = 0.5 * (position + vec4(1.0, 1.0, 1.0, 1.0));
return output;
}
`,
vertexBuffers: [
{
stepMode: "vertex", //optional
uid: "vertAttr", //must
attributes: {
position: { size: 4, value: positions },
color: { size: 4, value: colors }
}
}
],
uniformBuffers: [
{
type: "uniform",
uid: "systemMatrix",
uniforms: {
modelViewProjectionMatrix: {
type: "mat4",
value: () => {
let viewMatrix = mat4.identity([]);
mat4.translate(viewMatrix, viewMatrix, vec3.fromValues(0, 0, -4));
const now = Date.now() / 1000;
mat4.rotate(
viewMatrix,
viewMatrix,
1,
vec3.fromValues(Math.sin(now), Math.cos(now), 0)
);
mat4.multiply(modelViewProjectionMatrix, projectionMatrix, viewMatrix);
return modelViewProjectionMatrix;
}
}
}
}
],
renderState: {
targets: [
{
format: presentationFormat
}
],
primitive: {
topology: "triangle-list",
cullMode: "back"
},
depthStencil: {
depthWriteEnabled: true,
depthCompare: "less",
format: "depth24plus"
}
},
draw: {
count: 36,
instanceCount: 1
}
});

function animate() {
requestAnimationFrame(animate);
const passEncoder = canvasRenderTarget.beginRenderPass(context.device);
model.render({ device: context.device, passEncoder });
canvasRenderTarget.endRenderPass();
}
animate();
// ... build pipeline, draw loop, etc.
};
init();
</script>
```

## feature

- [✔] Camera
- [✔] PerspectiveCamera
- [✔] OrthographicCamera
- [✔] Math
- [✔] control
- [✔] OrbitControl
- [✔] Light
- [✔] AmbientLight
- [✔] DirectionalLight
- [✔] PointLight
- [✔] SpotLight
- [✔] Loader
- [✔] GLTFLoader
- [✔] CubeTextureLoader
- [✔] Materials
- [✔] ColorMaterial
- [✔] Material
- [✔] PbrMaterial(IBL/Light Render)
- [✔] BlinPhongMaterial
- [✔] ShaderMaterial
- [✔] SkyBoxMaterial
- [✔] Post-Effect
- [✔] BloomPostEffect
- [✔] Shadow
- [✔] DirectionalLightShadow
- [✔] PointLightShadow
- [✔] SpotLightShadow

## Next

1. Complete animation
2. Complete core glTF 2.0
3. Text and Sprite
4. Pick
Loading