@plasius/gpu-renderer 0.2.46 → 0.2.48
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 +53 -0
- package/README.md +230 -0
- package/dist/index.cjs +512 -40
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +510 -40
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
- package/src/canonical-wavefront-meshes.js +226 -0
- package/src/index.d.ts +55 -0
- package/src/index.js +3 -0
- package/src/native-scene-renderer.js +152 -7
- package/src/native-scene-shader.js +68 -18
- package/src/native-surface-materials.js +124 -0
package/CHANGELOG.md
CHANGED
|
@@ -23,6 +23,57 @@ All notable changes to this project will be documented in this file.
|
|
|
23
23
|
- **Security**
|
|
24
24
|
- (placeholder)
|
|
25
25
|
|
|
26
|
+
## [0.2.48] - 2026-10-11
|
|
27
|
+
|
|
28
|
+
- Expose native material preflight validation and transfer the reviewed demo adapters plus their tests to the shared material-study runtime for production reuse (#230).
|
|
29
|
+
|
|
30
|
+
- Correct vertical grab direction in the material-review camera for mouse, touch and keyboard orbit; preserve horizontal, pan and zoom directions (#230).
|
|
31
|
+
|
|
32
|
+
- Replace the material review camera toolbar with a five-second focus gesture guide; keep direct mouse/touch movement independent of keyboard modes, with replay and dismissal (#230).
|
|
33
|
+
|
|
34
|
+
- Update the existing brace-expansion development override to 5.0.12 for patched denial-of-service advisories (#230).
|
|
35
|
+
|
|
36
|
+
- Fix native normal maps losing detail at close range; add a source-demo camera adapter using shared orbit, truck, pan, dolly and zoom controls with keyboard/touch support (#230).
|
|
37
|
+
|
|
38
|
+
- Fix full varnish wear to exactly match the uncoated endpoint; replace random rope strands with shorter, finer guide-aligned tufts and bounded denser nap (#230).
|
|
39
|
+
|
|
40
|
+
- Add a versioned material-ageing profile and crate adapter with independent 30% rope fraying / 90% varnish-wear review defaults; preserve fibre roots across wear edits and retain coating islands within heavily scuffed wood (#230).
|
|
41
|
+
|
|
42
|
+
- Add bounded, deterministic curved rope fibres to the chest review fixture, with matte exposed-fibre materials and comparison/detail views (#230).
|
|
43
|
+
|
|
44
|
+
- Support spatial clearcoat coverage and roughness maps; keep the crate fixture's rope and hardware uncoated and vary its wood varnish with a deterministic wear preset (#230).
|
|
45
|
+
|
|
46
|
+
- Separate optional neutral varnish/clearcoat reflection from the coloured native surface, with independent roughness and Fresnel attenuation (#230).
|
|
47
|
+
|
|
48
|
+
- Add bounded, mip-filtered authored colour, normal and ORM materials to native surfaces, with optional UVs and draw ranges shared by the main and reflection passes (#230).
|
|
49
|
+
|
|
50
|
+
- **Added**
|
|
51
|
+
- (placeholder)
|
|
52
|
+
|
|
53
|
+
- **Changed**
|
|
54
|
+
- (placeholder)
|
|
55
|
+
|
|
56
|
+
- **Fixed**
|
|
57
|
+
- (placeholder)
|
|
58
|
+
|
|
59
|
+
- **Security**
|
|
60
|
+
- (placeholder)
|
|
61
|
+
|
|
62
|
+
## [0.2.47] - 2026-10-09
|
|
63
|
+
|
|
64
|
+
- **Added**
|
|
65
|
+
- Added `createCanonicalWavefrontMeshInputs` to adapt decoded canonical model
|
|
66
|
+
geometry, material factors, and texture samples to Wavefront renderer inputs.
|
|
67
|
+
|
|
68
|
+
- **Changed**
|
|
69
|
+
- (placeholder)
|
|
70
|
+
|
|
71
|
+
- **Fixed**
|
|
72
|
+
- (placeholder)
|
|
73
|
+
|
|
74
|
+
- **Security**
|
|
75
|
+
- (placeholder)
|
|
76
|
+
|
|
26
77
|
## [0.2.46] - 2026-09-29
|
|
27
78
|
|
|
28
79
|
- Add native showcase surface drawing with filtered shadows, HDR planar water
|
|
@@ -1149,3 +1200,5 @@ All notable changes to this project will be documented in this file.
|
|
|
1149
1200
|
[0.2.44]: https://github.com/Plasius-LTD/gpu-renderer/releases/tag/v0.2.44
|
|
1150
1201
|
[0.2.45]: https://github.com/Plasius-LTD/gpu-renderer/releases/tag/v0.2.45
|
|
1151
1202
|
[0.2.46]: https://github.com/Plasius-LTD/gpu-renderer/releases/tag/v0.2.46
|
|
1203
|
+
[0.2.47]: https://github.com/Plasius-LTD/gpu-renderer/releases/tag/v0.2.47
|
|
1204
|
+
[0.2.48]: https://github.com/Plasius-LTD/gpu-renderer/releases/tag/v0.2.48
|
package/README.md
CHANGED
|
@@ -129,6 +129,41 @@ renderer.resize(window.innerWidth, window.innerHeight);
|
|
|
129
129
|
renderer.start();
|
|
130
130
|
```
|
|
131
131
|
|
|
132
|
+
## Canonical model ingestion
|
|
133
|
+
|
|
134
|
+
`createCanonicalWavefrontMeshInputs` adapts decoded primitive geometry and image
|
|
135
|
+
samples from the canonical model pipeline to the renderer's existing
|
|
136
|
+
`WavefrontMeshInput` shape. It maps canonical material factors and standard
|
|
137
|
+
texture bindings, preserves supported material extension data, and rejects
|
|
138
|
+
missing primitive, material, or decoded texture references. It accepts triangle
|
|
139
|
+
primitives; parsing, resource fetching, image decoding, and other topologies stay
|
|
140
|
+
in the upstream conversion layer. Metallic-roughness and unlit workflows are
|
|
141
|
+
supported; workflows without an existing Wavefront mapping fail explicitly.
|
|
142
|
+
|
|
143
|
+
```js
|
|
144
|
+
import { createCanonicalWavefrontMeshInputs } from "@plasius/gpu-renderer";
|
|
145
|
+
|
|
146
|
+
const meshes = createCanonicalWavefrontMeshInputs({
|
|
147
|
+
document: canonicalDocument,
|
|
148
|
+
geometry: decodedPrimitives.map(({ primitiveId, positions, indices, normals, texcoords }) => ({
|
|
149
|
+
primitiveId,
|
|
150
|
+
positions,
|
|
151
|
+
indices,
|
|
152
|
+
normals,
|
|
153
|
+
texcoords,
|
|
154
|
+
})),
|
|
155
|
+
// ReadonlyMap<canonical texture id, decoded RGBA sample>
|
|
156
|
+
textures: decodedTextureSamples,
|
|
157
|
+
});
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
The canonical document uses types from `@plasius/gpu-model-core`. Geometry is
|
|
161
|
+
already renderer-ready, normals may be omitted to retain the renderer's existing
|
|
162
|
+
fallback, and texture samples are keyed by canonical texture ID. The consuming
|
|
163
|
+
surface remains responsible for evaluating the remote
|
|
164
|
+
`gpu.model.conversion.enabled` flag: when disabled or rolled back, keep the
|
|
165
|
+
existing rendering path active.
|
|
166
|
+
|
|
132
167
|
## Adaptive Frame Hooks
|
|
133
168
|
|
|
134
169
|
`@plasius/gpu-renderer` now exposes frame lifecycle hooks so the app can pass
|
|
@@ -751,3 +786,198 @@ there is no npm write-token fallback. CD remains disabled until the npm trusted
|
|
|
751
786
|
publisher binding and protected-branch-only production environment are
|
|
752
787
|
independently verified.
|
|
753
788
|
<!-- END PLASIUS RELEASE INTEGRITY -->
|
|
789
|
+
|
|
790
|
+
### Authored materials in native surfaces
|
|
791
|
+
|
|
792
|
+
`createNativeSceneRenderer({ canvas, materials })` accepts up to 16 opaque
|
|
793
|
+
materials containing decoded RGBA8 `baseColor`, `normal`, and/or `orm` maps.
|
|
794
|
+
This matches images returned by the `@plasius/gpu-shared` glTF loader. Colour maps
|
|
795
|
+
are sRGB; normals and ORM (occlusion/roughness/metalness) are linear. Optional
|
|
796
|
+
`normalScale` defaults to 1. Maps must be power-of-two, up to 2048 pixels per axis,
|
|
797
|
+
with a 64 MiB combined decoded-source budget. Textures are uploaded once and mip
|
|
798
|
+
filtered; the renderer owns GPU disposal, while callers own image loading.
|
|
799
|
+
|
|
800
|
+
For textured frames, supply `texcoords` (two floats per vertex) and `surfaces`
|
|
801
|
+
containing `{ firstVertex, vertexCount, materialIndex }`. Ranges must cover the
|
|
802
|
+
whole triangle list in order, refer to the initialization-time materials, and
|
|
803
|
+
contain whole triangles. At most 256 ranges are accepted. Linear vertex colour
|
|
804
|
+
and roughness/metalness factors multiply the maps. Omit both new frame fields to
|
|
805
|
+
retain the existing procedural/untextured path. Main and reflection passes use
|
|
806
|
+
the same authored material; alpha/transmission/skinning are not added here.
|
|
807
|
+
|
|
808
|
+
See [material design](docs/design/native-textured-surfaces.md) and
|
|
809
|
+
[ADR-0031](docs/adrs/adr-0031-native-authored-materials.md). Rollout inherits
|
|
810
|
+
`gpu-demo.scene-fidelity.enabled`; access remains governed by the site's capability.
|
|
811
|
+
|
|
812
|
+
For varnished wood, set optional `clearcoat` and `clearcoatRoughness` (both 0–1).
|
|
813
|
+
The coating reflects neutral light using its own smooth geometric normal above
|
|
814
|
+
the coloured, normal-mapped wood; Fresnel layering attenuates the underlying
|
|
815
|
+
material instead of simply adding shine. Strength defaults to zero, preserving
|
|
816
|
+
uncoated callers. Coating roughness defaults to zero and is independent of the
|
|
817
|
+
base roughness map. Optional `clearcoatMap` uses linear RGBA8: red multiplies
|
|
818
|
+
`clearcoat` coverage and green multiplies `clearcoatRoughness`; blue and alpha
|
|
819
|
+
are ignored. Omission uses white, preserving the scalar-only finish. Use a
|
|
820
|
+
nonzero roughness factor (for example 1) to author roughness directly in green.
|
|
821
|
+
The map shares the surface UVs, mip filtering, memory budget and GPU lifetime of
|
|
822
|
+
other maps. Clearcoat normal maps remain unsupported.
|
|
823
|
+
|
|
824
|
+
For mixed objects, give uncoated parts their own surface ranges with
|
|
825
|
+
`clearcoat: 0`. This keeps rope and hardware uncoated even when they share the
|
|
826
|
+
wood's atlas. The source example [native-crate-finish.js](https://github.com/Plasius-LTD/gpu-shared/tree/main/src/material-study-helpers/native-crate-finish.js)
|
|
827
|
+
provides reviewed crate ranges and a deterministic wear preset combining existing
|
|
828
|
+
roughness/scuff detail with broad UV patches. Its 0–1 wear control changes coat
|
|
829
|
+
coverage and roughness without modifying the underlying colour or source asset.
|
|
830
|
+
See [spatial coating decision](docs/adrs/adr-0032-spatial-native-clearcoat.md) and
|
|
831
|
+
the [fixture/provenance record](docs/design/cc0-demo-asset-review.md). The example
|
|
832
|
+
helper is source-only; the published API is the generic material map.
|
|
833
|
+
|
|
834
|
+
For subtle rope fraying, the source-demo helper
|
|
835
|
+
[native-rope-fibres.js](https://github.com/Plasius-LTD/gpu-shared/tree/main/src/material-study-helpers/native-rope-fibres.js) exports `createRopeFibres`.
|
|
836
|
+
Pass the expanded native `vertices`, `texcoords` and explicit rope-only
|
|
837
|
+
`{ firstVertex, vertexCount }` ranges. It returns separate triangles/UVs and a
|
|
838
|
+
`fibreCount`; append them once with their own draw range. Generate in metre-scale
|
|
839
|
+
world coordinates after transforms. Sampling is deterministic and area-weighted,
|
|
840
|
+
with short tapered curves in small aligned tufts. `density` controls roots per
|
|
841
|
+
square metre; `maxFibres` caps them at 4,000 (default 1,600). `length` and `radius`
|
|
842
|
+
are in metres. The 21 triangles per strand use ordinary native multisampling,
|
|
843
|
+
depth and lighting; no animated fur or dedicated hair scattering is claimed.
|
|
844
|
+
|
|
845
|
+
Optional `fray` (0–1, default 0.08) promotes exactly
|
|
846
|
+
`round(fibreCount * fray)` strands to longer curled loose ends, reported as
|
|
847
|
+
`looseEndCount`. Selection is seeded and nested: raising the level keeps earlier
|
|
848
|
+
loose ends, roots and UVs in place. At 0, short fuzz remains. This is a visual
|
|
849
|
+
proportion of generated fibres, not lost rope strength.
|
|
850
|
+
|
|
851
|
+
Use `createRopeFibreMaterial(ropeMaterial)` for the added range: it keeps the
|
|
852
|
+
rope's colour map and zero clearcoat while omitting the core's baked occlusion
|
|
853
|
+
and normal creases from exposed fibres. Vertex roughness is 1 and metallic is 0.
|
|
854
|
+
The review fixture offers fibre on/off and both rope-detail views. See
|
|
855
|
+
[ADR-0033](docs/adrs/adr-0033-demo-rope-fibres.md). These helpers remain source-only
|
|
856
|
+
and do not add a renderer API, dependency or network request.
|
|
857
|
+
|
|
858
|
+
### Material ageing review wrapper
|
|
859
|
+
|
|
860
|
+
[material-ageing.js](https://github.com/Plasius-LTD/gpu-shared/tree/main/src/material-study-helpers/material-ageing.js) validates and freezes a serializable
|
|
861
|
+
version-1 profile. [native-crate-ageing.js](https://github.com/Plasius-LTD/gpu-shared/tree/main/src/material-study-helpers/native-crate-ageing.js) applies it
|
|
862
|
+
through the existing coating/fibre helpers:
|
|
863
|
+
|
|
864
|
+
```js
|
|
865
|
+
import { createCrateAgeing } from '@plasius/gpu-shared/material-study';
|
|
866
|
+
|
|
867
|
+
const ageing = createCrateAgeing({ ropeFray: 0.30, varnishWear: 0.90, seed: 7349 });
|
|
868
|
+
const { wood, rope, metal, fibres: fibreMaterial } = ageing.createMaterials(sourceMaps);
|
|
869
|
+
const fibreGeometry = ageing.createFibres({ vertices, texcoords, ranges: ropeRanges, heightOffset: -minY });
|
|
870
|
+
// Append fibreGeometry with fibreMaterial using the existing native draw contract.
|
|
871
|
+
```
|
|
872
|
+
|
|
873
|
+
Those values are also the review defaults. `varnishWear` is independent visual
|
|
874
|
+
intensity, not coating area removed or elapsed years. Broad scuff patches expose
|
|
875
|
+
wood while sheltered areas retain coating at intermediate wear. Above 70%, the
|
|
876
|
+
remaining islands smoothly erode; at 100%, every coverage texel and the scalar
|
|
877
|
+
coat strength are zero, matching varnish disabled. The original wood maps remain
|
|
878
|
+
unchanged, including their ordinary substrate light response. `seed` controls fibre placement and
|
|
879
|
+
loose-end selection; varnish uses its existing stable UV pattern. The crate adapter
|
|
880
|
+
uses a 4.5 mm fibre length scale and 0.16 mm root radius, with a 4,000-fibre budget;
|
|
881
|
+
loose ends are 1.3–2 times the length scale and taper to a point. Source images and
|
|
882
|
+
geometry remain unchanged; rope, added fibres and metal never acquire clearcoat.
|
|
883
|
+
|
|
884
|
+
Generate/copy geometry only when the fray channel changes; rebuild finish maps
|
|
885
|
+
only when coating settings change. Camera movement reuses both. The caller still
|
|
886
|
+
owns verified asset ranges, GPU resources and disposal. The local review includes
|
|
887
|
+
fresh/aged presets, fibre/coat toggles and both handle-detail views.
|
|
888
|
+
|
|
889
|
+
This is a tested source-demo wrapper, not a newly published package or a complete
|
|
890
|
+
damage simulator. [ADR-0034](docs/adrs/adr-0034-material-ageing-profile.md) records
|
|
891
|
+
the proposed `@plasius/material-ageing` boundary after a second asset establishes
|
|
892
|
+
the shared contract. Production adoption retains `gpu-demo.scene-fidelity.enabled`
|
|
893
|
+
and the existing GPU route capability; disabling the feature selects the existing
|
|
894
|
+
site fallback. No package publication or site deployment is implied by this study.
|
|
895
|
+
|
|
896
|
+
|
|
897
|
+
For structured nap, `createRopeFibres` accepts optional `guides`: at most eight
|
|
898
|
+
polylines of 2–65 finite 3D points, in the same metre-scale coordinates as the
|
|
899
|
+
input geometry. The nearest guide is projected onto the surface and given a
|
|
900
|
+
consistent helical lay. Without a usable projected guide, a finite tangent
|
|
901
|
+
fallback is used. Four nearby roots form a tuft within 1 mm of its anchor, with
|
|
902
|
+
small angular variation, shallow lift and tapered tips. Sampling remains stable
|
|
903
|
+
when fray changes; changing guides reauthors the groom.
|
|
904
|
+
|
|
905
|
+
[native-crate-groom.js](https://github.com/Plasius-LTD/gpu-shared/tree/main/src/material-study-helpers/native-crate-groom.js) supplies the hash-verified
|
|
906
|
+
fixture's loop/knot paths. Pass the same `heightOffset` used to ground its vertices
|
|
907
|
+
(default 0 means unmodified asset coordinates); other transforms require matching
|
|
908
|
+
transformed guide coordinates. The crate adapter adds 84,000 triangles: 90,578
|
|
909
|
+
triangles / 271,734 vertices total, within the native default budget. Its final
|
|
910
|
+
fibre arrays occupy 14,112,000 bytes. This deliberate denser nap replaces the
|
|
911
|
+
previous 1,600-strand loose-end study. See [ADR-0035](docs/adrs/adr-0035-groomed-rope-and-bare-coat-endpoint.md).
|
|
912
|
+
|
|
913
|
+
|
|
914
|
+
### In-scene material inspection camera
|
|
915
|
+
|
|
916
|
+
The shared [native-demo-camera.js](https://github.com/Plasius-LTD/gpu-shared/tree/main/src/material-study-helpers/native-demo-camera.js) adapter uses
|
|
917
|
+
released `@plasius/gpu-camera` state/control/projection APIs and the separate
|
|
918
|
+
`@plasius/gpu-camera-controls` pointer gesture runtime/browser normalizer. It maps DOM input to
|
|
919
|
+
orbit, camera-plane truck/pedestal, pan/tilt, dolly and optical zoom; camera math
|
|
920
|
+
is not duplicated in the renderer. The camera and fixture adapters now belong to the isolated gpu-shared material-study
|
|
921
|
+
entry; the renderer root does not load them.
|
|
922
|
+
|
|
923
|
+
```js
|
|
924
|
+
import { createNativeDemoCamera } from '@plasius/gpu-shared/material-study';
|
|
925
|
+
|
|
926
|
+
// Supply a focusable canvas with an accessible name and persistent
|
|
927
|
+
// aria-describedby instructions. The visual example is initially hidden,
|
|
928
|
+
// aria-hidden, pointer-events:none and contains no interactive controls.
|
|
929
|
+
const cameraControls = createNativeDemoCamera({
|
|
930
|
+
canvas,
|
|
931
|
+
camera: { eye: [-0.7, 0.5, 0.8], target: [0, 0.16, 0], fov: 42 },
|
|
932
|
+
onChange: () => draw(),
|
|
933
|
+
onHintChange: visible => { gestureExample.hidden = !visible; },
|
|
934
|
+
});
|
|
935
|
+
// Each draw uses camera: cameraControls.read(). Keep the controls alive across
|
|
936
|
+
// renderer/material rebuilds; defer drawing while the renderer is unavailable.
|
|
937
|
+
// At teardown (also cancels the hint timer):
|
|
938
|
+
cameraControls.destroy();
|
|
939
|
+
```
|
|
940
|
+
|
|
941
|
+
The material review uses direct manipulation with no persistent camera toolbar.
|
|
942
|
+
The optional `onHintChange` callback shows a brief example on canvas focus and
|
|
943
|
+
hides it after five seconds, on blur, Escape or disposal. Refocus or `?` replays
|
|
944
|
+
it; replay replaces the prior timer. The host owns visual presentation: show
|
|
945
|
+
mouse/touch or keyboard examples, preserve a screen-reader description without a
|
|
946
|
+
time limit, and respect reduced motion. Do not move the camera to demonstrate a
|
|
947
|
+
gesture or let the example intercept input. Keep material controls below the scene.
|
|
948
|
+
|
|
949
|
+
| Input | Camera action |
|
|
950
|
+
| --- | --- |
|
|
951
|
+
| Left-drag / one finger | Orbit, with the grabbed surface following the drag on both axes |
|
|
952
|
+
| Right/middle/Shift-drag | Truck / pedestal across the current view |
|
|
953
|
+
| Alt-drag | Pan / tilt in place |
|
|
954
|
+
| Scroll / touch pinch | Move closer or farther (dolly) |
|
|
955
|
+
| Shift-scroll | Change the lens (optical zoom) |
|
|
956
|
+
| Two fingers moving together | Truck / pedestal |
|
|
957
|
+
| Arrows / Shift-arrows | Selected keyboard mode / truck |
|
|
958
|
+
| 1–5 | Select orbit, truck, pan, dolly or lens zoom for keyboard arrows |
|
|
959
|
+
| +/− | Dolly (lens zoom in keyboard zoom mode) |
|
|
960
|
+
| Home | Reset view |
|
|
961
|
+
| ? / Escape | Replay / dismiss the brief guide |
|
|
962
|
+
|
|
963
|
+
Vertical orbit follows the grab direction for mouse, one-finger touch and keyboard
|
|
964
|
+
arrows. The adapter maps single-pointer orbit through gpu-camera; the shared
|
|
965
|
+
gesture runtime retains original pointer coordinates for multi-pointer truck/pinch
|
|
966
|
+
and stable transitions. Keyboard mode selection does not change mouse or touch gestures. The source-only
|
|
967
|
+
`setMode`, `getMode`, `move` and `reset` methods remain available to host code.
|
|
968
|
+
Browser Ctrl/Meta/Alt key shortcuts and keys outside the canvas are left alone.
|
|
969
|
+
Wheel input only belongs to a focused canvas; the surrounding page remains
|
|
970
|
+
scrollable. No inertia or animation loop is introduced. Distances, lens and travel
|
|
971
|
+
are bounded; pointer cancellation/blur/disposal release captures and listeners.
|
|
972
|
+
This is an inspection camera without scene collision detection or object picking.
|
|
973
|
+
|
|
974
|
+
Native material normal-map degeneracy checks now use normalized screen-space
|
|
975
|
+
position/UV gradients. Valid tiny derivatives in rope macro views no longer disable
|
|
976
|
+
normal maps. Mirrored UV handedness and geometric-normal fallback for degenerate
|
|
977
|
+
UVs are retained in the common direct/reflection shader. The shader contract tests
|
|
978
|
+
require browser rendering evidence as well; Node mocks do not execute WGSL.
|
|
979
|
+
See [ADR-0036](docs/adrs/adr-0036-in-scene-material-inspection.md).
|
|
980
|
+
|
|
981
|
+
### Shared material-study runtime
|
|
982
|
+
|
|
983
|
+
Production demo helpers and their regression tests now live in `@plasius/gpu-shared/material-study`. The renderer exposes `validateNativeSurfaceMaterials(materials)` so authoring and GPU creation use identical validation without allocation. See [ADR-0037](docs/adrs/adr-0037-shared-material-study-runtime.md).
|