hilo3d 2.0.0-alpha.2 → 2.0.0-alpha.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +371 -13
- package/README.md +179 -271
- package/README_ZH.md +173 -250
- package/dist/Hilo3d.d.ts +3436 -911
- package/dist/Hilo3d.d.ts.map +1 -1
- package/dist/Hilo3d.js +47300 -24219
- package/dist/Hilo3d.js.map +1 -1
- package/dist/{web_naga-D4FbPGzE.js → web_naga-B71-0Gwu.js} +2 -2
- package/dist/{web_naga-D4FbPGzE.js.map → web_naga-B71-0Gwu.js.map} +1 -1
- package/package.json +7 -4
package/README.md
CHANGED
|
@@ -1,27 +1,51 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
1
|
+
<div align="center">
|
|
2
|
+
<img src="./website/assets/hilo3d-logo.png" width="320" alt="Hilo3D" />
|
|
3
|
+
|
|
4
|
+
<p><strong>A modern Web graphics engine for production 2D and 3D experiences.</strong></p>
|
|
5
|
+
|
|
6
|
+
<p>
|
|
7
|
+
A portable RHI, validated Render Graph, and Scriptable Render Pipeline<br />
|
|
8
|
+
power one shared renderer for WebGPU and WebGL 2.
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
<p>
|
|
12
|
+
<a href="https://hilo3d.js.org/"><strong>Website</strong></a> ·
|
|
13
|
+
<a href="https://hilo3d.js.org/examples/list.html">Examples</a> ·
|
|
14
|
+
<a href="https://hilo3d.js.org/docs/">Documentation</a> ·
|
|
15
|
+
<a href="https://hilo3d.js.org/docs/modules/Hilo3d.html">API</a> ·
|
|
16
|
+
<a href="./README_ZH.md">简体中文</a>
|
|
17
|
+
</p>
|
|
18
|
+
|
|
19
|
+
<p>
|
|
20
|
+
<a href="https://www.npmjs.com/package/hilo3d"><img src="https://img.shields.io/npm/v/hilo3d.svg?style=flat-square" alt="npm version" /></a>
|
|
21
|
+
<a href="https://github.com/hiloteam/Hilo3d/actions/workflows/npm_test.yml"><img src="https://img.shields.io/github/actions/workflow/status/hiloteam/Hilo3d/npm_test.yml?style=flat-square" alt="CI status" /></a>
|
|
22
|
+
<a href="https://github.com/hiloteam/Hilo3d/blob/dev/LICENSE"><img src="https://img.shields.io/npm/l/hilo3d.svg?style=flat-square" alt="MIT license" /></a>
|
|
23
|
+
</p>
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
> Hilo3D 2.0 is currently in alpha. Existing projects should review the
|
|
27
|
+
> [breaking changes](./CHANGELOG.md#breaking-changes) before upgrading.
|
|
28
|
+
|
|
29
|
+
## Why Hilo3D
|
|
30
|
+
|
|
31
|
+
Hilo3D keeps high-level scene authoring and low-level GPU control in the same engine. Applications
|
|
32
|
+
use one scene, material, render-target, and shader contract while the renderer selects a native
|
|
33
|
+
WebGPU path or a production WebGL 2 compatibility path.
|
|
34
|
+
|
|
35
|
+
- **One renderer, two backends** — `auto` prefers compatible WebGPU and uses WebGL 2 when WebGPU is
|
|
36
|
+
unavailable. Explicit backend requests never change silently.
|
|
37
|
+
- **Modern materials and output** — glTF 2.0, layered PBR, HDR lighting, Bloom, automatic exposure,
|
|
38
|
+
filmic tone mapping, transmission, volume, iridescence, clearcoat, and anisotropy.
|
|
39
|
+
- **2D and 3D together** — scene graph, meshes, animation, cameras, lights, shadows, sprites, text,
|
|
40
|
+
batching, picking, and layered multi-camera composition.
|
|
41
|
+
- **GPU-driven rendering** — instancing and multi-pass rendering across both backends, plus a WebGPU
|
|
42
|
+
high-end profile with GPU Scene culling/LOD, Hi-Z, indirect buckets, and Clustered Forward+.
|
|
43
|
+
- **Stable high-end lighting** — TAA/TAAU, dynamic resolution, GTAO, SSR, SSGI, froxel volumetrics,
|
|
44
|
+
physical atmosphere, temporal clouds, cloud shadows, and eye adaptation.
|
|
45
|
+
- **A frame you can shape** — a validated Render Graph and scriptable render pipeline coordinate
|
|
46
|
+
shadows, scene passes, post-processing, render targets, readback, and presentation.
|
|
47
|
+
- **Production lifecycle** — bounded GPU caches, incremental uploads, explicit resource ownership,
|
|
48
|
+
and recovery from WebGPU device loss or WebGL context loss.
|
|
25
49
|
|
|
26
50
|
## Install
|
|
27
51
|
|
|
@@ -29,32 +53,39 @@ immediate, state-cached GL execution.
|
|
|
29
53
|
npm install hilo3d
|
|
30
54
|
```
|
|
31
55
|
|
|
32
|
-
|
|
33
|
-
|
|
56
|
+
Hilo3D is ESM-only. It targets modern browsers with WebGPU or WebGL 2; WebGL 1 and legacy global
|
|
57
|
+
builds are outside the 2.0 contract.
|
|
58
|
+
|
|
59
|
+
## Build games with Codex
|
|
34
60
|
|
|
35
|
-
|
|
61
|
+
The standalone
|
|
62
|
+
[`hilo3d-game` Agent Skill](https://github.com/hiloteam/Hilo3d/tree/dev/skills/hilo3d-game) helps
|
|
63
|
+
Codex plan, scaffold, implement, debug, and optimize Hilo3D 2D, 3D, and hybrid browser games. It
|
|
64
|
+
uses the published `hilo3d` package and is kept outside `.agents/skills` so it is distributed from
|
|
65
|
+
this repository without becoming guidance for contributors working on the engine itself.
|
|
36
66
|
|
|
37
|
-
|
|
38
|
-
available, and waits for the selected backend to become ready. The returned stage is ready to
|
|
39
|
-
render.
|
|
67
|
+
## Create your first scene
|
|
40
68
|
|
|
41
69
|
```ts
|
|
42
70
|
import * as Hilo3d from 'hilo3d';
|
|
43
71
|
|
|
44
|
-
const camera = new Hilo3d.PerspectiveCamera({
|
|
72
|
+
const camera = new Hilo3d.PerspectiveCamera({
|
|
73
|
+
aspect: innerWidth / innerHeight,
|
|
74
|
+
z: 4
|
|
75
|
+
});
|
|
45
76
|
|
|
46
77
|
const stage = await Hilo3d.Stage.create({
|
|
47
|
-
backend: '
|
|
78
|
+
backend: 'auto',
|
|
48
79
|
container: document.querySelector('#app')!,
|
|
49
80
|
camera,
|
|
50
81
|
width: innerWidth,
|
|
51
82
|
height: innerHeight
|
|
52
83
|
});
|
|
53
84
|
|
|
54
|
-
|
|
85
|
+
new Hilo3d.Mesh({
|
|
55
86
|
geometry: new Hilo3d.BoxGeometry(),
|
|
56
87
|
material: new Hilo3d.PBRMaterial({
|
|
57
|
-
baseColor: new Hilo3d.Color(0.
|
|
88
|
+
baseColor: new Hilo3d.Color(0.83, 0.12, 0.09)
|
|
58
89
|
})
|
|
59
90
|
}).addTo(stage);
|
|
60
91
|
|
|
@@ -65,256 +96,133 @@ ticker.addTick(stage);
|
|
|
65
96
|
ticker.start();
|
|
66
97
|
```
|
|
67
98
|
|
|
68
|
-
|
|
69
|
-
`
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
99
|
+
`Stage.create()` is asynchronous because backend selection and GPU initialization are asynchronous.
|
|
100
|
+
Use `backend: 'webgpu'` or `backend: 'webgl2'` when an application requires a specific backend.
|
|
101
|
+
|
|
102
|
+
## See the engine in motion
|
|
103
|
+
|
|
104
|
+
<table>
|
|
105
|
+
<tr>
|
|
106
|
+
<td width="33.33%"><a href="https://hilo3d.js.org/examples/bloom.html?backend=webgpu"><img src="./website/assets/example-bloom.webp" alt="HDR Bloom example" /></a></td>
|
|
107
|
+
<td width="33.33%"><a href="https://hilo3d.js.org/examples/gltf_material_extensions.html"><img src="./website/assets/example-gltf-materials.webp" alt="glTF material extensions example" /></a></td>
|
|
108
|
+
<td width="33.33%"><a href="https://hilo3d.js.org/examples/compute_raytracing.html?backend=webgpu"><img src="./website/assets/example-compute-raytracing.webp" alt="Compute path tracing example" /></a></td>
|
|
109
|
+
</tr>
|
|
110
|
+
<tr>
|
|
111
|
+
<td><strong>HDR Bloom</strong><br />Compute-driven light shaped through the engine post-processing pipeline.</td>
|
|
112
|
+
<td><strong>glTF material extensions</strong><br />Layered Khronos assets on the shared WebGPU and WebGL 2 renderer.</td>
|
|
113
|
+
<td><strong>Compute path tracing</strong><br />Progressive WebGPU tracing with denoising, caustics, and HDR output.</td>
|
|
114
|
+
</tr>
|
|
115
|
+
</table>
|
|
116
|
+
|
|
117
|
+
[Browse the complete example gallery →](https://hilo3d.js.org/examples/list.html)
|
|
118
|
+
|
|
119
|
+
## Modern rendering stack
|
|
120
|
+
|
|
121
|
+
The opt-in WebGPU high-end profile is built on the same Scene, Material, Render Graph, and RHI
|
|
122
|
+
contracts as the portable renderer. Unsupported devices fail capability checks before the runtime is
|
|
123
|
+
created; compatible meshes that are outside the native GPU Scene slice remain on the shared Forward
|
|
124
|
+
path and compose into the same linear HDR frame.
|
|
125
|
+
|
|
126
|
+
| System | Current production slice |
|
|
127
|
+
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
|
|
128
|
+
| GPU Scene | Dirty object/material databases, previous-frame Hi-Z occlusion, projected-radius LOD, compact visible ranges, and fixed indirect buckets |
|
|
129
|
+
| Clustered Forward+ | Depth-driven 3D clusters, bounded deterministic light allocation, storage PBR, shared directional/spot/point shadows, and LTC area lights |
|
|
130
|
+
| Temporal rendering | Motion vectors, authored reactive masks, native TAA, 0.5–1.0 TAAU, and timestamp-driven dynamic resolution |
|
|
131
|
+
| Screen-space lighting | Portable GTAO and SSGI on WebGPU/WebGL 2, plus WebGPU Clustered hierarchical SSR |
|
|
132
|
+
| Volumetrics and weather | Froxel height/local fog, directional/point/spot injection, physical atmosphere LUTs, temporal clouds, and cloud shadows |
|
|
133
|
+
| HDR display | GPU histogram exposure, asymmetric eye adaptation, Bloom, and configurable filmic display transforms |
|
|
134
|
+
|
|
135
|
+
Explore the
|
|
136
|
+
[Clustered Sponza lab](https://hilo3d.js.org/examples/clustered_forward_plus_sponza.html),
|
|
137
|
+
[Temporal Observatory](https://hilo3d.js.org/examples/temporal_aa_observatory.html),
|
|
138
|
+
[Silent Dragon GTAO](https://hilo3d.js.org/examples/ground_truth_ambient_occlusion.html),
|
|
139
|
+
[Afterimage SSR](https://hilo3d.js.org/examples/screen_space_reflections_palace.html),
|
|
140
|
+
[Prismatic Vespers SSGI](https://hilo3d.js.org/examples/screen_space_global_illumination_chapel.html),
|
|
141
|
+
[Neon Reliquary volumetrics](https://hilo3d.js.org/examples/volumetric_neon_reliquary.html), and
|
|
142
|
+
[Stormfront Observatory](https://hilo3d.js.org/examples/stormfront_observatory.html).
|
|
143
|
+
|
|
144
|
+
See the [modern WebGPU rendering roadmap](./documentation/MODERN_WEBGPU_RENDERING_ROADMAP.md) for
|
|
145
|
+
the exact completed boundaries, remaining compatibility paths, and future streaming/virtualization
|
|
146
|
+
work.
|
|
147
|
+
|
|
148
|
+
## Rendering profiles
|
|
149
|
+
|
|
150
|
+
| | Portable profile | WebGPU high-end profile |
|
|
151
|
+
| -------------------- | ------------------------------------------------------------- | ---------------------------------------------------------------------------- |
|
|
152
|
+
| Backend | WebGPU and WebGL 2 | WebGPU |
|
|
153
|
+
| Scene and materials | Shared scene graph, PBR materials, glTF, sprites, text | The same public model with registered PBR buckets and Forward fallback |
|
|
154
|
+
| Frame composition | Render Graph, render targets, MRT, MSAA, post-processing | The same graph with GPU Scene, clustered lighting, and native compute |
|
|
155
|
+
| Lighting and quality | Forward PBR, shadows, GTAO, SSGI, TAA/TAAU, Bloom, Color Uber | Adds Hi-Z SSR, dynamic resolution, froxels, atmosphere/clouds, auto exposure |
|
|
156
|
+
| GPU workloads | Instancing, uniform buffers, incremental resource uploads | Compute, storage buffers/textures, indirect GPU workflows |
|
|
157
|
+
| Shader path | Authored GLSL ES 3.00 | Raster GLSL → Naga → WGSL; validated direct WGSL compute |
|
|
158
|
+
| Recovery | WebGL context restoration or WebGPU resource rebuild | WebGPU device reacquisition with submission-aware history rebuild |
|
|
159
|
+
|
|
160
|
+
Unsupported WebGPU-only features fail capability checks on WebGL 2 instead of being partially
|
|
161
|
+
emulated.
|
|
162
|
+
|
|
163
|
+
## Architecture at a glance
|
|
164
|
+
|
|
165
|
+
```text
|
|
166
|
+
Scene · Materials · 2D · Animation · Lights
|
|
167
|
+
│
|
|
168
|
+
Shared Renderer
|
|
169
|
+
│
|
|
170
|
+
Render Graph · Scriptable Render Pipeline
|
|
171
|
+
│
|
|
172
|
+
Portable RHI
|
|
173
|
+
┌─────┴─────┐
|
|
174
|
+
WebGPU WebGL 2
|
|
88
175
|
```
|
|
89
176
|
|
|
90
|
-
|
|
177
|
+
The shared renderer owns scene collection, culling, sorting, instancing, shadows, post-processing,
|
|
178
|
+
draw preparation, and resource coordination. Production frames flow through the Render Graph and
|
|
179
|
+
portable RHI; backend code remains responsible only for native API execution.
|
|
91
180
|
|
|
92
|
-
|
|
181
|
+
Raster shaders have one GLSL ES 3.00 source of truth. WebGL 2 compiles that source directly, while
|
|
182
|
+
the WebGPU path preprocesses it for Naga and produces WGSL. WebGPU-only compute uses the engine's
|
|
183
|
+
validated `ComputeShader` contract.
|
|
93
184
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
backend: 'webgl2',
|
|
97
|
-
container: document.querySelector('#app')!,
|
|
98
|
-
camera
|
|
99
|
-
});
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
`Stage` is created only through the asynchronous `Stage.create()` factory, including when WebGL 2 is
|
|
103
|
-
selected explicitly. Hilo3d never creates a WebGL 1 context.
|
|
104
|
-
|
|
105
|
-
## Creating a renderer directly
|
|
106
|
-
|
|
107
|
-
`Renderer` is the only public renderer class and is created exclusively through the asynchronous
|
|
108
|
-
`Renderer.create()` factory:
|
|
109
|
-
|
|
110
|
-
```ts
|
|
111
|
-
const webglRenderer = await Hilo3d.Renderer.create({
|
|
112
|
-
backend: 'webgl2',
|
|
113
|
-
domElement: document.querySelector('canvas')!
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
const autoRenderer = await Hilo3d.Renderer.create({
|
|
117
|
-
backend: 'auto',
|
|
118
|
-
domElement: document.createElement('canvas')
|
|
119
|
-
});
|
|
185
|
+
Read the [rendering architecture](./documentation/RENDERING_ARCHITECTURE.md) for the complete frame,
|
|
186
|
+
resource, shader, and recovery contracts.
|
|
120
187
|
|
|
121
|
-
|
|
122
|
-
backend: 'webgpu',
|
|
123
|
-
domElement: document.createElement('canvas')
|
|
124
|
-
});
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
Every renderer creates the same public `RenderTarget` contract. Backend selection is observable
|
|
128
|
-
through `renderer.backend`; it does not change the scene, material, target, or shader API.
|
|
129
|
-
|
|
130
|
-
## Capability matrix
|
|
131
|
-
|
|
132
|
-
| Capability | WebGPU | WebGL 2 |
|
|
133
|
-
| ------------------------ | ------------------------------------------------------------- | -------------------------------------------------------------- |
|
|
134
|
-
| RHI execution | Thin native encoder/pass/queue mapping | Immediate GL execution behind encoder/pass semantics |
|
|
135
|
-
| Shader module input | Renderer-prepared WGSL | Renderer-prepared GLSL ES 3.00 |
|
|
136
|
-
| Multi-pass `renderFrame` | One encoder/submit for resource-ready renderer passes | Ordered immediate execution; submit never replays commands |
|
|
137
|
-
| Device-object reuse | Bounded pipeline, layout, and sampler caches | Bounded pipeline, layout, sampler, framebuffer, and VAO caches |
|
|
138
|
-
| Incremental uploads | UBO/geometry dirty ranges; texture revisions | UBO/geometry dirty ranges; texture revisions |
|
|
139
|
-
| Render targets | MRT, 1×/4× MSAA, sampled attachments, async readback | Same engine contract |
|
|
140
|
-
| Unsupported RHI features | Reported through `features`/`limits`; rejected when requested | Compute/storage/1D/async buffer mapping report unsupported |
|
|
141
|
-
| Loss handling | Device reacquisition and resource recovery | Context restoration and resource recovery |
|
|
142
|
-
| Backend selection | Explicit requests reject; `auto` uses an adapter-only probe | Selected directly when the `auto` probe is unsupported |
|
|
188
|
+
## Documentation
|
|
143
189
|
|
|
144
|
-
|
|
190
|
+
- [Getting started and API documentation](https://hilo3d.js.org/docs/)
|
|
191
|
+
- [Example gallery](https://hilo3d.js.org/examples/list.html)
|
|
192
|
+
- [`hilo3d-game` Agent Skill](https://github.com/hiloteam/Hilo3d/tree/dev/skills/hilo3d-game)
|
|
193
|
+
- [Engineering documentation index](./documentation/README.md)
|
|
194
|
+
- [Rendering architecture](./documentation/RENDERING_ARCHITECTURE.md)
|
|
195
|
+
- [PBR, HDR, and post-processing](./documentation/PBR_AND_POST_PROCESSING.md)
|
|
196
|
+
- [Modern WebGPU rendering roadmap](./documentation/MODERN_WEBGPU_RENDERING_ROADMAP.md)
|
|
197
|
+
- [Material system modernization](./documentation/MATERIAL_SYSTEM_MODERNIZATION.md)
|
|
198
|
+
- [Temporal rendering](./documentation/TEMPORAL_RENDERING_REMEDIATION.md)
|
|
199
|
+
- [Screen-space global illumination](./documentation/SCREEN_SPACE_GLOBAL_ILLUMINATION.md)
|
|
200
|
+
- [Froxel volumetric lighting](./documentation/VOLUMETRIC_LIGHTING.md)
|
|
201
|
+
- [Physical atmosphere and weather](./documentation/PHYSICAL_ATMOSPHERE_AND_WEATHER.md)
|
|
202
|
+
- [2D rendering and multi-camera composition](./documentation/2D_RENDERING.md)
|
|
203
|
+
- [Scriptable render pipeline](./documentation/SCRIPTABLE_RENDER_PIPELINE_PLAN.md)
|
|
204
|
+
- [Breaking changes](./CHANGELOG.md#breaking-changes)
|
|
145
205
|
|
|
146
|
-
|
|
147
|
-
and present calls in the callback share one application command encoder and finish with at most one
|
|
148
|
-
application submission. WebGL 2 executes the same commands in order through the same backend-neutral
|
|
149
|
-
facade.
|
|
206
|
+
## Develop locally
|
|
150
207
|
|
|
151
|
-
|
|
152
|
-
const reflectionTarget = renderer.createRenderTarget({
|
|
153
|
-
width: renderer.width,
|
|
154
|
-
height: renderer.height
|
|
155
|
-
});
|
|
156
|
-
const sceneTarget = renderer.createRenderTarget({ width: renderer.width, height: renderer.height });
|
|
208
|
+
Requires Node.js 20.19.0 or newer and the npm version declared by the repository.
|
|
157
209
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
frame.present(sceneTarget);
|
|
162
|
-
});
|
|
210
|
+
```sh
|
|
211
|
+
npm ci
|
|
212
|
+
npm run dev
|
|
163
213
|
```
|
|
164
214
|
|
|
165
|
-
|
|
166
|
-
custom tick instead of also letting `Stage` perform its default render. The callback is synchronous:
|
|
167
|
-
do not return a Promise or retain its `frame` facade. Settle scene transforms, material values,
|
|
168
|
-
`GeometryData`, and texture updates before entering it; geometry and texture content cannot change
|
|
169
|
-
after first use in the same frame. Cold texture mipmap preparation and explicit readback are
|
|
170
|
-
separate GPU work and are not counted as application-pass submission. Run renderer
|
|
171
|
-
resize/`setRenderTarget()`/resource release/destruction and render-target
|
|
172
|
-
resize/readback/destruction outside the callback; attempting those operations while WebGPU is
|
|
173
|
-
recording aborts the entire frame and prevents a partial submission.
|
|
174
|
-
|
|
175
|
-
## Scriptable render pipelines
|
|
176
|
-
|
|
177
|
-
Pass a reusable `renderPipeline` factory to `Renderer.create()` or `Stage.create()` to replace frame
|
|
178
|
-
composition, or use `ForwardRenderPipelineFactory` features to inject work around shadows, opaque,
|
|
179
|
-
transparent, post-process, and output stages. Each Renderer receives independent pipeline and
|
|
180
|
-
feature runtimes; recording stays synchronous and writes into the same transactional Render Graph as
|
|
181
|
-
ordinary renderer commands. The empty default feature set keeps the original direct forward path,
|
|
182
|
-
without an intermediate scene target or an extra present pass.
|
|
183
|
-
|
|
184
|
-
Graph sampling and texture copies use distinct declarations: fullscreen inputs must be
|
|
185
|
-
linear-filterable, while copy passes declare an exact source/destination pair and validate the
|
|
186
|
-
resolved RHI textures before a backend frame begins.
|
|
187
|
-
|
|
188
|
-
The [scriptable pipeline example](https://hilo3d.js.org/examples/scriptable_pipeline.html) samples
|
|
189
|
-
scene color through a retained fullscreen feature. The
|
|
190
|
-
[SRP architecture document](./documentation/SCRIPTABLE_RENDER_PIPELINE_PLAN.md) covers ownership,
|
|
191
|
-
failure handling, performance gates, and the capability-gated route to storage buffers and compute.
|
|
192
|
-
Those compute/storage capability names are currently fail-closed rather than partially emulated on
|
|
193
|
-
WebGL 2.
|
|
194
|
-
|
|
195
|
-
## Modern renderer architecture
|
|
196
|
-
|
|
197
|
-
- `src/render` owns the single public Renderer, scene traversal, frame planning, render-target
|
|
198
|
-
contracts, std140 uniform data, shader-interface preparation, and deterministic engine-resource
|
|
199
|
-
ownership.
|
|
200
|
-
- `src/shader` owns authored GLSL preprocessing and engine shader variants; `src/render/shader`
|
|
201
|
-
reflects bindings and performs GLSL-to-WGSL compilation. RHI code never knows what a shader
|
|
202
|
-
variant or material is.
|
|
203
|
-
- `src/render/rhi/RHI.ts` defines the portable WebGPU-shaped device, resource, pipeline, bind-group,
|
|
204
|
-
render-pass, encoder, queue, surface, feature, and limit contracts.
|
|
205
|
-
- `src/render/rhi/RHIFactory.ts` is the single hardware composition root. It constructs one concrete
|
|
206
|
-
RHI and owns backend support probes; it does not wrap that RHI in a per-command facade.
|
|
207
|
-
- `src/render/rhi/backends/webgpu` directly wraps native WebGPU. `src/render/rhi/backends/webgl2`
|
|
208
|
-
contains the WebGL 2 emulation, state cache, framebuffer/VAO ownership, and context recovery.
|
|
209
|
-
Neither RHI backend imports engine scene types.
|
|
210
|
-
- Backend-specific preparation and native execution remain internal implementation details; there
|
|
211
|
-
are no backend-specific public Renderer or RenderTarget classes. The internal Renderer factory
|
|
212
|
-
selects a concrete driver once during construction and returns it directly.
|
|
213
|
-
|
|
214
|
-
The abstraction boundary intentionally follows WebGPU rather than the WebGL state machine. A WebGPU
|
|
215
|
-
render pass maps one-for-one to its native pass, and a WebGPU command encoder owns the native
|
|
216
|
-
encoder directly. WebGL2RHI applies pipeline and bind-group state only when it changes and executes
|
|
217
|
-
draw/copy commands during encoding; the returned command buffer is a single-use submission token.
|
|
218
|
-
Production WebGPU paths use one-hop native fast paths on that same concrete device, so the main draw
|
|
219
|
-
loop keeps native handles and pays no per-draw wrapper or virtual-dispatch cost. The WebGL 2 path
|
|
220
|
-
runs its Program/VAO work in a frame-scoped session backed by the RHI's single context, canonical
|
|
221
|
-
state differential, lifecycle, and device-owned sampler cache. Program, VAO, and framebuffer caches
|
|
222
|
-
remain render-layer caches; it never creates a parallel context or a replayable command list.
|
|
223
|
-
Capabilities that do not have a sound WebGL 2 implementation—including compute pipelines, storage
|
|
224
|
-
textures, storage buffers, 1D textures, asynchronous buffer mapping, base-vertex draws, and
|
|
225
|
-
first-instance draws—are absent from its `features` or exposed as zero limits and fail explicitly
|
|
226
|
-
when requested. Inside the RHI contract, per-format sampling, filtering, attachment, storage, and
|
|
227
|
-
MSAA support is reported conservatively, including extension/tier-dependent differences.
|
|
228
|
-
|
|
229
|
-
Every engine shader starts as GLSL ES 3.00. WebGL 2 compiles it directly. WebGPU resolves the shader
|
|
230
|
-
variant, rewrites its active interface to Vulkan GLSL 4.50, and passes it through the Naga WASM
|
|
231
|
-
frontend to produce WGSL. Engine utility passes use the same path; there is no handwritten fallback
|
|
232
|
-
WGSL shader set.
|
|
233
|
-
|
|
234
|
-
Shader variants use a structured, type- and length-delimited dual-lane 64-bit hash without an
|
|
235
|
-
intermediate serialized key. Exact fields are retained for collision checks, so a collision receives
|
|
236
|
-
a deterministic bucket key instead of aliasing another shader. Cache ownership is deliberately
|
|
237
|
-
single-layered: each RHI device owns bounded immutable sampler, bind-group-layout, pipeline-layout,
|
|
238
|
-
and render-pipeline caches; the Renderer owns material, Mesh, shader-variant, binding-set, and
|
|
239
|
-
upload revision caches. Buffers, textures, shader modules, and bind groups are never
|
|
240
|
-
descriptor-deduplicated by the RHI because their identity and lifetime are application data. Labels
|
|
241
|
-
do not participate in device cache keys. Device loss/context restoration and explicit destruction
|
|
242
|
-
clear every device cache.
|
|
243
|
-
|
|
244
|
-
Texture identity is backend-neutral: the shared object stores CPU content, immutable update
|
|
245
|
-
snapshots, and monotonic revisions only. Each WebGL context and WebGPU device owns its native
|
|
246
|
-
allocations and upload cursor. WebGL descriptor snapshots preserve stable native objects across
|
|
247
|
-
framebuffer resize/reset; WebGPU defers destruction of buffers and textures referenced by a pending
|
|
248
|
-
submission. Internal lifecycle observers release every backend allocation before cancellable public
|
|
249
|
-
events run, including device/context loss and explicit resource release. WebGL sampler variants are
|
|
250
|
-
immutable, bounded, and bound per texture unit, so one depth texture can be read numerically and
|
|
251
|
-
through a comparison sampler in the same draw without mutating global texture state.
|
|
252
|
-
|
|
253
|
-
Render-target owners track attachment allocation generations on both backends. Texture target
|
|
254
|
-
changes, failed uploads, and explicit attachment destruction invalidate the previous allocation; the
|
|
255
|
-
target rebuilds or reattaches before reuse and rejects stale native handles.
|
|
256
|
-
|
|
257
|
-
Uniform buffers, dynamic geometry, and textures carry backend-local revisions. Both backends upload
|
|
258
|
-
only merged UBO and geometry dirty ranges when allocation shape is stable, while textures replay
|
|
259
|
-
immutable subresource-update snapshots from the required revision. WebGPU command-state caching also
|
|
260
|
-
suppresses repeated pipeline, bind-group, vertex/index buffer, viewport, and stencil commands within
|
|
261
|
-
a pass.
|
|
262
|
-
|
|
263
|
-
## Custom GLSL and UBO contract
|
|
264
|
-
|
|
265
|
-
Numeric shader data belongs in registered std140 blocks. Samplers are the only uniforms allowed
|
|
266
|
-
outside blocks.
|
|
215
|
+
Useful commands:
|
|
267
216
|
|
|
268
|
-
```
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
});
|
|
274
|
-
|
|
275
|
-
const material = new Hilo3d.ShaderMaterial({
|
|
276
|
-
attributes: { a_position: 'POSITION' },
|
|
277
|
-
uniformBlocks: { EffectBlock: effectBlock },
|
|
278
|
-
vs: `#version 300 es
|
|
279
|
-
layout(std140) uniform EffectBlock { vec4 tint; };
|
|
280
|
-
in vec3 a_position; out vec4 v_tint;
|
|
281
|
-
void main() { v_tint = tint; gl_Position = vec4(a_position, 1.0); }`,
|
|
282
|
-
fs: `#version 300 es
|
|
283
|
-
precision highp float;
|
|
284
|
-
in vec4 v_tint; layout(location = 0) out vec4 outColor;
|
|
285
|
-
void main() { outColor = v_tint; }`
|
|
286
|
-
});
|
|
287
|
-
|
|
288
|
-
effectBlock.set('tint', [1, 0.5, 0.2, 1]);
|
|
217
|
+
```sh
|
|
218
|
+
npm run examples:dev # run the example gallery locally
|
|
219
|
+
npm run typecheck # check maintained TypeScript
|
|
220
|
+
npm run test # run the test suite
|
|
221
|
+
npm run validate # run the full release validation
|
|
289
222
|
```
|
|
290
223
|
|
|
291
|
-
|
|
292
|
-
use, keep same-name block layouts identical across stages, and use flat schemas of scalars, vectors,
|
|
293
|
-
matrices, or fixed arrays.
|
|
294
|
-
|
|
295
|
-
## Device and resource lifecycle
|
|
224
|
+
See the [contributing guide](./.github/CONTRIBUTING.md) before opening a pull request.
|
|
296
225
|
|
|
297
|
-
|
|
298
|
-
requirements, revalidates features and limits, rebuilds device-owned managers and caches, restores
|
|
299
|
-
render-target resources without changing their public object identity, and emits
|
|
300
|
-
`webgpuDeviceRestored`. Frames are skipped while recovery is active. Terminal recovery emits
|
|
301
|
-
`webgpuDeviceRecoveryFailed`; later renders throw that error and the renderer never switches to
|
|
302
|
-
WebGL 2. `releaseGPUResources()` clears owned GPU state while leaving the renderer reusable.
|
|
226
|
+
## License
|
|
303
227
|
|
|
304
|
-
|
|
305
|
-
Native interoperability is opt-in through `renderer.getExtension('webgl2-native')` or
|
|
306
|
-
`renderer.getExtension('webgpu-native')`; native contexts and devices are not fields on the public
|
|
307
|
-
Renderer. Always capability-check an extension before using it, and keep normal rendering on the
|
|
308
|
-
shared Renderer/RenderTarget API.
|
|
309
|
-
|
|
310
|
-
## Documentation
|
|
311
|
-
|
|
312
|
-
- [API documentation](https://hilo3d.js.org/docs/)
|
|
313
|
-
- [Example gallery](https://hilo3d.js.org/examples/list.html)
|
|
314
|
-
- [glTF viewer](https://hilo3d.js.org/examples/glTFViewer/index.html)
|
|
315
|
-
- [Engineering documentation index](./documentation/README.md)
|
|
316
|
-
- [Current rendering architecture](./documentation/RENDERING_ARCHITECTURE.md)
|
|
317
|
-
- [vNext renderer engineering record](./documentation/ENGINEERING_MODERNIZATION.md#双后端渲染与-shader-abi)
|
|
318
|
-
- [ShaderMaterial migration guide](./documentation/ENGINEERING_MODERNIZATION.md#shadermaterial-迁移)
|
|
319
|
-
- [Breaking changes](./CHANGELOG.md#breaking-changes)
|
|
320
|
-
- [Contributing](./.github/CONTRIBUTING.md)
|
|
228
|
+
[MIT](./LICENSE) © Hilo3D contributors.
|