@aardworx/wombat.rendering 0.7.2 → 0.8.1
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/dist/runtime/heapScene.d.ts +61 -0
- package/dist/runtime/heapScene.d.ts.map +1 -0
- package/dist/runtime/heapScene.js +354 -0
- package/dist/runtime/heapScene.js.map +1 -0
- package/dist/runtime/heapShader.d.ts +12 -0
- package/dist/runtime/heapShader.d.ts.map +1 -0
- package/dist/runtime/heapShader.js +157 -0
- package/dist/runtime/heapShader.js.map +1 -0
- package/dist/runtime/index.d.ts +2 -0
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/index.js +2 -0
- package/dist/runtime/index.js.map +1 -1
- package/package.json +1 -1
- package/src/runtime/heapScene.ts +510 -0
- package/src/runtime/heapShader.ts +185 -0
- package/src/runtime/index.ts +12 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { Trafo3d, V3d, V4f } from "@aardworx/wombat.base";
|
|
2
|
+
import type { aval } from "@aardworx/wombat.adaptive";
|
|
3
|
+
import type { CanvasAttachment } from "../window/index.js";
|
|
4
|
+
/**
|
|
5
|
+
* Geometry triple. Tightly-packed Float32 positions / normals (3
|
|
6
|
+
* floats per vertex) plus Uint32 indices. The heap-scene packer
|
|
7
|
+
* concatenates all draws' geometry into per-group slabs.
|
|
8
|
+
*/
|
|
9
|
+
export interface HeapGeometry {
|
|
10
|
+
readonly positions: Float32Array;
|
|
11
|
+
readonly normals: Float32Array;
|
|
12
|
+
readonly indices: Uint32Array;
|
|
13
|
+
}
|
|
14
|
+
export interface HeapDrawSpec {
|
|
15
|
+
readonly geo: HeapGeometry;
|
|
16
|
+
readonly modelTrafo: aval<Trafo3d> | Trafo3d;
|
|
17
|
+
readonly color: aval<V4f> | V4f;
|
|
18
|
+
/** Group key — selects which pipeline-state group this draw joins. */
|
|
19
|
+
readonly groupKey: string;
|
|
20
|
+
}
|
|
21
|
+
export interface HeapSceneStats {
|
|
22
|
+
readonly groups: number;
|
|
23
|
+
readonly totalDraws: number;
|
|
24
|
+
readonly globalsBytes: number;
|
|
25
|
+
drawBytes: number;
|
|
26
|
+
readonly geometryBytes: number;
|
|
27
|
+
}
|
|
28
|
+
export interface HeapScene {
|
|
29
|
+
/** Render one frame against the given globals. */
|
|
30
|
+
frame(viewProj: Trafo3d, lightLocation: V3d): void;
|
|
31
|
+
readonly stats: HeapSceneStats;
|
|
32
|
+
dispose(): void;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Per-group texture set. Bindless isn't standard WebGPU, so a group
|
|
36
|
+
* with sampled textures gets a distinct bind-group layout and is
|
|
37
|
+
* keyed separately from groups with no textures or different sets.
|
|
38
|
+
*/
|
|
39
|
+
export interface HeapTextureSet {
|
|
40
|
+
readonly texture: GPUTexture;
|
|
41
|
+
readonly textureView?: GPUTextureView;
|
|
42
|
+
readonly sampler: GPUSampler;
|
|
43
|
+
}
|
|
44
|
+
export interface BuildHeapSceneOptions {
|
|
45
|
+
/** WGSL fragment-stage source per group key — must declare `fs(in: VsOut) -> @location(0) vec4<f32>`. */
|
|
46
|
+
readonly fragmentShaders: ReadonlyMap<string, string>;
|
|
47
|
+
/**
|
|
48
|
+
* Per-group texture set. When present, the group's bind-group
|
|
49
|
+
* layout adds a `texture_2d<f32>` at binding 4 and a sampler at
|
|
50
|
+
* binding 5. The user's FS WGSL must declare them.
|
|
51
|
+
*/
|
|
52
|
+
readonly texturesByGroupKey?: ReadonlyMap<string, HeapTextureSet>;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Build a multi-group heap-backed scene renderer. Buckets `draws` by
|
|
56
|
+
* `groupKey`, builds one pipeline + bind group + heap per bucket,
|
|
57
|
+
* subscribes per-RO avals so dirty marks propagate to per-slot
|
|
58
|
+
* `writeBuffer`s on the next `frame()`.
|
|
59
|
+
*/
|
|
60
|
+
export declare function buildHeapScene(device: GPUDevice, attach: CanvasAttachment, draws: readonly HeapDrawSpec[], opts: BuildHeapSceneOptions): HeapScene;
|
|
61
|
+
//# sourceMappingURL=heapScene.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heapScene.d.ts","sourceRoot":"","sources":["../../src/runtime/heapScene.ts"],"names":[],"mappings":"AA4CA,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAa,MAAM,uBAAuB,CAAC;AAErE,OAAO,KAAK,EAAE,IAAI,EAAe,MAAM,2BAA2B,CAAC;AACnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AA4G3D;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,SAAS,EAAE,YAAY,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAI,YAAY,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAI,WAAW,CAAC;CACjC;AAoLD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,GAAG,EAAE,YAAY,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;IAC7C,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;IAChC,sEAAsE;IACtE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,SAAS;IACxB,kDAAkD;IAClD,KAAK,CAAC,QAAQ,EAAE,OAAO,EAAE,aAAa,EAAE,GAAG,GAAG,IAAI,CAAC;IACnD,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,OAAO,IAAI,IAAI,CAAC;CACjB;AAED;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7B,QAAQ,CAAC,WAAW,CAAC,EAAE,cAAc,CAAC;IACtC,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;CAC9B;AAED,MAAM,WAAW,qBAAqB;IACpC,yGAAyG;IACzG,QAAQ,CAAC,eAAe,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtD;;;;OAIG;IACH,QAAQ,CAAC,kBAAkB,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;CACnE;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,gBAAgB,EACxB,KAAK,EAAE,SAAS,YAAY,EAAE,EAC9B,IAAI,EAAE,qBAAqB,GAC1B,SAAS,CA6GX"}
|
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
// heapScene — multi-group heap-everything render path.
|
|
2
|
+
//
|
|
3
|
+
// Public-API extraction of the experimental heap-demo (commits in
|
|
4
|
+
// the `experimental/heap-arch` branch document the design). One
|
|
5
|
+
// shared GPURenderPipeline + GPUBindGroup per pipeline-state group,
|
|
6
|
+
// per-draw uniforms in a storage buffer, vertex pulling from packed
|
|
7
|
+
// position / normal slabs, indexed draws via a shared index buffer
|
|
8
|
+
// and `firstInstance` routing into the heap.
|
|
9
|
+
//
|
|
10
|
+
// Per-frame uploads:
|
|
11
|
+
// - Globals (one UBO per group): viewProj + lightLocation. ~80 B.
|
|
12
|
+
// Independent of draw count.
|
|
13
|
+
// - DrawHeader (one storage buffer per group): only slots whose
|
|
14
|
+
// `aval<Trafo3d>` or `aval<V4f>` were marked since last frame
|
|
15
|
+
// are re-uploaded — 160 B per dirty slot.
|
|
16
|
+
//
|
|
17
|
+
// Geometry is uploaded ONCE at construction (positions + normals +
|
|
18
|
+
// indices, packed across all draws in a group).
|
|
19
|
+
//
|
|
20
|
+
// The user supplies a fragment-shader body per group key. The vertex
|
|
21
|
+
// stage is provided by this module and reads from a fixed layout:
|
|
22
|
+
//
|
|
23
|
+
// @group(0) @binding(0) var<uniform> globals: Globals;
|
|
24
|
+
// @group(0) @binding(1) var<storage, read> draws: array<DrawHeader>;
|
|
25
|
+
// @group(0) @binding(2) var<storage, read> positions: array<f32>;
|
|
26
|
+
// @group(0) @binding(3) var<storage, read> normals: array<f32>;
|
|
27
|
+
//
|
|
28
|
+
// struct VsOut {
|
|
29
|
+
// @builtin(position) clipPos: vec4<f32>,
|
|
30
|
+
// @location(0) worldPos: vec3<f32>,
|
|
31
|
+
// @location(1) normal: vec3<f32>,
|
|
32
|
+
// @location(2) color: vec4<f32>,
|
|
33
|
+
// @location(3) lightLoc: vec3<f32>,
|
|
34
|
+
// };
|
|
35
|
+
//
|
|
36
|
+
// User WGSL must declare `@fragment fn fs(in: VsOut) -> @location(0) vec4<f32>`.
|
|
37
|
+
//
|
|
38
|
+
// Per-group texture sets. WebGPU 1.0 has no bindless, so texture-set
|
|
39
|
+
// is a wedge in the group key: groups with different texture sets
|
|
40
|
+
// can't share a bind group. Pass a `textures: { texture, sampler }`
|
|
41
|
+
// per groupKey via `BuildHeapSceneOptions.texturesByGroupKey`. The
|
|
42
|
+
// package adds the texture (binding 4) + sampler (binding 5) to that
|
|
43
|
+
// group's bind-group layout; the user's FS WGSL declares them.
|
|
44
|
+
import { Trafo3d, V3d, V4f } from "@aardworx/wombat.base";
|
|
45
|
+
import { AVal, addMarkingCallback } from "@aardworx/wombat.adaptive";
|
|
46
|
+
// ---------------------------------------------------------------------------
|
|
47
|
+
// Layouts
|
|
48
|
+
// ---------------------------------------------------------------------------
|
|
49
|
+
const GLOBALS_BYTES = 64 + 16; // mat4 + vec4
|
|
50
|
+
const GLOBALS_FLOATS = GLOBALS_BYTES / 4;
|
|
51
|
+
const DRAW_HEADER_BYTES = 64 * 2 + 16 + 16; // 2 mat4 + vec4 + (u32 + 3*pad)
|
|
52
|
+
const DRAW_HEADER_FLOATS = DRAW_HEADER_BYTES / 4;
|
|
53
|
+
function packMat44(m, dst, off) {
|
|
54
|
+
// M44d._data is the row-major Float64Array; not part of the public
|
|
55
|
+
// type surface. toArray() round-trips through a fresh number[] which
|
|
56
|
+
// we copy into the f32 staging buffer below.
|
|
57
|
+
const r = m.toArray();
|
|
58
|
+
for (let i = 0; i < 16; i++)
|
|
59
|
+
dst[off + i] = r[i];
|
|
60
|
+
}
|
|
61
|
+
function packGlobals(viewProj, lightLocation, dst) {
|
|
62
|
+
packMat44(viewProj.forward, dst, 0);
|
|
63
|
+
dst[16] = lightLocation.x;
|
|
64
|
+
dst[17] = lightLocation.y;
|
|
65
|
+
dst[18] = lightLocation.z;
|
|
66
|
+
dst[19] = 0;
|
|
67
|
+
}
|
|
68
|
+
function packDrawHeader(modelTrafo, color, vertexBase, dst, drawIndex) {
|
|
69
|
+
const off = drawIndex * DRAW_HEADER_FLOATS;
|
|
70
|
+
packMat44(modelTrafo.forward, dst, off + 0);
|
|
71
|
+
packMat44(modelTrafo.backward, dst, off + 16);
|
|
72
|
+
dst[off + 32] = color.x;
|
|
73
|
+
dst[off + 33] = color.y;
|
|
74
|
+
dst[off + 34] = color.z;
|
|
75
|
+
dst[off + 35] = color.w;
|
|
76
|
+
new Uint32Array(dst.buffer, dst.byteOffset, dst.length)[off + 36] = vertexBase;
|
|
77
|
+
}
|
|
78
|
+
// ---------------------------------------------------------------------------
|
|
79
|
+
// Shared WGSL prelude (struct + bindings + VS)
|
|
80
|
+
// ---------------------------------------------------------------------------
|
|
81
|
+
const SHADER_PRELUDE = /* wgsl */ `
|
|
82
|
+
struct Globals {
|
|
83
|
+
viewProj: mat4x4<f32>,
|
|
84
|
+
lightLocation: vec4<f32>,
|
|
85
|
+
};
|
|
86
|
+
struct DrawHeader {
|
|
87
|
+
modelTrafo: mat4x4<f32>,
|
|
88
|
+
modelTrafoInv: mat4x4<f32>,
|
|
89
|
+
color: vec4<f32>,
|
|
90
|
+
vertexBase: u32,
|
|
91
|
+
_pad0: u32, _pad1: u32, _pad2: u32,
|
|
92
|
+
};
|
|
93
|
+
@group(0) @binding(0) var<uniform> globals: Globals;
|
|
94
|
+
@group(0) @binding(1) var<storage, read> draws: array<DrawHeader>;
|
|
95
|
+
@group(0) @binding(2) var<storage, read> positions: array<f32>;
|
|
96
|
+
@group(0) @binding(3) var<storage, read> normals: array<f32>;
|
|
97
|
+
|
|
98
|
+
struct VsOut {
|
|
99
|
+
@builtin(position) clipPos: vec4<f32>,
|
|
100
|
+
@location(0) worldPos: vec3<f32>,
|
|
101
|
+
@location(1) normal: vec3<f32>,
|
|
102
|
+
@location(2) color: vec4<f32>,
|
|
103
|
+
@location(3) lightLoc: vec3<f32>,
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
fn fetchVec3(buf: ptr<storage, array<f32>, read>, base: u32) -> vec3<f32> {
|
|
107
|
+
return vec3<f32>((*buf)[base + 0u], (*buf)[base + 1u], (*buf)[base + 2u]);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
@vertex
|
|
111
|
+
fn vs(@builtin(vertex_index) vid: u32, @builtin(instance_index) drawIdx: u32) -> VsOut {
|
|
112
|
+
let d = draws[drawIdx];
|
|
113
|
+
let base = (d.vertexBase + vid) * 3u;
|
|
114
|
+
let pos = fetchVec3(&positions, base);
|
|
115
|
+
let nor = fetchVec3(&normals, base);
|
|
116
|
+
// wombat.shader convention: matrices uploaded row-major; WGSL reads
|
|
117
|
+
// them as col-major = transposed. v * M is the row-vec dual of
|
|
118
|
+
// M.mul(v) (= M*v math).
|
|
119
|
+
let wp = vec4<f32>(pos, 1.0) * d.modelTrafo;
|
|
120
|
+
let n = (vec4<f32>(nor, 0.0) * d.modelTrafo).xyz;
|
|
121
|
+
var out: VsOut;
|
|
122
|
+
out.clipPos = wp * globals.viewProj;
|
|
123
|
+
out.worldPos = wp.xyz;
|
|
124
|
+
out.normal = n;
|
|
125
|
+
out.color = d.color;
|
|
126
|
+
out.lightLoc = globals.lightLocation.xyz;
|
|
127
|
+
return out;
|
|
128
|
+
}
|
|
129
|
+
`;
|
|
130
|
+
function packGeometry(device, geos, label) {
|
|
131
|
+
let totalVerts = 0, totalIndices = 0;
|
|
132
|
+
for (const g of geos) {
|
|
133
|
+
totalVerts += g.positions.length / 3;
|
|
134
|
+
totalIndices += g.indices.length;
|
|
135
|
+
}
|
|
136
|
+
const positions = new Float32Array(totalVerts * 3);
|
|
137
|
+
const normals = new Float32Array(totalVerts * 3);
|
|
138
|
+
const indices = new Uint32Array(totalIndices);
|
|
139
|
+
const entries = [];
|
|
140
|
+
let vOff = 0, iOff = 0;
|
|
141
|
+
for (const g of geos) {
|
|
142
|
+
const vCount = g.positions.length / 3;
|
|
143
|
+
positions.set(g.positions, vOff * 3);
|
|
144
|
+
normals.set(g.normals, vOff * 3);
|
|
145
|
+
indices.set(g.indices, iOff);
|
|
146
|
+
entries.push({ vertexBase: vOff, indexCount: g.indices.length, firstIndex: iOff });
|
|
147
|
+
vOff += vCount;
|
|
148
|
+
iOff += g.indices.length;
|
|
149
|
+
}
|
|
150
|
+
const mk = (data, usage, lbl) => {
|
|
151
|
+
const buf = device.createBuffer({
|
|
152
|
+
size: alignUp(data.byteLength, 4),
|
|
153
|
+
usage: usage | GPUBufferUsage.COPY_DST,
|
|
154
|
+
label: lbl,
|
|
155
|
+
});
|
|
156
|
+
device.queue.writeBuffer(buf, 0, data.buffer, data.byteOffset, data.byteLength);
|
|
157
|
+
return buf;
|
|
158
|
+
};
|
|
159
|
+
return {
|
|
160
|
+
positionsBuf: mk(positions, GPUBufferUsage.STORAGE, `${label}/pos`),
|
|
161
|
+
normalsBuf: mk(normals, GPUBufferUsage.STORAGE, `${label}/nor`),
|
|
162
|
+
indexBuf: mk(indices, GPUBufferUsage.INDEX, `${label}/idx`),
|
|
163
|
+
entries,
|
|
164
|
+
bytes: positions.byteLength + normals.byteLength + indices.byteLength,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
function alignUp(n, a) { return (n + a - 1) & ~(a - 1); }
|
|
168
|
+
function asAval(v) {
|
|
169
|
+
return (typeof v === "object" && v !== null && typeof v.getValue === "function")
|
|
170
|
+
? v
|
|
171
|
+
: AVal.constant(v);
|
|
172
|
+
}
|
|
173
|
+
function buildGroup(device, attach, key, fragmentWgsl, textureSet, draws, modelTrafos, colors) {
|
|
174
|
+
const sig = attach.signature;
|
|
175
|
+
const colorAttachmentName = sig.colorNames[0];
|
|
176
|
+
if (colorAttachmentName === undefined) {
|
|
177
|
+
throw new Error("buildHeapScene: framebuffer signature has no color attachment");
|
|
178
|
+
}
|
|
179
|
+
const colorFormat = sig.colors.tryFind(colorAttachmentName);
|
|
180
|
+
const depthFormat = sig.depthStencil?.format;
|
|
181
|
+
const memberIndices = draws.map(d => d.sourceIndex);
|
|
182
|
+
const myTrafos = memberIndices.map(i => modelTrafos[i]);
|
|
183
|
+
const myColors = memberIndices.map(i => colors[i]);
|
|
184
|
+
const packed = packGeometry(device, draws.map(d => d.spec.geo), `heapScene/${key}`);
|
|
185
|
+
const globals = device.createBuffer({
|
|
186
|
+
size: alignUp(GLOBALS_BYTES, 16),
|
|
187
|
+
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
|
|
188
|
+
label: `heapScene/${key}/globals`,
|
|
189
|
+
});
|
|
190
|
+
const globalsStaging = new Float32Array(GLOBALS_FLOATS);
|
|
191
|
+
const heapBytes = DRAW_HEADER_BYTES * draws.length;
|
|
192
|
+
const drawHeap = device.createBuffer({
|
|
193
|
+
size: alignUp(heapBytes, 16),
|
|
194
|
+
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,
|
|
195
|
+
label: `heapScene/${key}/draws`,
|
|
196
|
+
});
|
|
197
|
+
const drawStaging = new Float32Array(DRAW_HEADER_FLOATS * draws.length);
|
|
198
|
+
for (let i = 0; i < draws.length; i++) {
|
|
199
|
+
packDrawHeader(myTrafos[i].force( /* allow-force */), myColors[i].force( /* allow-force */), packed.entries[i].vertexBase, drawStaging, i);
|
|
200
|
+
}
|
|
201
|
+
device.queue.writeBuffer(drawHeap, 0, drawStaging.buffer, drawStaging.byteOffset, heapBytes);
|
|
202
|
+
const dirty = new Set();
|
|
203
|
+
const subs = [];
|
|
204
|
+
for (let i = 0; i < draws.length; i++) {
|
|
205
|
+
subs.push(addMarkingCallback(myTrafos[i], () => dirty.add(i)));
|
|
206
|
+
subs.push(addMarkingCallback(myColors[i], () => dirty.add(i)));
|
|
207
|
+
}
|
|
208
|
+
const module = device.createShaderModule({
|
|
209
|
+
code: SHADER_PRELUDE + fragmentWgsl,
|
|
210
|
+
label: `heapScene/${key}/shader`,
|
|
211
|
+
});
|
|
212
|
+
const bindLayoutEntries = [
|
|
213
|
+
{ binding: 0, visibility: GPUShaderStage.VERTEX, buffer: { type: "uniform" } },
|
|
214
|
+
{ binding: 1, visibility: GPUShaderStage.VERTEX, buffer: { type: "read-only-storage" } },
|
|
215
|
+
{ binding: 2, visibility: GPUShaderStage.VERTEX, buffer: { type: "read-only-storage" } },
|
|
216
|
+
{ binding: 3, visibility: GPUShaderStage.VERTEX, buffer: { type: "read-only-storage" } },
|
|
217
|
+
];
|
|
218
|
+
if (textureSet !== undefined) {
|
|
219
|
+
bindLayoutEntries.push({ binding: 4, visibility: GPUShaderStage.FRAGMENT, texture: { sampleType: "float" } }, { binding: 5, visibility: GPUShaderStage.FRAGMENT, sampler: { type: "filtering" } });
|
|
220
|
+
}
|
|
221
|
+
const bindGroupLayout = device.createBindGroupLayout({
|
|
222
|
+
label: `heapScene/${key}/bgl`,
|
|
223
|
+
entries: bindLayoutEntries,
|
|
224
|
+
});
|
|
225
|
+
const pipelineLayout = device.createPipelineLayout({ bindGroupLayouts: [bindGroupLayout] });
|
|
226
|
+
const pipeline = device.createRenderPipeline({
|
|
227
|
+
label: `heapScene/${key}/pipeline`,
|
|
228
|
+
layout: pipelineLayout,
|
|
229
|
+
vertex: { module, entryPoint: "vs", buffers: [] },
|
|
230
|
+
fragment: { module, entryPoint: "fs", targets: [{ format: colorFormat }] },
|
|
231
|
+
primitive: { topology: "triangle-list", cullMode: "back", frontFace: "ccw" },
|
|
232
|
+
...(depthFormat !== undefined
|
|
233
|
+
? { depthStencil: { format: depthFormat, depthWriteEnabled: true, depthCompare: "less" } }
|
|
234
|
+
: {}),
|
|
235
|
+
});
|
|
236
|
+
const bindEntries = [
|
|
237
|
+
{ binding: 0, resource: { buffer: globals } },
|
|
238
|
+
{ binding: 1, resource: { buffer: drawHeap } },
|
|
239
|
+
{ binding: 2, resource: { buffer: packed.positionsBuf } },
|
|
240
|
+
{ binding: 3, resource: { buffer: packed.normalsBuf } },
|
|
241
|
+
];
|
|
242
|
+
if (textureSet !== undefined) {
|
|
243
|
+
bindEntries.push({ binding: 4, resource: textureSet.textureView ?? textureSet.texture.createView() }, { binding: 5, resource: textureSet.sampler });
|
|
244
|
+
}
|
|
245
|
+
const bindGroup = device.createBindGroup({
|
|
246
|
+
label: `heapScene/${key}/bg`,
|
|
247
|
+
layout: bindGroupLayout,
|
|
248
|
+
entries: bindEntries,
|
|
249
|
+
});
|
|
250
|
+
return {
|
|
251
|
+
key, pipeline, bindGroup, globals, globalsStaging, drawHeap, drawStaging,
|
|
252
|
+
packed, trafos: myTrafos, colors: myColors, dirty, subs,
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Build a multi-group heap-backed scene renderer. Buckets `draws` by
|
|
257
|
+
* `groupKey`, builds one pipeline + bind group + heap per bucket,
|
|
258
|
+
* subscribes per-RO avals so dirty marks propagate to per-slot
|
|
259
|
+
* `writeBuffer`s on the next `frame()`.
|
|
260
|
+
*/
|
|
261
|
+
export function buildHeapScene(device, attach, draws, opts) {
|
|
262
|
+
const modelTrafos = draws.map(d => asAval(d.modelTrafo));
|
|
263
|
+
const colors = draws.map(d => asAval(d.color));
|
|
264
|
+
// Bucket by group key.
|
|
265
|
+
const buckets = new Map();
|
|
266
|
+
for (let i = 0; i < draws.length; i++) {
|
|
267
|
+
const d = draws[i];
|
|
268
|
+
let bucket = buckets.get(d.groupKey);
|
|
269
|
+
if (bucket === undefined) {
|
|
270
|
+
bucket = [];
|
|
271
|
+
buckets.set(d.groupKey, bucket);
|
|
272
|
+
}
|
|
273
|
+
bucket.push({ spec: d, sourceIndex: i });
|
|
274
|
+
}
|
|
275
|
+
const groups = [];
|
|
276
|
+
for (const [key, members] of buckets) {
|
|
277
|
+
const fs = opts.fragmentShaders.get(key);
|
|
278
|
+
if (fs === undefined) {
|
|
279
|
+
throw new Error(`buildHeapScene: no fragment shader supplied for groupKey '${key}'`);
|
|
280
|
+
}
|
|
281
|
+
const textureSet = opts.texturesByGroupKey?.get(key);
|
|
282
|
+
groups.push(buildGroup(device, attach, key, fs, textureSet, members, modelTrafos, colors));
|
|
283
|
+
}
|
|
284
|
+
const stats = {
|
|
285
|
+
groups: groups.length,
|
|
286
|
+
totalDraws: draws.length,
|
|
287
|
+
globalsBytes: GLOBALS_BYTES * groups.length,
|
|
288
|
+
drawBytes: 0,
|
|
289
|
+
geometryBytes: groups.reduce((acc, g) => acc + g.packed.bytes, 0),
|
|
290
|
+
};
|
|
291
|
+
function frame(viewProj, lightLocation) {
|
|
292
|
+
const fb = attach.framebuffer.force( /* allow-force */);
|
|
293
|
+
const colorAttachmentName = attach.signature.colorNames[0];
|
|
294
|
+
const colorView = fb.colors.tryFind(colorAttachmentName);
|
|
295
|
+
const depthFormat = attach.signature.depthStencil?.format;
|
|
296
|
+
const depthView = fb.depthStencil;
|
|
297
|
+
let totalDirtyBytes = 0;
|
|
298
|
+
const enc = device.createCommandEncoder({ label: "heapScene: encoder" });
|
|
299
|
+
let firstPass = true;
|
|
300
|
+
for (const g of groups) {
|
|
301
|
+
packGlobals(viewProj, lightLocation, g.globalsStaging);
|
|
302
|
+
device.queue.writeBuffer(g.globals, 0, g.globalsStaging.buffer, g.globalsStaging.byteOffset, GLOBALS_BYTES);
|
|
303
|
+
if (g.dirty.size > 0) {
|
|
304
|
+
for (const i of g.dirty) {
|
|
305
|
+
packDrawHeader(g.trafos[i].force( /* allow-force */), g.colors[i].force( /* allow-force */), g.packed.entries[i].vertexBase, g.drawStaging, i);
|
|
306
|
+
const byteOff = i * DRAW_HEADER_BYTES;
|
|
307
|
+
device.queue.writeBuffer(g.drawHeap, byteOff, g.drawStaging.buffer, g.drawStaging.byteOffset + byteOff, DRAW_HEADER_BYTES);
|
|
308
|
+
totalDirtyBytes += DRAW_HEADER_BYTES;
|
|
309
|
+
}
|
|
310
|
+
g.dirty.clear();
|
|
311
|
+
}
|
|
312
|
+
const pass = enc.beginRenderPass({
|
|
313
|
+
colorAttachments: [{
|
|
314
|
+
view: colorView,
|
|
315
|
+
clearValue: { r: 0.07, g: 0.07, b: 0.08, a: 1.0 },
|
|
316
|
+
loadOp: firstPass ? "clear" : "load",
|
|
317
|
+
storeOp: "store",
|
|
318
|
+
}],
|
|
319
|
+
...(depthView !== undefined && depthFormat !== undefined ? {
|
|
320
|
+
depthStencilAttachment: {
|
|
321
|
+
view: depthView,
|
|
322
|
+
depthClearValue: 1.0,
|
|
323
|
+
depthLoadOp: firstPass ? "clear" : "load",
|
|
324
|
+
depthStoreOp: "store",
|
|
325
|
+
},
|
|
326
|
+
} : {}),
|
|
327
|
+
});
|
|
328
|
+
pass.setPipeline(g.pipeline);
|
|
329
|
+
pass.setBindGroup(0, g.bindGroup);
|
|
330
|
+
pass.setIndexBuffer(g.packed.indexBuf, "uint32");
|
|
331
|
+
for (let i = 0; i < g.packed.entries.length; i++) {
|
|
332
|
+
const e = g.packed.entries[i];
|
|
333
|
+
pass.drawIndexed(e.indexCount, 1, e.firstIndex, 0, i);
|
|
334
|
+
}
|
|
335
|
+
pass.end();
|
|
336
|
+
firstPass = false;
|
|
337
|
+
}
|
|
338
|
+
stats.drawBytes = totalDirtyBytes;
|
|
339
|
+
device.queue.submit([enc.finish()]);
|
|
340
|
+
}
|
|
341
|
+
function dispose() {
|
|
342
|
+
for (const g of groups) {
|
|
343
|
+
for (const s of g.subs)
|
|
344
|
+
s.dispose();
|
|
345
|
+
g.globals.destroy();
|
|
346
|
+
g.drawHeap.destroy();
|
|
347
|
+
g.packed.positionsBuf.destroy();
|
|
348
|
+
g.packed.normalsBuf.destroy();
|
|
349
|
+
g.packed.indexBuf.destroy();
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
return { frame, stats, dispose };
|
|
353
|
+
}
|
|
354
|
+
//# sourceMappingURL=heapScene.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heapScene.js","sourceRoot":"","sources":["../../src/runtime/heapScene.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Effect } from "@aardworx/wombat.shader";
|
|
2
|
+
/**
|
|
3
|
+
* Compile a wombat.shader fragment `Effect` into a WGSL string
|
|
4
|
+
* usable as a `buildHeapScene` `fragmentShaders` value.
|
|
5
|
+
*
|
|
6
|
+
* The effect's fragment input field names must match the
|
|
7
|
+
* heap-scene `VsOut` fields: `worldPos`, `normal`, `color`,
|
|
8
|
+
* `lightLoc`. The fragment output must be a single `vec4<f32>`
|
|
9
|
+
* field (any name).
|
|
10
|
+
*/
|
|
11
|
+
export declare function compileHeapFragment(effect: Effect): string;
|
|
12
|
+
//# sourceMappingURL=heapShader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heapShader.d.ts","sourceRoot":"","sources":["../../src/runtime/heapShader.ts"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAEtD;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAO1D"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
// heapShader — bridge from wombat.shader effects to heap-scene
|
|
2
|
+
// fragment WGSL.
|
|
3
|
+
//
|
|
4
|
+
// `buildHeapScene` requires a fragment-stage WGSL string per group
|
|
5
|
+
// key (see runtime/heapScene.ts). Writing those strings by hand
|
|
6
|
+
// works but is the wrong long-term shape — users want to write the
|
|
7
|
+
// FS in the wombat.shader DSL and get the same effect-composition,
|
|
8
|
+
// type-checking, and DCE the per-RO path enjoys.
|
|
9
|
+
//
|
|
10
|
+
// `compileHeapFragment(effect)` runs wombat.shader's emit on a
|
|
11
|
+
// fragment Effect and rewrites the resulting WGSL to plug into the
|
|
12
|
+
// heap-scene's `VsOut` shape:
|
|
13
|
+
//
|
|
14
|
+
// ┌─ heap-scene's VsOut ┌─ DSL fragment input must use
|
|
15
|
+
// │ worldPos: vec3<f32> │ matching field names:
|
|
16
|
+
// │ normal: vec3<f32> │ worldPos, normal, color,
|
|
17
|
+
// │ color: vec4<f32> │ lightLoc
|
|
18
|
+
// │ lightLoc: vec3<f32> │
|
|
19
|
+
// └─ └─
|
|
20
|
+
//
|
|
21
|
+
// The DSL effect's fragment OUTPUT must be a single field; its name
|
|
22
|
+
// is irrelevant (the adapter rewraps to bare `@location(0) vec4<f32>`).
|
|
23
|
+
// `uniform.X` references inside the fragment body are redirected to
|
|
24
|
+
// `in.X` — the contract is that any uniform the FS reads must have
|
|
25
|
+
// been thread through the VS into the corresponding VsOut field.
|
|
26
|
+
//
|
|
27
|
+
// What this DOES NOT do: rewrite the vertex stage. The heap-scene's
|
|
28
|
+
// VS is fixed (storage-buffer uniform reads, vertex pulling from
|
|
29
|
+
// position/normal slabs); user effects only contribute the fragment.
|
|
30
|
+
/**
|
|
31
|
+
* Compile a wombat.shader fragment `Effect` into a WGSL string
|
|
32
|
+
* usable as a `buildHeapScene` `fragmentShaders` value.
|
|
33
|
+
*
|
|
34
|
+
* The effect's fragment input field names must match the
|
|
35
|
+
* heap-scene `VsOut` fields: `worldPos`, `normal`, `color`,
|
|
36
|
+
* `lightLoc`. The fragment output must be a single `vec4<f32>`
|
|
37
|
+
* field (any name).
|
|
38
|
+
*/
|
|
39
|
+
export function compileHeapFragment(effect) {
|
|
40
|
+
const compiled = effect.compile({ target: "wgsl" });
|
|
41
|
+
const fs = compiled.stages.find(s => s.stage === "fragment");
|
|
42
|
+
if (fs === undefined) {
|
|
43
|
+
throw new Error("compileHeapFragment: effect has no fragment stage");
|
|
44
|
+
}
|
|
45
|
+
return rewriteFragment(fs.source);
|
|
46
|
+
}
|
|
47
|
+
function rewriteFragment(wgsl) {
|
|
48
|
+
let s = wgsl;
|
|
49
|
+
// 1. Drop the auto-emitted UBO struct + binding. Heap-scene FS
|
|
50
|
+
// doesn't bind a UBO at all (uniforms ride on VsOut from VS).
|
|
51
|
+
s = s.replace(/struct\s+_UB_uniform\s*\{[\s\S]*?\};?\s*/g, "");
|
|
52
|
+
s = s.replace(/@group\(\d+\)\s*@binding\(\d+\)\s*var<uniform>\s+_w_uniform\s*:\s*_UB_uniform\s*;?\s*/g, "");
|
|
53
|
+
// 2. Redirect uniform reads to inter-stage. _w_uniform.LightLocation
|
|
54
|
+
// → in.lightLoc.
|
|
55
|
+
s = s.replace(/_w_uniform\.(\w+)/g, (_m, name) => "in." + uniformToVsOut(name));
|
|
56
|
+
// 3. Locate the @fragment function signature; capture the input
|
|
57
|
+
// struct name + output struct name from the signature itself.
|
|
58
|
+
// Two emit shapes seen in practice:
|
|
59
|
+
// - inline-marker: `wombat_fragment_<hash>` + `Wombat_fragment_<hash>{Input,Output}`
|
|
60
|
+
// - direct stage(): `<fnName>` + `<FnName>{Input,Output}`
|
|
61
|
+
// Detecting from the signature works for both.
|
|
62
|
+
const fnSigMatch = s.match(/@fragment\s+fn\s+(\w+)\s*\(\s*(\w+)\s*:\s*(\w+)\s*\)\s*->\s*(\w+)\s*\{/);
|
|
63
|
+
if (fnSigMatch === null) {
|
|
64
|
+
throw new Error("compileHeapFragment: emitted WGSL has no @fragment function header");
|
|
65
|
+
}
|
|
66
|
+
const fnHeader = fnSigMatch[0];
|
|
67
|
+
const paramName = fnSigMatch[2];
|
|
68
|
+
const inputStructName = fnSigMatch[3];
|
|
69
|
+
const outputStructName = fnSigMatch[4];
|
|
70
|
+
// 4. Drop the input struct.
|
|
71
|
+
const inputStructRe = new RegExp(`struct\\s+${escapeRegExp(inputStructName)}\\s*\\{[\\s\\S]*?\\};?`);
|
|
72
|
+
s = s.replace(inputStructRe, "");
|
|
73
|
+
// 5. Capture + drop the output struct, recording its (single) field name.
|
|
74
|
+
const outputStructRe = new RegExp(`struct\\s+${escapeRegExp(outputStructName)}\\s*\\{([\\s\\S]*?)\\};?`);
|
|
75
|
+
const outputMatch = s.match(outputStructRe);
|
|
76
|
+
if (outputMatch === null) {
|
|
77
|
+
throw new Error(`compileHeapFragment: cannot locate output struct '${outputStructName}'`);
|
|
78
|
+
}
|
|
79
|
+
const outputBody = outputMatch[1];
|
|
80
|
+
const fieldRe = /@location\(0\)\s+(\w+)\s*:\s*vec4<f32>\s*,?/g;
|
|
81
|
+
const fieldMatches = [...outputBody.matchAll(fieldRe)];
|
|
82
|
+
if (fieldMatches.length !== 1) {
|
|
83
|
+
throw new Error(`compileHeapFragment: fragment output must be a single @location(0) vec4<f32> field; got ${fieldMatches.length} field(s)`);
|
|
84
|
+
}
|
|
85
|
+
const outputFieldName = fieldMatches[0][1];
|
|
86
|
+
s = s.replace(outputMatch[0], "");
|
|
87
|
+
// 6. Rewrite the function header to the heap-scene shape. Any parameter
|
|
88
|
+
// name (in, input, …) is renormalised to `in` so the user shader's
|
|
89
|
+
// field references work uniformly downstream.
|
|
90
|
+
s = s.replace(fnHeader, "@fragment\nfn fs(in: VsOut) -> @location(0) vec4<f32> {");
|
|
91
|
+
if (paramName !== "in") {
|
|
92
|
+
// Rewrite `paramName.X` references to `in.X`.
|
|
93
|
+
const paramRe = new RegExp(`\\b${escapeRegExp(paramName)}\\.`, "g");
|
|
94
|
+
s = s.replace(paramRe, "in.");
|
|
95
|
+
}
|
|
96
|
+
// 7. Rewrite the body's `out: <Output>; ... out.<field> = expr; return out;` to
|
|
97
|
+
// return expr directly. wombat.shader's emit always uses this pattern; we
|
|
98
|
+
// transform it via two passes (capture the assignment, drop the var/return).
|
|
99
|
+
const fieldRef = `out\\.${escapeRegExp(outputFieldName)}`;
|
|
100
|
+
const assignRe = new RegExp(`var\\s+out\\s*:\\s*${escapeRegExp(outputStructName)}\\s*;([\\s\\S]*?)${fieldRef}\\s*=\\s*([\\s\\S]*?);([\\s\\S]*?)return\\s+out\\s*;`);
|
|
101
|
+
const assignMatch = s.match(assignRe);
|
|
102
|
+
if (assignMatch === null) {
|
|
103
|
+
// Fall back: if user wrote a more exotic body we surface a clear error.
|
|
104
|
+
throw new Error("compileHeapFragment: emitted body doesn't follow the var-out / out." + outputFieldName +
|
|
105
|
+
" = ... / return out pattern (got unsupported emit shape)");
|
|
106
|
+
}
|
|
107
|
+
const beforeAssign = assignMatch[1]; // statements between var-out decl and the field assignment
|
|
108
|
+
const expr = assignMatch[2];
|
|
109
|
+
const afterAssign = assignMatch[3]; // statements between the assignment and the return
|
|
110
|
+
s = s.replace(assignMatch[0], beforeAssign + afterAssign + `return ${expr};`);
|
|
111
|
+
// 8. Map references `in.<DslField>` to the corresponding heap VsOut
|
|
112
|
+
// field name (a 1:1 mapping when the user's input struct uses
|
|
113
|
+
// the canonical field names; identity otherwise).
|
|
114
|
+
s = s.replace(/in\.(\w+)/g, (_m, name) => "in." + dslFieldToVsOut(name));
|
|
115
|
+
// 9. Tidy: collapse 3+ blank lines to one.
|
|
116
|
+
s = s.replace(/\n{3,}/g, "\n\n").trimStart();
|
|
117
|
+
return s;
|
|
118
|
+
}
|
|
119
|
+
// Map a DSL uniform name to the heap-scene VsOut field that carries
|
|
120
|
+
// it. Today only `LightLocation` rides on VsOut; everything else
|
|
121
|
+
// would need to be added to the VS prelude in heapScene.ts.
|
|
122
|
+
function escapeRegExp(s) {
|
|
123
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
124
|
+
}
|
|
125
|
+
function uniformToVsOut(name) {
|
|
126
|
+
switch (name) {
|
|
127
|
+
case "LightLocation": return "lightLoc";
|
|
128
|
+
default:
|
|
129
|
+
throw new Error(`compileHeapFragment: uniform '${name}' is not carried on VsOut. Either thread it through the VS or use a fragment that doesn't read it.`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// Map an inter-stage name from the DSL convention (PascalCase, e.g.
|
|
133
|
+
// 'Normals', 'WorldPositions') or our preferred direct names
|
|
134
|
+
// ('normal', 'worldPos') to the canonical VsOut field name.
|
|
135
|
+
function dslFieldToVsOut(name) {
|
|
136
|
+
switch (name) {
|
|
137
|
+
// canonical heap-scene names — pass through.
|
|
138
|
+
case "worldPos":
|
|
139
|
+
case "normal":
|
|
140
|
+
case "color":
|
|
141
|
+
case "lightLoc":
|
|
142
|
+
return name;
|
|
143
|
+
// legacy PascalCase from the wombat.dom convention — auto-translate
|
|
144
|
+
// so users can copy DSL effects from the per-RO path with minimal edits.
|
|
145
|
+
case "WorldPositions": return "worldPos";
|
|
146
|
+
case "WorldPosition": return "worldPos";
|
|
147
|
+
case "Normals": return "normal";
|
|
148
|
+
case "Normal": return "normal";
|
|
149
|
+
case "Colors": return "color";
|
|
150
|
+
case "Color": return "color";
|
|
151
|
+
case "LightLocation": return "lightLoc";
|
|
152
|
+
default:
|
|
153
|
+
throw new Error(`compileHeapFragment: input field '${name}' has no mapping to VsOut. ` +
|
|
154
|
+
`Use one of: worldPos, normal, color, lightLoc.`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=heapShader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heapShader.js","sourceRoot":"","sources":["../../src/runtime/heapShader.ts"],"names":[],"mappings":"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"}
|
package/dist/runtime/index.d.ts
CHANGED
|
@@ -3,4 +3,6 @@ export { compileRenderTask, type RuntimeContext, } from "./renderTask.js";
|
|
|
3
3
|
export { copy } from "./copy.js";
|
|
4
4
|
export { renderTo, type RenderToOptions, type RenderToResult, } from "./renderTo.js";
|
|
5
5
|
export { ScenePass, type WalkerStats, } from "./scenePass.js";
|
|
6
|
+
export { buildHeapScene, type HeapScene, type HeapSceneStats, type HeapDrawSpec, type HeapGeometry, type HeapTextureSet, type BuildHeapSceneOptions, } from "./heapScene.js";
|
|
7
|
+
export { compileHeapFragment } from "./heapShader.js";
|
|
6
8
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,OAAO,EACP,KAAK,cAAc,GACpB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,iBAAiB,EACjB,KAAK,cAAc,GACpB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EACL,QAAQ,EACR,KAAK,eAAe,EACpB,KAAK,cAAc,GACpB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,SAAS,EACT,KAAK,WAAW,GACjB,MAAM,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,OAAO,EACP,KAAK,cAAc,GACpB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,iBAAiB,EACjB,KAAK,cAAc,GACpB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EACL,QAAQ,EACR,KAAK,eAAe,EACpB,KAAK,cAAc,GACpB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,SAAS,EACT,KAAK,WAAW,GACjB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,cAAc,EACd,KAAK,SAAS,EACd,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,qBAAqB,GAC3B,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC"}
|
package/dist/runtime/index.js
CHANGED
|
@@ -4,4 +4,6 @@ export { compileRenderTask, } from "./renderTask.js";
|
|
|
4
4
|
export { copy } from "./copy.js";
|
|
5
5
|
export { renderTo, } from "./renderTo.js";
|
|
6
6
|
export { ScenePass, } from "./scenePass.js";
|
|
7
|
+
export { buildHeapScene, } from "./heapScene.js";
|
|
8
|
+
export { compileHeapFragment } from "./heapShader.js";
|
|
7
9
|
//# sourceMappingURL=index.js.map
|