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/README.md CHANGED
@@ -1,27 +1,51 @@
1
- # Hilo3d
2
-
3
- English | [简体中文](./README_ZH.md)
4
-
5
- **A WebGPU-first, TypeScript-first 3D engine with a production WebGL 2 compatibility backend.**
6
-
7
- Hilo3d vNext is designed around a WebGPU-shaped rendering hardware interface (RHI), explicit render
8
- passes, reusable GPU resources, GLSL ES 3.00, physically based rendering, and glTF. WebGPU keeps its
9
- native pipeline/bind-group/command model, while WebGL 2 implements the same portable subset through
10
- immediate, state-cached GL execution.
11
-
12
- [![npm](https://img.shields.io/npm/v/hilo3d.svg?style=flat-square)](https://www.npmjs.com/package/hilo3d)
13
- [![CI](https://img.shields.io/github/actions/workflow/status/hiloteam/Hilo3d/npm_test.yml?style=flat-square)](https://github.com/hiloteam/Hilo3d/actions/workflows/npm_test.yml)
14
- [![license](https://img.shields.io/npm/l/hilo3d.svg?style=flat-square)](https://github.com/hiloteam/Hilo3d/blob/dev/LICENSE)
15
-
16
- - WebGPURHI is a thin mapping to native WebGPU objects and commands; it does not become a GL-style
17
- state machine and does not replay a second JavaScript command buffer.
18
- - WebGL2RHI emulates pipeline, bind-group, render-pass, and command-encoder semantics while issuing
19
- GL calls immediately through a state-diff cache. `finish()`/`submit()` are ownership boundaries,
20
- not a deferred replay path.
21
- - GLSL ES 3.00 is the only authored shader source. The Renderer shader compiler resolves variants
22
- and translates WebGPU modules through Naga before the RHI sees them.
23
- - Backend policy is explicit: `auto` performs a capability-based choice, while an explicit `webgpu`
24
- or `webgl2` request is never changed silently.
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
- The package has one ESM entry point for modern bundlers and native browser ESM. WebGL 1, CommonJS,
33
- UMD, and global-script builds are not part of the vNext contract.
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
- ## WebGPU quick start
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
- `Stage.create()` defaults to `backend: 'auto'`, prefers WebGPU when a compatible adapter is
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({ aspect: innerWidth / innerHeight, z: 4 });
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: 'webgpu',
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
- const box = new Hilo3d.Mesh({
85
+ new Hilo3d.Mesh({
55
86
  geometry: new Hilo3d.BoxGeometry(),
56
87
  material: new Hilo3d.PBRMaterial({
57
- baseColor: new Hilo3d.Color(0.832, 0.119, 0.093)
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
- Omitting `backend` is equivalent to `backend: 'auto'`. Auto selection calls
69
- `Renderer.isBackendSupported('webgpu', options)` first. This lightweight probe only requests an
70
- adapter and validates the fallback-adapter policy, required features, required limits, and Hilo3d's
71
- minimum adapter limits. It does **not** request a device, acquire a canvas context, initialize Naga,
72
- create a pipeline, or allocate GPU resources. A compatible adapter selects WebGPU; otherwise
73
- `Stage.create()` creates WebGL 2 directly. Supplying the WebGL2-only `preserveDrawingBuffer` option
74
- also makes auto selection choose WebGL 2 directly, as does requesting straight-alpha canvas
75
- compositing with `alpha: true, premultipliedAlpha: false`.
76
-
77
- Once the probe selects WebGPU, normal WebGPU initialization runs exactly once. A device or canvas
78
- context error, shader-compiler failure, pipeline/resource initialization error, or any later failure
79
- rejects `Stage.create()` and is never caught as a reason to fall back. Requesting
80
- `backend: 'webgpu'` skips the auto probe and likewise never falls back.
81
-
82
- Applications can use the same device- and GPU-resource-free probe without creating a renderer:
83
-
84
- ```ts
85
- const webgpuSupported = await Hilo3d.Renderer.isBackendSupported('webgpu', {
86
- powerPreference: 'high-performance'
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
- ## WebGL 2 compatibility
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
- Use the compatibility backend without changing scene, material, render-target, or GLSL code:
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
- ```ts
95
- const stage = await Hilo3d.Stage.create({
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
- const webgpuRenderer = await Hilo3d.Renderer.create({
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
- ## One frame, multiple passes
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
- Use `renderFrame()` for an application-owned frame graph. On WebGPU, resource-ready scene, target,
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
- ```ts
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
- renderer.renderFrame(frame => {
159
- frame.renderToTarget(reflectionTarget, stage, reflectionCamera);
160
- frame.renderToTarget(sceneTarget, stage, camera, true);
161
- frame.present(sceneTarget);
162
- });
210
+ ```sh
211
+ npm ci
212
+ npm run dev
163
213
  ```
164
214
 
165
- Resize application-owned targets when the renderer size changes. Use this frame callback from a
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
- ```ts
269
- Hilo3d.registerUniformBlockBinding('EffectBlock');
270
- const effectLayout = Hilo3d.createStd140Layout({ tint: 'vec4' });
271
- const effectBlock = Hilo3d.UniformBuffer.fromSchema(effectLayout, {
272
- tint: [0.6, 0.8, 1, 1]
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
- Use `in`/`out`, `texture()`, and explicit fragment outputs. Register each custom block before first
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
- WebGPU device loss emits `webgpuDeviceLost`, reacquires an equivalent adapter/device with the frozen
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
- Use `await renderer.waitForIdle()` when application code needs a backend-neutral completion fence.
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.