wgsl-renderer 0.0.2 → 0.0.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 +236 -228
- package/README.zh-CN.md +417 -0
- package/dist/cjs/index.js +111 -114
- package/dist/esm/index.d.ts +154 -0
- package/dist/esm/index.js +111 -114
- package/package.json +6 -4
- package/dist/types/index.d.ts +0 -85
- package/dist/types/index.js +0 -434
package/dist/cjs/index.js
CHANGED
|
@@ -7,13 +7,12 @@ var RenderPass = class {
|
|
|
7
7
|
vertexBuffer;
|
|
8
8
|
clearColor;
|
|
9
9
|
blendMode;
|
|
10
|
-
|
|
10
|
+
view;
|
|
11
|
+
format;
|
|
11
12
|
passResources = [];
|
|
12
13
|
device;
|
|
13
|
-
originalBindGroupEntries;
|
|
14
14
|
constructor(descriptor, device, format, layout) {
|
|
15
15
|
this.device = device;
|
|
16
|
-
this.originalBindGroupEntries = [...descriptor.bindGroupEntries || []];
|
|
17
16
|
this.name = descriptor.name;
|
|
18
17
|
this.clearColor = descriptor.clearColor || {
|
|
19
18
|
r: 0,
|
|
@@ -21,7 +20,10 @@ var RenderPass = class {
|
|
|
21
20
|
b: 0,
|
|
22
21
|
a: 1
|
|
23
22
|
};
|
|
24
|
-
this.blendMode = descriptor.blendMode || "
|
|
23
|
+
this.blendMode = descriptor.blendMode || "none";
|
|
24
|
+
this.view = descriptor.view;
|
|
25
|
+
this.format = descriptor.format;
|
|
26
|
+
const actualFormat = descriptor.format || format;
|
|
25
27
|
const module$1 = this.device.createShaderModule({ code: descriptor.shaderCode });
|
|
26
28
|
this.vertexBuffer = this.device.createBuffer({
|
|
27
29
|
size: 36,
|
|
@@ -40,11 +42,13 @@ var RenderPass = class {
|
|
|
40
42
|
0
|
|
41
43
|
]);
|
|
42
44
|
this.vertexBuffer.unmap();
|
|
45
|
+
const vertexEntryPoint = descriptor.entryPoints?.vertex || "vs_main";
|
|
46
|
+
const fragmentEntryPoint = descriptor.entryPoints?.fragment || "fs_main";
|
|
43
47
|
this.pipeline = this.device.createRenderPipeline({
|
|
44
48
|
layout,
|
|
45
49
|
vertex: {
|
|
46
50
|
module: module$1,
|
|
47
|
-
entryPoint:
|
|
51
|
+
entryPoint: vertexEntryPoint,
|
|
48
52
|
buffers: [{
|
|
49
53
|
arrayStride: 12,
|
|
50
54
|
attributes: [{
|
|
@@ -56,26 +60,21 @@ var RenderPass = class {
|
|
|
56
60
|
},
|
|
57
61
|
fragment: {
|
|
58
62
|
module: module$1,
|
|
59
|
-
entryPoint:
|
|
63
|
+
entryPoint: fragmentEntryPoint,
|
|
60
64
|
targets: [{
|
|
61
|
-
format,
|
|
65
|
+
format: actualFormat,
|
|
62
66
|
blend: this.getBlendState()
|
|
63
67
|
}]
|
|
64
68
|
},
|
|
65
69
|
primitive: { topology: "triangle-list" }
|
|
66
70
|
});
|
|
67
|
-
|
|
68
|
-
this.bindGroup = this.device.createBindGroup({
|
|
69
|
-
layout: bindGroupLayout,
|
|
70
|
-
entries: this.originalBindGroupEntries
|
|
71
|
-
});
|
|
71
|
+
this.bindGroup = null;
|
|
72
72
|
}
|
|
73
73
|
/**
|
|
74
74
|
* Update bind group with new entries (e.g., after texture resize)
|
|
75
75
|
*/
|
|
76
76
|
updateBindGroup(newEntries) {
|
|
77
77
|
const bindGroupLayout = this.pipeline.getBindGroupLayout(0);
|
|
78
|
-
this.originalBindGroupEntries = [...newEntries];
|
|
79
78
|
this.bindGroup = this.device.createBindGroup({
|
|
80
79
|
layout: bindGroupLayout,
|
|
81
80
|
entries: newEntries
|
|
@@ -132,21 +131,17 @@ var TextureManager = class {
|
|
|
132
131
|
device;
|
|
133
132
|
width;
|
|
134
133
|
height;
|
|
135
|
-
oldTextures = [];
|
|
136
134
|
constructor(device, width, height) {
|
|
137
135
|
this.device = device;
|
|
138
136
|
this.width = width;
|
|
139
137
|
this.height = height;
|
|
140
138
|
}
|
|
141
139
|
createTexture(name, format) {
|
|
142
|
-
if (this.textures.has(name))
|
|
143
|
-
const oldTexture = this.textures.get(name);
|
|
144
|
-
this.oldTextures.push(oldTexture);
|
|
145
|
-
}
|
|
140
|
+
if (this.textures.has(name)) this.textures.get(name).destroy();
|
|
146
141
|
const texture = this.device.createTexture({
|
|
147
142
|
size: [this.width, this.height],
|
|
148
143
|
format: format || "bgra8unorm",
|
|
149
|
-
usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING
|
|
144
|
+
usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST
|
|
150
145
|
});
|
|
151
146
|
this.textures.set(name, texture);
|
|
152
147
|
return texture;
|
|
@@ -159,37 +154,13 @@ var TextureManager = class {
|
|
|
159
154
|
this.width = width;
|
|
160
155
|
this.height = height;
|
|
161
156
|
this.textures.forEach((texture) => {
|
|
162
|
-
this.oldTextures.push(texture);
|
|
163
|
-
});
|
|
164
|
-
this.textures.clear();
|
|
165
|
-
}
|
|
166
|
-
/**
|
|
167
|
-
* Recreate a specific texture with current dimensions
|
|
168
|
-
*/
|
|
169
|
-
recreateTexture(name, format) {
|
|
170
|
-
const texture = this.device.createTexture({
|
|
171
|
-
size: [this.width, this.height],
|
|
172
|
-
format: format || "bgra8unorm",
|
|
173
|
-
usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING
|
|
174
|
-
});
|
|
175
|
-
this.textures.set(name, texture);
|
|
176
|
-
return texture;
|
|
177
|
-
}
|
|
178
|
-
/**
|
|
179
|
-
* Clean up old textures that are no longer needed
|
|
180
|
-
* Call this after ensuring GPU work is complete
|
|
181
|
-
*/
|
|
182
|
-
cleanupOldTextures() {
|
|
183
|
-
this.oldTextures.forEach((texture) => {
|
|
184
157
|
texture.destroy();
|
|
185
158
|
});
|
|
186
|
-
this.
|
|
159
|
+
this.textures.clear();
|
|
187
160
|
}
|
|
188
161
|
destroy() {
|
|
189
162
|
this.textures.forEach((texture) => texture.destroy());
|
|
190
163
|
this.textures.clear();
|
|
191
|
-
this.oldTextures.forEach((texture) => texture.destroy());
|
|
192
|
-
this.oldTextures.length = 0;
|
|
193
164
|
}
|
|
194
165
|
getPixelSize() {
|
|
195
166
|
return {
|
|
@@ -199,6 +170,30 @@ var TextureManager = class {
|
|
|
199
170
|
}
|
|
200
171
|
};
|
|
201
172
|
|
|
173
|
+
//#endregion
|
|
174
|
+
//#region src/PassTextureRef.ts
|
|
175
|
+
const PASS_TEXTURE_REF_SYMBOL = Symbol("PassTextureRef");
|
|
176
|
+
var PassTextureRef = class PassTextureRef {
|
|
177
|
+
[PASS_TEXTURE_REF_SYMBOL] = true;
|
|
178
|
+
passName;
|
|
179
|
+
constructor(passName) {
|
|
180
|
+
this.passName = passName;
|
|
181
|
+
}
|
|
182
|
+
static is(obj) {
|
|
183
|
+
return obj && typeof obj === "object" && PASS_TEXTURE_REF_SYMBOL in obj;
|
|
184
|
+
}
|
|
185
|
+
static fromGPUBindingResource(resource) {
|
|
186
|
+
if (this.is(resource)) return resource;
|
|
187
|
+
return null;
|
|
188
|
+
}
|
|
189
|
+
static create(passName) {
|
|
190
|
+
return new PassTextureRef(passName);
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
function isPassTextureRef(obj) {
|
|
194
|
+
return PassTextureRef.is(obj);
|
|
195
|
+
}
|
|
196
|
+
|
|
202
197
|
//#endregion
|
|
203
198
|
//#region src/index.ts
|
|
204
199
|
var WGSLRenderer = class {
|
|
@@ -230,19 +225,17 @@ var WGSLRenderer = class {
|
|
|
230
225
|
}
|
|
231
226
|
async resize(width, height) {
|
|
232
227
|
if (this.isResizing) return;
|
|
233
|
-
|
|
234
|
-
if (currentSize.width === width && currentSize.height === height) return;
|
|
228
|
+
if (this.canvas.width === width && this.canvas.height === height) return;
|
|
235
229
|
this.isResizing = true;
|
|
236
230
|
this.canvas.width = width;
|
|
237
231
|
this.canvas.height = height;
|
|
238
232
|
const future = this.device.queue.onSubmittedWorkDone();
|
|
239
233
|
future.catch(() => {
|
|
234
|
+
console.warn("GPU work submission failed during resize.");
|
|
240
235
|
this.isResizing = false;
|
|
241
236
|
});
|
|
242
237
|
await future;
|
|
243
|
-
this.textureManager.cleanupOldTextures();
|
|
244
238
|
this.textureManager.resize(width, height);
|
|
245
|
-
this.updateAllBindGroups();
|
|
246
239
|
this.isResizing = false;
|
|
247
240
|
}
|
|
248
241
|
getContext() {
|
|
@@ -252,84 +245,79 @@ var WGSLRenderer = class {
|
|
|
252
245
|
return this.device;
|
|
253
246
|
}
|
|
254
247
|
/**
|
|
255
|
-
*
|
|
248
|
+
* Get texture reference by pass name
|
|
249
|
+
* Returns a PassTextureRef that will resolve to the actual texture at render time
|
|
256
250
|
*/
|
|
257
|
-
|
|
258
|
-
this.
|
|
259
|
-
|
|
260
|
-
const finalBindGroupEntries = [];
|
|
261
|
-
if (index >= 1) {
|
|
262
|
-
const previousOutputTextureName = `pass_${index - 1}_output`;
|
|
263
|
-
let previousOutput = this.textureManager.getTexture(previousOutputTextureName);
|
|
264
|
-
if (!previousOutput) previousOutput = this.textureManager.recreateTexture(previousOutputTextureName, this.format);
|
|
265
|
-
finalBindGroupEntries.push({
|
|
266
|
-
binding: 0,
|
|
267
|
-
resource: previousOutput.createView()
|
|
268
|
-
});
|
|
269
|
-
}
|
|
270
|
-
if (pass.passResources) pass.passResources.forEach((resource, resourceIndex) => {
|
|
271
|
-
finalBindGroupEntries.push({
|
|
272
|
-
binding: resourceIndex + 1,
|
|
273
|
-
resource
|
|
274
|
-
});
|
|
275
|
-
});
|
|
276
|
-
pass.updateBindGroup(finalBindGroupEntries);
|
|
277
|
-
});
|
|
251
|
+
getPassTexture(passName) {
|
|
252
|
+
if (!this.passes.find((pass) => pass.name === passName)) throw new Error(`Cannot find pass named '${passName}'. Available passes: [${this.passes.map((p) => p.name).join(", ")}]`);
|
|
253
|
+
return PassTextureRef.create(passName);
|
|
278
254
|
}
|
|
279
255
|
/**
|
|
280
|
-
*
|
|
256
|
+
* Resolve a PassTextureRef to actual GPUTextureView with validation
|
|
281
257
|
*/
|
|
282
|
-
|
|
283
|
-
this.passes.
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
258
|
+
resolveTextureRef(ref) {
|
|
259
|
+
const targetPassIndex = this.passes.findIndex((pass) => pass.name === ref.passName);
|
|
260
|
+
if (targetPassIndex === -1) throw new Error(`Cannot find pass named '${ref.passName}'. Available passes: [${this.passes.map((p) => p.name).join(", ")}]`);
|
|
261
|
+
const textureName = `pass_${targetPassIndex}_output`;
|
|
262
|
+
let texture = this.textureManager.getTexture(textureName);
|
|
263
|
+
if (!texture) texture = this.textureManager.createTexture(textureName, this.format);
|
|
264
|
+
return texture.createView();
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Get pass by name
|
|
268
|
+
*/
|
|
269
|
+
getPassByName(passName) {
|
|
270
|
+
return this.passes.find((pass) => pass.name === passName);
|
|
289
271
|
}
|
|
290
272
|
/**
|
|
291
273
|
* Add a render pass to the multi-pass pipeline
|
|
292
274
|
*/
|
|
293
275
|
addPass(descriptor) {
|
|
294
276
|
const finalBindGroupEntries = [];
|
|
295
|
-
|
|
296
|
-
if (!firstPass) {
|
|
297
|
-
const previousOutput = this.getPassOutput(this.passes.length - 1);
|
|
298
|
-
if (previousOutput) finalBindGroupEntries.push({
|
|
299
|
-
binding: 0,
|
|
300
|
-
resource: previousOutput.createView()
|
|
301
|
-
});
|
|
302
|
-
}
|
|
303
|
-
descriptor.resources.forEach((resource, index) => {
|
|
277
|
+
descriptor.resources?.forEach((resource, index) => {
|
|
304
278
|
finalBindGroupEntries.push({
|
|
305
|
-
binding: index
|
|
279
|
+
binding: index,
|
|
306
280
|
resource
|
|
307
281
|
});
|
|
308
282
|
});
|
|
309
|
-
const
|
|
283
|
+
const internalDescriptor = {
|
|
310
284
|
name: descriptor.name,
|
|
311
285
|
shaderCode: descriptor.shaderCode,
|
|
286
|
+
entryPoints: descriptor.entryPoints,
|
|
312
287
|
clearColor: descriptor.clearColor,
|
|
313
288
|
blendMode: descriptor.blendMode,
|
|
314
|
-
bindGroupEntries: finalBindGroupEntries
|
|
315
|
-
|
|
316
|
-
|
|
289
|
+
bindGroupEntries: finalBindGroupEntries,
|
|
290
|
+
view: descriptor.view,
|
|
291
|
+
format: descriptor.format
|
|
292
|
+
};
|
|
293
|
+
const pipelineFormat = descriptor.format || this.format;
|
|
294
|
+
const pass = new RenderPass(internalDescriptor, this.device, pipelineFormat, "auto");
|
|
295
|
+
pass.passResources = descriptor.resources ?? [];
|
|
317
296
|
this.passes.push(pass);
|
|
318
|
-
const currentPassIndex = this.passes.length - 1;
|
|
319
|
-
const textureName = `pass_${currentPassIndex}_output`;
|
|
320
|
-
this.textureManager.createTexture(textureName, this.format);
|
|
321
|
-
this.passes[currentPassIndex].hasOutputTexture = true;
|
|
322
297
|
}
|
|
323
298
|
/**
|
|
324
|
-
*
|
|
299
|
+
* Resolve resource to actual GPU binding resource
|
|
300
|
+
* Handles PassTextureRef by getting the current texture view with validation
|
|
325
301
|
*/
|
|
326
|
-
|
|
327
|
-
if (
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
302
|
+
resolveResource(resource) {
|
|
303
|
+
if (isPassTextureRef(resource)) return this.resolveTextureRef(resource);
|
|
304
|
+
return resource;
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Update bind groups to resolve current texture references
|
|
308
|
+
* Call this before rendering to ensure all PassTextureRef are resolved
|
|
309
|
+
*/
|
|
310
|
+
updateBindGroups() {
|
|
311
|
+
this.passes.forEach((pass) => {
|
|
312
|
+
const finalBindGroupEntries = [];
|
|
313
|
+
pass.passResources.forEach((resource, index) => {
|
|
314
|
+
if (resource) finalBindGroupEntries.push({
|
|
315
|
+
binding: index,
|
|
316
|
+
resource: this.resolveResource(resource)
|
|
317
|
+
});
|
|
318
|
+
});
|
|
319
|
+
pass.updateBindGroup(finalBindGroupEntries);
|
|
320
|
+
});
|
|
333
321
|
}
|
|
334
322
|
/**
|
|
335
323
|
* Create a uniforms
|
|
@@ -367,7 +355,11 @@ var WGSLRenderer = class {
|
|
|
367
355
|
console.error("Failed to load texture:", err);
|
|
368
356
|
});
|
|
369
357
|
const res = await resp;
|
|
370
|
-
const
|
|
358
|
+
const future = createImageBitmap(await res.blob());
|
|
359
|
+
future.catch((err) => {
|
|
360
|
+
console.error("Failed to load texture:", err);
|
|
361
|
+
});
|
|
362
|
+
const imgBitmap = await future;
|
|
371
363
|
const texture = this.device.createTexture({
|
|
372
364
|
size: [
|
|
373
365
|
imgBitmap.width,
|
|
@@ -386,22 +378,25 @@ var WGSLRenderer = class {
|
|
|
386
378
|
}
|
|
387
379
|
renderFrame() {
|
|
388
380
|
if (this.passes.length === 0) return;
|
|
381
|
+
this.updateBindGroups();
|
|
389
382
|
const commandEncoder = this.device.createCommandEncoder();
|
|
390
383
|
for (let i = 0; i < this.passes.length; i++) {
|
|
391
384
|
const pass = this.passes[i];
|
|
385
|
+
let loadOp = "load";
|
|
386
|
+
const isLast = i === this.passes.length - 1;
|
|
387
|
+
if (isLast) loadOp = "clear";
|
|
392
388
|
let renderTarget;
|
|
393
|
-
|
|
394
|
-
if (
|
|
389
|
+
if (pass.view) renderTarget = pass.view;
|
|
390
|
+
else if (isLast) renderTarget = this.ctx.getCurrentTexture().createView();
|
|
395
391
|
else {
|
|
396
392
|
const textureName = `pass_${i}_output`;
|
|
397
|
-
|
|
398
|
-
if (!texture)
|
|
393
|
+
let texture = this.textureManager.getTexture(textureName);
|
|
394
|
+
if (!texture) texture = this.textureManager.createTexture(textureName, "rgba16float");
|
|
399
395
|
renderTarget = texture.createView();
|
|
400
|
-
loadOp = "load";
|
|
401
396
|
}
|
|
402
397
|
const renderPass = commandEncoder.beginRenderPass({ colorAttachments: [{
|
|
403
398
|
view: renderTarget,
|
|
404
|
-
loadOp
|
|
399
|
+
loadOp,
|
|
405
400
|
storeOp: "store",
|
|
406
401
|
clearValue: pass.clearColor
|
|
407
402
|
}] });
|
|
@@ -414,9 +409,11 @@ var WGSLRenderer = class {
|
|
|
414
409
|
this.device.queue.submit([commandEncoder.finish()]);
|
|
415
410
|
}
|
|
416
411
|
loopRender(cb) {
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
412
|
+
this.animationFrameId = requestAnimationFrame((t) => {
|
|
413
|
+
cb?.(t);
|
|
414
|
+
this.renderFrame();
|
|
415
|
+
this.loopRender(cb);
|
|
416
|
+
});
|
|
420
417
|
}
|
|
421
418
|
stopLoop() {
|
|
422
419
|
if (this.animationFrameId !== null) {
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
//#region src/PassTextureRef.d.ts
|
|
2
|
+
declare const PASS_TEXTURE_REF_SYMBOL: unique symbol;
|
|
3
|
+
declare class PassTextureRef {
|
|
4
|
+
readonly [PASS_TEXTURE_REF_SYMBOL] = true;
|
|
5
|
+
readonly passName: string;
|
|
6
|
+
constructor(passName: string);
|
|
7
|
+
static is(obj: any): obj is PassTextureRef;
|
|
8
|
+
static fromGPUBindingResource(resource: GPUBindingResource): PassTextureRef | null;
|
|
9
|
+
static create(passName: string): PassTextureRef;
|
|
10
|
+
}
|
|
11
|
+
//#endregion
|
|
12
|
+
//#region src/RenderPass.d.ts
|
|
13
|
+
type BandingResource = GPUBindingResource | PassTextureRef;
|
|
14
|
+
type BindingEntry = {
|
|
15
|
+
binding: number;
|
|
16
|
+
resource: BandingResource;
|
|
17
|
+
};
|
|
18
|
+
interface RenderPassOptions {
|
|
19
|
+
name: string;
|
|
20
|
+
shaderCode: string;
|
|
21
|
+
entryPoints?: {
|
|
22
|
+
vertex?: string;
|
|
23
|
+
fragment?: string;
|
|
24
|
+
};
|
|
25
|
+
clearColor?: {
|
|
26
|
+
r: number;
|
|
27
|
+
g: number;
|
|
28
|
+
b: number;
|
|
29
|
+
a: number;
|
|
30
|
+
};
|
|
31
|
+
blendMode?: 'additive' | 'alpha' | 'multiply' | 'none';
|
|
32
|
+
resources?: BandingResource[];
|
|
33
|
+
view?: GPUTextureView;
|
|
34
|
+
format?: GPUTextureFormat;
|
|
35
|
+
}
|
|
36
|
+
interface InternalRenderPassDescriptor {
|
|
37
|
+
name: string;
|
|
38
|
+
shaderCode: string;
|
|
39
|
+
entryPoints?: {
|
|
40
|
+
vertex?: string;
|
|
41
|
+
fragment?: string;
|
|
42
|
+
};
|
|
43
|
+
clearColor?: {
|
|
44
|
+
r: number;
|
|
45
|
+
g: number;
|
|
46
|
+
b: number;
|
|
47
|
+
a: number;
|
|
48
|
+
};
|
|
49
|
+
blendMode?: 'additive' | 'alpha' | 'multiply' | 'none';
|
|
50
|
+
bindGroupEntries: BindingEntry[];
|
|
51
|
+
view?: GPUTextureView;
|
|
52
|
+
format?: GPUTextureFormat;
|
|
53
|
+
}
|
|
54
|
+
declare class RenderPass {
|
|
55
|
+
name: string;
|
|
56
|
+
pipeline: GPURenderPipeline;
|
|
57
|
+
bindGroup: GPUBindGroup | null;
|
|
58
|
+
vertexBuffer: GPUBuffer;
|
|
59
|
+
clearColor: {
|
|
60
|
+
r: number;
|
|
61
|
+
g: number;
|
|
62
|
+
b: number;
|
|
63
|
+
a: number;
|
|
64
|
+
};
|
|
65
|
+
blendMode: 'additive' | 'alpha' | 'multiply' | 'none';
|
|
66
|
+
view?: GPUTextureView;
|
|
67
|
+
format?: GPUTextureFormat;
|
|
68
|
+
passResources: BandingResource[];
|
|
69
|
+
private device;
|
|
70
|
+
constructor(descriptor: InternalRenderPassDescriptor, device: GPUDevice, format: GPUTextureFormat, layout: GPUPipelineLayout | 'auto');
|
|
71
|
+
/**
|
|
72
|
+
* Update bind group with new entries (e.g., after texture resize)
|
|
73
|
+
*/
|
|
74
|
+
updateBindGroup(newEntries: BindingEntry[]): void;
|
|
75
|
+
private getBlendState;
|
|
76
|
+
}
|
|
77
|
+
//#endregion
|
|
78
|
+
//#region src/index.d.ts
|
|
79
|
+
interface MultiPassDescriptor {
|
|
80
|
+
passes: RenderPassOptions[];
|
|
81
|
+
}
|
|
82
|
+
interface WGSLRendererOptions {
|
|
83
|
+
config?: GPUCanvasConfiguration;
|
|
84
|
+
}
|
|
85
|
+
declare class WGSLRenderer {
|
|
86
|
+
canvas: HTMLCanvasElement;
|
|
87
|
+
options?: WGSLRendererOptions | undefined;
|
|
88
|
+
private ctx;
|
|
89
|
+
private device;
|
|
90
|
+
private format;
|
|
91
|
+
private passes;
|
|
92
|
+
private textureManager;
|
|
93
|
+
private animationFrameId;
|
|
94
|
+
private isResizing;
|
|
95
|
+
constructor(canvas: HTMLCanvasElement, options?: WGSLRendererOptions | undefined);
|
|
96
|
+
init(): Promise<void>;
|
|
97
|
+
resize(width: number, height: number): Promise<void>;
|
|
98
|
+
getContext(): GPUCanvasContext;
|
|
99
|
+
getDevice(): GPUDevice;
|
|
100
|
+
/**
|
|
101
|
+
* Get texture reference by pass name
|
|
102
|
+
* Returns a PassTextureRef that will resolve to the actual texture at render time
|
|
103
|
+
*/
|
|
104
|
+
getPassTexture(passName: string): PassTextureRef;
|
|
105
|
+
/**
|
|
106
|
+
* Resolve a PassTextureRef to actual GPUTextureView with validation
|
|
107
|
+
*/
|
|
108
|
+
private resolveTextureRef;
|
|
109
|
+
/**
|
|
110
|
+
* Get pass by name
|
|
111
|
+
*/
|
|
112
|
+
getPassByName(passName: string): RenderPass | undefined;
|
|
113
|
+
/**
|
|
114
|
+
* Add a render pass to the multi-pass pipeline
|
|
115
|
+
*/
|
|
116
|
+
addPass(descriptor: RenderPassOptions): void;
|
|
117
|
+
/**
|
|
118
|
+
* Resolve resource to actual GPU binding resource
|
|
119
|
+
* Handles PassTextureRef by getting the current texture view with validation
|
|
120
|
+
*/
|
|
121
|
+
private resolveResource;
|
|
122
|
+
/**
|
|
123
|
+
* Update bind groups to resolve current texture references
|
|
124
|
+
* Call this before rendering to ensure all PassTextureRef are resolved
|
|
125
|
+
*/
|
|
126
|
+
private updateBindGroups;
|
|
127
|
+
/**
|
|
128
|
+
* Create a uniforms
|
|
129
|
+
* @param length The length of the uniform buffer in number of floats
|
|
130
|
+
* @return The uniform object containing the buffer and data array
|
|
131
|
+
*/
|
|
132
|
+
createUniforms(length: number): {
|
|
133
|
+
values: Float32Array<ArrayBuffer>;
|
|
134
|
+
apply: () => void;
|
|
135
|
+
getBuffer: () => GPUBuffer;
|
|
136
|
+
};
|
|
137
|
+
/**
|
|
138
|
+
* Create a sampler
|
|
139
|
+
*/
|
|
140
|
+
createSampler(options?: GPUSamplerDescriptor): GPUSampler;
|
|
141
|
+
loadImageTexture(url: string): Promise<{
|
|
142
|
+
texture: GPUTexture;
|
|
143
|
+
width: number;
|
|
144
|
+
height: number;
|
|
145
|
+
}>;
|
|
146
|
+
renderFrame(): void;
|
|
147
|
+
loopRender(cb?: {
|
|
148
|
+
(t?: number): void;
|
|
149
|
+
}): void;
|
|
150
|
+
stopLoop(): void;
|
|
151
|
+
}
|
|
152
|
+
declare function createWGSLRenderer(cvs: HTMLCanvasElement, options?: WGSLRendererOptions): Promise<WGSLRenderer>;
|
|
153
|
+
//#endregion
|
|
154
|
+
export { MultiPassDescriptor, createWGSLRenderer };
|