@driftengine/core 4.4.1 → 4.5.0
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.json +72 -0
- package/README.md +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +7 -0
- package/dist/render/backend/api.d.ts +17 -11
- package/dist/render/backend/webgl2/glassTintPrograms.d.ts +13 -0
- package/dist/render/backend/webgl2/glassTintPrograms.js +38 -0
- package/dist/render/backend/webgl2/renderer.d.ts +82 -8
- package/dist/render/backend/webgl2/renderer.js +373 -105
- package/dist/render/backend/webgpu/buffers.d.ts +19 -1
- package/dist/render/backend/webgpu/buffers.js +27 -1
- package/dist/render/backend/webgpu/depthPass.d.ts +1 -1
- package/dist/render/backend/webgpu/depthPass.js +2 -1
- package/dist/render/backend/webgpu/flatPass.d.ts +2 -0
- package/dist/render/backend/webgpu/flatPass.js +20 -1
- package/dist/render/backend/webgpu/glassTintPass.d.ts +28 -0
- package/dist/render/backend/webgpu/glassTintPass.js +205 -0
- package/dist/render/backend/webgpu/gpuDrivenPass.d.ts +60 -1
- package/dist/render/backend/webgpu/gpuDrivenPass.js +305 -5
- package/dist/render/backend/webgpu/instanced.d.ts +12 -1
- package/dist/render/backend/webgpu/instanced.js +20 -1
- package/dist/render/backend/webgpu/latePass.d.ts +26 -0
- package/dist/render/backend/webgpu/latePass.js +133 -0
- package/dist/render/backend/webgpu/lightVolumePass.js +5 -1
- package/dist/render/backend/webgpu/motionPass.d.ts +95 -0
- package/dist/render/backend/webgpu/motionPass.js +491 -0
- package/dist/render/backend/webgpu/pipelineCache.d.ts +10 -1
- package/dist/render/backend/webgpu/pipelineCache.js +11 -1
- package/dist/render/backend/webgpu/pointGlassTintPass.d.ts +32 -0
- package/dist/render/backend/webgpu/pointGlassTintPass.js +193 -0
- package/dist/render/backend/webgpu/pointShadowPass.d.ts +35 -6
- package/dist/render/backend/webgpu/pointShadowPass.js +105 -20
- package/dist/render/backend/webgpu/postPass.d.ts +21 -15
- package/dist/render/backend/webgpu/postPass.js +17 -4
- package/dist/render/backend/webgpu/renderer.d.ts +181 -54
- package/dist/render/backend/webgpu/renderer.js +1011 -394
- package/dist/render/backend/webgpu/scatterPass.js +2 -1
- package/dist/render/backend/webgpu/skinPaletteRing.d.ts +4 -0
- package/dist/render/backend/webgpu/skinPaletteRing.js +4 -0
- package/dist/render/backend/webgpu/snapshotMips.d.ts +29 -0
- package/dist/render/backend/webgpu/snapshotMips.js +52 -0
- package/dist/render/backend/webgpu/surfaceTexturePass.d.ts +5 -0
- package/dist/render/backend/webgpu/surfaceTexturePass.js +1 -1
- package/dist/render/flameLight.js +15 -2
- package/dist/render/glass.d.ts +45 -0
- package/dist/render/glass.js +39 -0
- package/dist/render/glassCasters.d.ts +40 -0
- package/dist/render/glassCasters.js +84 -0
- package/dist/render/glassShadow.d.ts +78 -0
- package/dist/render/glassShadow.js +125 -0
- package/dist/render/globalMediumPass.d.ts +2 -3
- package/dist/render/globalMediumPass.js +2 -8
- package/dist/render/gpudriven/lit.d.ts +12 -0
- package/dist/render/gpudriven/lit.js +23 -0
- package/dist/render/gpudriven/materialTable.d.ts +15 -5
- package/dist/render/gpudriven/materialTable.js +26 -6
- package/dist/render/gpudriven/pipeline.d.ts +1 -1
- package/dist/render/gpudriven/pipeline.js +4 -3
- package/dist/render/gpudriven/sunGlass.d.ts +35 -0
- package/dist/render/gpudriven/sunGlass.js +89 -0
- package/dist/render/lightBudget.d.ts +17 -5
- package/dist/render/lightBudget.js +17 -5
- package/dist/render/pointGlassTint.d.ts +59 -0
- package/dist/render/pointGlassTint.js +198 -0
- package/dist/render/pointShadowArray.d.ts +56 -3
- package/dist/render/pointShadowArray.js +127 -16
- package/dist/render/pointShadowBudget.js +51 -41
- package/dist/render/pointShadowMap.d.ts +23 -1
- package/dist/render/pointShadowMap.js +27 -1
- package/dist/render/recon/changeFrames.d.ts +15 -0
- package/dist/render/recon/changeFrames.js +21 -0
- package/dist/render/recon/disocclusion.d.ts +36 -3
- package/dist/render/recon/disocclusion.js +56 -4
- package/dist/render/recon/lateRouting.d.ts +14 -0
- package/dist/render/recon/lateRouting.js +18 -0
- package/dist/render/recon/mover.d.ts +57 -0
- package/dist/render/recon/mover.js +86 -0
- package/dist/render/recon/resolve.js +95 -12
- package/dist/render/renderQuality.d.ts +35 -0
- package/dist/render/renderQuality.js +7 -0
- package/dist/render/rendererHarness.js +12 -0
- package/dist/render/sceneTarget.d.ts +9 -1
- package/dist/render/sceneTarget.js +59 -13
- package/dist/render/shaders/depth.d.ts +16 -1
- package/dist/render/shaders/depth.js +85 -9
- package/dist/render/shaders/flat/directionalShadow.js +91 -6
- package/dist/render/shaders/flat/glassTint.d.ts +6 -0
- package/dist/render/shaders/flat/glassTint.js +25 -0
- package/dist/render/shaders/flat/index.d.ts +13 -0
- package/dist/render/shaders/flat/index.js +4 -0
- package/dist/render/shaders/flat/lampGlass.d.ts +1 -0
- package/dist/render/shaders/flat/lampGlass.js +183 -0
- package/dist/render/shaders/flat/main.d.ts +1 -1
- package/dist/render/shaders/flat/main.js +115 -15
- package/dist/render/shaders/flat/pointShadow.d.ts +1 -1
- package/dist/render/shaders/flat/pointShadow.js +2 -0
- package/dist/render/shaders/flat/preamble.js +21 -6
- package/dist/render/shaders/generated/depth.wgsl.d.ts +227 -4
- package/dist/render/shaders/generated/depth.wgsl.js +227 -4
- package/dist/render/shaders/generated/flat.wgsl.d.ts +360 -312
- package/dist/render/shaders/generated/flat.wgsl.js +376 -328
- package/dist/render/shaders/generated/globalMedium.wgsl.d.ts +3 -13
- package/dist/render/shaders/generated/globalMedium.wgsl.js +3 -13
- package/dist/render/shaders/generated/lightVolume.wgsl.d.ts +3 -13
- package/dist/render/shaders/generated/lightVolume.wgsl.js +4 -14
- package/dist/render/shaders/generated/octahedralResolve.wgsl.d.ts +29 -0
- package/dist/render/shaders/generated/octahedralResolve.wgsl.js +29 -0
- package/dist/render/shaders/generated/temporalResolve.wgsl.d.ts +31 -6
- package/dist/render/shaders/generated/temporalResolve.wgsl.js +31 -6
- package/dist/render/shaders/globalMedium.js +6 -6
- package/dist/render/shaders/gpudriven/blendRaster.wgsl.d.ts +7 -0
- package/dist/render/shaders/gpudriven/blendRaster.wgsl.js +86 -1
- package/dist/render/shaders/gpudriven/cull.wgsl.d.ts +1 -1
- package/dist/render/shaders/gpudriven/cull.wgsl.js +11 -2
- package/dist/render/shaders/gpudriven/materialTable.wgsl.d.ts +1 -1
- package/dist/render/shaders/gpudriven/materialTable.wgsl.js +3 -1
- package/dist/render/shaders/gpudriven/shade.wgsl.js +50 -1
- package/dist/render/shaders/gpudriven/sunGlass.wgsl.d.ts +9 -0
- package/dist/render/shaders/gpudriven/sunGlass.wgsl.js +133 -0
- package/dist/render/shaders/lightVolume.js +6 -6
- package/dist/render/shaders/octahedralResolve.d.ts +8 -0
- package/dist/render/shaders/octahedralResolve.js +48 -17
- package/dist/render/shaders/recon/lateDepth.wgsl.d.ts +1 -0
- package/dist/render/shaders/recon/lateDepth.wgsl.js +44 -0
- package/dist/render/shaders/recon/motion.wgsl.d.ts +1 -1
- package/dist/render/shaders/recon/motion.wgsl.js +84 -0
- package/dist/render/shaders/recon/resolve.wgsl.d.ts +1 -1
- package/dist/render/shaders/recon/resolve.wgsl.js +112 -8
- package/dist/render/shaders/temporalResolve.js +133 -5
- package/dist/render/shadowCasters.d.ts +20 -1
- package/dist/render/shadowCasters.js +15 -1
- package/dist/render/shadowMap.d.ts +54 -5
- package/dist/render/shadowMap.js +190 -36
- package/dist/render/sunGlassTint.d.ts +25 -0
- package/dist/render/sunGlassTint.js +79 -0
- package/dist/render/temporalAa.d.ts +145 -0
- package/dist/render/temporalAa.js +190 -0
- package/dist/render/temporalPass.d.ts +16 -14
- package/dist/render/temporalPass.js +59 -14
- package/dist/render/translucentQueue.d.ts +6 -0
- package/dist/render/translucentQueue.js +15 -1
- package/package.json +6 -6
- package/src/index.ts +10 -0
- package/src/render/backend/api.ts +15 -9
- package/src/render/backend/webgl2/glassTintPrograms.ts +58 -0
- package/src/render/backend/webgl2/renderer.ts +422 -109
- package/src/render/backend/webgpu/buffers.ts +50 -2
- package/src/render/backend/webgpu/depthPass.ts +2 -1
- package/src/render/backend/webgpu/flatPass.ts +22 -1
- package/src/render/backend/webgpu/glassTintPass.ts +244 -0
- package/src/render/backend/webgpu/gpuDrivenPass.ts +349 -5
- package/src/render/backend/webgpu/instanced.ts +21 -1
- package/src/render/backend/webgpu/latePass.ts +152 -0
- package/src/render/backend/webgpu/lightVolumePass.ts +5 -1
- package/src/render/backend/webgpu/motionPass.ts +535 -0
- package/src/render/backend/webgpu/pipelineCache.ts +12 -1
- package/src/render/backend/webgpu/pointGlassTintPass.ts +233 -0
- package/src/render/backend/webgpu/pointShadowPass.ts +158 -26
- package/src/render/backend/webgpu/postPass.ts +34 -4
- package/src/render/backend/webgpu/renderer.ts +1178 -425
- package/src/render/backend/webgpu/scatterPass.ts +2 -1
- package/src/render/backend/webgpu/skinPaletteRing.ts +4 -0
- package/src/render/backend/webgpu/snapshotMips.ts +80 -0
- package/src/render/backend/webgpu/surfaceTexturePass.ts +1 -1
- package/src/render/flameLight.ts +15 -2
- package/src/render/glass.ts +74 -0
- package/src/render/glassCasters.ts +164 -0
- package/src/render/glassShadow.ts +153 -0
- package/src/render/globalMediumPass.ts +4 -11
- package/src/render/gpudriven/lit.ts +31 -0
- package/src/render/gpudriven/materialTable.ts +28 -6
- package/src/render/gpudriven/pipeline.ts +4 -3
- package/src/render/gpudriven/sunGlass.ts +117 -0
- package/src/render/lightBudget.ts +19 -5
- package/src/render/pointGlassTint.ts +250 -0
- package/src/render/pointShadowArray.ts +188 -22
- package/src/render/pointShadowBudget.ts +49 -39
- package/src/render/pointShadowMap.ts +41 -0
- package/src/render/recon/changeFrames.ts +24 -0
- package/src/render/recon/disocclusion.ts +54 -3
- package/src/render/recon/lateRouting.ts +29 -0
- package/src/render/recon/mover.ts +118 -0
- package/src/render/recon/resolve.ts +137 -10
- package/src/render/renderQuality.ts +47 -0
- package/src/render/rendererHarness.ts +12 -0
- package/src/render/sceneTarget.ts +66 -12
- package/src/render/shaders/depth.ts +109 -9
- package/src/render/shaders/flat/directionalShadow.ts +97 -6
- package/src/render/shaders/flat/glassTint.ts +25 -0
- package/src/render/shaders/flat/index.ts +17 -0
- package/src/render/shaders/flat/lampGlass.ts +185 -0
- package/src/render/shaders/flat/main.ts +115 -15
- package/src/render/shaders/flat/pointShadow.ts +2 -0
- package/src/render/shaders/flat/preamble.ts +21 -6
- package/src/render/shaders/generated/depth.wgsl.ts +234 -4
- package/src/render/shaders/generated/flat.wgsl.ts +376 -328
- package/src/render/shaders/generated/globalMedium.wgsl.ts +3 -13
- package/src/render/shaders/generated/lightVolume.wgsl.ts +4 -14
- package/src/render/shaders/generated/octahedralResolve.wgsl.ts +30 -0
- package/src/render/shaders/generated/temporalResolve.wgsl.ts +31 -6
- package/src/render/shaders/globalMedium.ts +6 -6
- package/src/render/shaders/gpudriven/blendRaster.wgsl.ts +88 -1
- package/src/render/shaders/gpudriven/cull.wgsl.ts +11 -2
- package/src/render/shaders/gpudriven/materialTable.wgsl.ts +3 -1
- package/src/render/shaders/gpudriven/shade.wgsl.ts +50 -1
- package/src/render/shaders/gpudriven/sunGlass.wgsl.ts +139 -0
- package/src/render/shaders/lightVolume.ts +6 -6
- package/src/render/shaders/octahedralResolve.ts +50 -17
- package/src/render/shaders/recon/lateDepth.wgsl.ts +47 -0
- package/src/render/shaders/recon/motion.wgsl.ts +84 -0
- package/src/render/shaders/recon/resolve.wgsl.ts +112 -8
- package/src/render/shaders/temporalResolve.ts +141 -5
- package/src/render/shadowCasters.ts +28 -1
- package/src/render/shadowMap.ts +231 -37
- package/src/render/sunGlassTint.ts +86 -0
- package/src/render/temporalAa.ts +227 -0
- package/src/render/temporalPass.ts +88 -12
- package/src/render/translucentQueue.ts +20 -1
|
@@ -48,6 +48,15 @@ export interface GpuMesh {
|
|
|
48
48
|
* its own does.
|
|
49
49
|
*/
|
|
50
50
|
readonly vertexStride: number;
|
|
51
|
+
/**
|
|
52
|
+
* Byte offsets of the joint indices and weights in the interleaved vertex, or null for a mesh
|
|
53
|
+
* that supplied neither. For a pass that skins through a shader of its own — the motion pass —
|
|
54
|
+
* which has to find them without the `present` map the generated pipelines are keyed by.
|
|
55
|
+
*/
|
|
56
|
+
readonly skinOffsets: {
|
|
57
|
+
readonly joints: number;
|
|
58
|
+
readonly weights: number;
|
|
59
|
+
} | null;
|
|
51
60
|
readonly indexBuffer: GPUBuffer;
|
|
52
61
|
readonly indexCount: number;
|
|
53
62
|
/**
|
|
@@ -114,7 +123,16 @@ export interface GpuMesh {
|
|
|
114
123
|
* one CPU-side copy of the vertex data per dynamic mesh, which is why the flag exists rather
|
|
115
124
|
* than every mesh paying it.
|
|
116
125
|
*/
|
|
117
|
-
readonly update: ((device: GPUDevice, positions: Float32Array, normals?: Float32Array) => void) | null;
|
|
126
|
+
readonly update: ((device: GPUDevice, positions: Float32Array, normals?: Float32Array, previous?: GPUBuffer | null) => void) | null;
|
|
127
|
+
/**
|
|
128
|
+
* A dynamic mesh's motion state, which the renderer owns: a buffer for last frame's interleaved
|
|
129
|
+
* rows, made the first time a reconstructing renderer rewrites the mesh, and the frame of the
|
|
130
|
+
* last rewrite. Null on a mesh created without `{ dynamic: true }`, which never moves a vertex.
|
|
131
|
+
*/
|
|
132
|
+
readonly motion: {
|
|
133
|
+
previous: GPUBuffer | null;
|
|
134
|
+
changed: number;
|
|
135
|
+
} | null;
|
|
118
136
|
dispose(): void;
|
|
119
137
|
}
|
|
120
138
|
/** A mesh on its way to the device, and the iterator that gets it there. */
|
|
@@ -235,6 +235,7 @@ export function createGpuMeshIncremental(device, data, dynamic = false) {
|
|
|
235
235
|
progress,
|
|
236
236
|
hasTangents: data.tangents !== undefined,
|
|
237
237
|
isSkinned: data.joints !== undefined,
|
|
238
|
+
skinOffsets: skinOffsetsOf(supplied),
|
|
238
239
|
hasChannel: data.channel !== undefined,
|
|
239
240
|
morph: data.morphTargets === undefined || data.morphTargetCount === undefined
|
|
240
241
|
? null
|
|
@@ -329,12 +330,31 @@ function interleaveField(rows, source, width, step, fieldOffset, from, to) {
|
|
|
329
330
|
rows[write] = source[read];
|
|
330
331
|
}
|
|
331
332
|
}
|
|
333
|
+
/**
|
|
334
|
+
* Where the joints and weights sit in a vertex of `supplied`, the attributes a mesh interleaves in
|
|
335
|
+
* layout order; null unless it supplied both.
|
|
336
|
+
*/
|
|
337
|
+
function skinOffsetsOf(supplied) {
|
|
338
|
+
let floats = 0;
|
|
339
|
+
let joints = -1;
|
|
340
|
+
let weights = -1;
|
|
341
|
+
for (const attribute of supplied) {
|
|
342
|
+
if (attribute.name === 'joints')
|
|
343
|
+
joints = floats * 4;
|
|
344
|
+
if (attribute.name === 'weights')
|
|
345
|
+
weights = floats * 4;
|
|
346
|
+
floats += attribute.components;
|
|
347
|
+
}
|
|
348
|
+
return joints >= 0 && weights >= 0 ? { joints, weights } : null;
|
|
349
|
+
}
|
|
332
350
|
/** The handle, made where it can see only what it hands out. */
|
|
333
351
|
function gpuMeshOf(parts) {
|
|
352
|
+
const motion = parts.update === null ? null : { previous: null, changed: -1 };
|
|
334
353
|
const { vertices, constants, indexBuffer, progress } = parts;
|
|
335
354
|
return {
|
|
336
355
|
vertexBuffers: [vertices, constants],
|
|
337
356
|
vertexStride: parts.stride,
|
|
357
|
+
skinOffsets: parts.skinOffsets,
|
|
338
358
|
indexBuffer,
|
|
339
359
|
indexCount: parts.indexCount,
|
|
340
360
|
bounds: parts.bounds,
|
|
@@ -346,7 +366,9 @@ function gpuMeshOf(parts) {
|
|
|
346
366
|
hasChannel: parts.hasChannel,
|
|
347
367
|
morph: parts.morph,
|
|
348
368
|
update: parts.update,
|
|
369
|
+
motion,
|
|
349
370
|
dispose() {
|
|
371
|
+
motion?.previous?.destroy();
|
|
350
372
|
vertices.destroy();
|
|
351
373
|
constants.destroy();
|
|
352
374
|
indexBuffer.destroy();
|
|
@@ -359,12 +381,16 @@ function gpuMeshOf(parts) {
|
|
|
359
381
|
* receive have to still be there.
|
|
360
382
|
*/
|
|
361
383
|
function dynamicUpdate(interleaved, vertices, bounds, vertexCount, step, positionField, normalField) {
|
|
362
|
-
return (target, positions, normals) => {
|
|
384
|
+
return (target, positions, normals, previous = null) => {
|
|
363
385
|
if (positions.length !== vertexCount * 3) {
|
|
364
386
|
throw new Error(`this mesh has ${vertexCount} vertices and the update has ${positions.length / 3}. ` +
|
|
365
387
|
"A mesh's vertex count is fixed at creation: the index buffer, the pipeline and " +
|
|
366
388
|
'every other attribute are sized against it.');
|
|
367
389
|
}
|
|
390
|
+
/* The rows as they stand are last frame's, handed over before a position of them changes.
|
|
391
|
+
`writeBuffer` copies at the call, so patching the array afterwards cannot reach this copy. */
|
|
392
|
+
if (previous !== null)
|
|
393
|
+
target.queue.writeBuffer(previous, 0, interleaved);
|
|
368
394
|
/* Everything that decides whether this is on screen starts from the bounds, so a cloth
|
|
369
395
|
that blew sideways out of its original box would be culled while still visible. */
|
|
370
396
|
boundsOfPositions(positions, bounds);
|
|
@@ -117,7 +117,7 @@ export declare const DEPTH_FRAG_BINDING: 1;
|
|
|
117
117
|
export declare const DEPTH_PREVIOUS_BINDING: {
|
|
118
118
|
readonly texture: 32;
|
|
119
119
|
readonly sampler: 33;
|
|
120
|
-
readonly type: "
|
|
120
|
+
readonly type: "sampler2DArray";
|
|
121
121
|
};
|
|
122
122
|
/** Where the skinned vertex stage reads the joint palette. Generated, not chosen here. */
|
|
123
123
|
export declare const DEPTH_PALETTE_BINDING: {
|
|
@@ -104,7 +104,8 @@ cutout = false) {
|
|
|
104
104
|
{
|
|
105
105
|
binding: PREVIOUS.texture,
|
|
106
106
|
visibility: VISIBILITY_FRAGMENT,
|
|
107
|
-
|
|
107
|
+
/* An array since the sun's maps became one (`shadowMap.ts`): the peel reads its static layer. */
|
|
108
|
+
texture: { sampleType: 'unfilterable-float', viewDimension: '2d-array' },
|
|
108
109
|
},
|
|
109
110
|
{
|
|
110
111
|
binding: PREVIOUS.sampler,
|
|
@@ -58,6 +58,8 @@ export interface StageBindings {
|
|
|
58
58
|
readonly stride?: number;
|
|
59
59
|
}>>;
|
|
60
60
|
readonly textures: Readonly<Record<string, TextureBinding>>;
|
|
61
|
+
/** Each pipeline-overridable constant's id, by the GLSL name it was declared under. */
|
|
62
|
+
readonly overrides?: Readonly<Record<string, number>>;
|
|
61
63
|
}
|
|
62
64
|
/** The key for a set of vertex flags: the same rule `variantKey` uses, flags on, sorted, joined. */
|
|
63
65
|
export declare function flatVertexKey(skinned: boolean, morphed: boolean, instanced?: boolean): string;
|
|
@@ -107,6 +107,20 @@ export function flatFragmentBindings(variant) {
|
|
|
107
107
|
throw new Error(`flatPass: no bindings for variant "${variant}"`);
|
|
108
108
|
return found;
|
|
109
109
|
}
|
|
110
|
+
/**
|
|
111
|
+
* The lit fragment stage's constants, set from the cache: the glass switch, keyed by its **id**.
|
|
112
|
+
*
|
|
113
|
+
* Not by its name, because an override declared with `@id` answers to the id alone — WebGPU's
|
|
114
|
+
* "pipeline-overridable constant identifier string" — and naga writes one on every specialisation
|
|
115
|
+
* constant. Keyed by name, Chrome refused every lit pipeline: *Pipeline overridable constant
|
|
116
|
+
* "GLASS_SHADOWS" not found*, and the frame drew nothing.
|
|
117
|
+
*/
|
|
118
|
+
function flatFragmentConstants(variant, cache) {
|
|
119
|
+
const id = flatFragmentBindings(variant).overrides?.['GLASS_SHADOWS'];
|
|
120
|
+
if (id === undefined)
|
|
121
|
+
throw new Error(`flatPass: variant "${variant}" has no glass switch`);
|
|
122
|
+
return { [String(id)]: cache.glassShadows ? 1 : 0 };
|
|
123
|
+
}
|
|
110
124
|
/** The depth format both backends compare with. */
|
|
111
125
|
/* Re-exported so the twenty passes that already import it from here do not each learn a new
|
|
112
126
|
module; `depthConvention.ts` is where the decision lives and why. */
|
|
@@ -182,7 +196,10 @@ export function createFlatBindGroupLayout(device, variant, skinned = false, morp
|
|
|
182
196
|
const integer = texture.type === 'usampler2D' || texture.type === 'usampler3D';
|
|
183
197
|
/* DriftLight's brick index and atlas, the lit pass's only volumes. See `driftLight.ts`. */
|
|
184
198
|
const volume = texture.type === 'sampler3D' || texture.type === 'usampler3D';
|
|
185
|
-
|
|
199
|
+
/* Glass tints are colour, mipmapped and filtered: a frosted pane is read at a coarser level. */
|
|
200
|
+
const tint = name.endsWith('GlassTints');
|
|
201
|
+
const isShadow = integer ||
|
|
202
|
+
(!tint && name !== 'uEnvironment' && (name.endsWith('ShadowMap') || cube || array));
|
|
186
203
|
entries.push({
|
|
187
204
|
binding: texture.texture,
|
|
188
205
|
visibility: VISIBILITY_FRAGMENT,
|
|
@@ -449,6 +466,8 @@ doubleSided = false) {
|
|
|
449
466
|
code: FLAT_FRAG_WGSL[variant] ?? '',
|
|
450
467
|
}),
|
|
451
468
|
entryPoint: 'main',
|
|
469
|
+
/* Every variant declares it, so every lit pipeline may set it: see `PipelineCache`. */
|
|
470
|
+
constants: flatFragmentConstants(variant, cache),
|
|
452
471
|
targets: [
|
|
453
472
|
oitTarget(oit) ??
|
|
454
473
|
(translucent
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ResolvedGlass } from '../../glass.ts';
|
|
2
|
+
import type { PipelineCache } from './pipelineCache.ts';
|
|
3
|
+
import { UniformRing } from './uniformRing.ts';
|
|
4
|
+
export type GlassTintKind = 'rigid' | 'instanced' | 'skinned' | 'cutout' | 'instancedCutout';
|
|
5
|
+
/** The multiplying state: colour times what passes, clarity times clarity, order-free. */
|
|
6
|
+
export declare const GLASS_TINT_BLEND: GPUBlendState;
|
|
7
|
+
export declare class GpuGlassTint {
|
|
8
|
+
readonly frag: UniformRing;
|
|
9
|
+
private readonly layouts;
|
|
10
|
+
private plainGroup;
|
|
11
|
+
private groupVertBuffer;
|
|
12
|
+
private groupFragBuffer;
|
|
13
|
+
private readonly cutoutGroups;
|
|
14
|
+
private readonly skinnedGroups;
|
|
15
|
+
private readonly device;
|
|
16
|
+
constructor(device: GPUDevice);
|
|
17
|
+
/** One pane's block: what it lets through, how clear it is, and the light it is drawn for. */
|
|
18
|
+
writePane(slot: number, glass: ResolvedGlass, light: Float32Array): void;
|
|
19
|
+
/** The plain group, rebuilt only when a ring has grown a new buffer under it. */
|
|
20
|
+
group(vertBuffer: GPUBuffer): GPUBindGroup;
|
|
21
|
+
/** A cutout pane's group, one per map, built the first time that map casts colour. */
|
|
22
|
+
cutoutGroup(vertBuffer: GPUBuffer, view: GPUTextureView, sampler: GPUSampler): GPUBindGroup;
|
|
23
|
+
/** A skinned pane's group, one per palette view. */
|
|
24
|
+
skinnedGroup(vertBuffer: GPUBuffer, palette: GPUTextureView): GPUBindGroup;
|
|
25
|
+
/** The pipeline for one kind of caster, cull mode and vertex layout, cached by key. */
|
|
26
|
+
pipeline(cache: PipelineCache, kind: GlassTintKind, key: string, present: Readonly<Record<string, boolean>>, cullMode: GPUCullMode): GPURenderPipeline;
|
|
27
|
+
dispose(): void;
|
|
28
|
+
}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a pane lets through, drawn into a shadow's tint layer on this device: the layouts, the
|
|
3
|
+
* per-draw block, the bind groups and the pipelines for the five tint programs (`depth.ts`).
|
|
4
|
+
*
|
|
5
|
+
* **The vertex half is the depth pass's**, block for block — the tint's vertex stages are the depth
|
|
6
|
+
* ones with the world position handed on — so a draw's vertex slot comes from the shadow pass's own
|
|
7
|
+
* ring and only the pane's 32 bytes are this file's. **The fragment half multiplies**: an
|
|
8
|
+
* `rgba8unorm` target cleared to white, `dst × src` for colour and `dst-alpha × src` for clarity, and
|
|
9
|
+
* no depth, so every pane on a ray counts in any order. Built the first time glass casts, so a scene
|
|
10
|
+
* with no glass builds none of it.
|
|
11
|
+
*/
|
|
12
|
+
import { DEPTH_BINDINGS } from '../../shaders/generated/depth.wgsl.js';
|
|
13
|
+
import { GLASS_TINT_CUTOUT_FRAG_WGSL, GLASS_TINT_CUTOUT_VERT_WGSL, GLASS_TINT_FRAG_WGSL, GLASS_TINT_INSTANCED_CUTOUT_VERT_WGSL, GLASS_TINT_INSTANCED_VERT_WGSL, GLASS_TINT_SKINNED_VERT_WGSL, GLASS_TINT_VERT_WGSL, } from '../../shaders/generated/depth.wgsl.js';
|
|
14
|
+
import { vertexBufferLayouts } from './buffers.js';
|
|
15
|
+
import { shaderModule } from './shaderModules.js';
|
|
16
|
+
import { UniformRing } from './uniformRing.js';
|
|
17
|
+
const VISIBILITY_VERTEX = 0x1;
|
|
18
|
+
const VISIBILITY_FRAGMENT = 0x2;
|
|
19
|
+
const USAGE_UNIFORM_DST = 0x40 | 0x8; // UNIFORM | COPY_DST
|
|
20
|
+
const VERT = DEPTH_BINDINGS.GLASS_TINT_VERT;
|
|
21
|
+
const CUTOUT_VERT = DEPTH_BINDINGS.GLASS_TINT_CUTOUT_VERT;
|
|
22
|
+
const FRAG = DEPTH_BINDINGS.GLASS_TINT_FRAG;
|
|
23
|
+
const CUTOUT_MAP = DEPTH_BINDINGS.GLASS_TINT_CUTOUT_FRAG.textures.uCutoutMap;
|
|
24
|
+
const PALETTE = DEPTH_BINDINGS.GLASS_TINT_SKINNED_VERT.textures.uJointPalette;
|
|
25
|
+
const PANE = FRAG.fields.uGlassPane.offset;
|
|
26
|
+
const LIGHT = FRAG.fields.uGlassLight.offset;
|
|
27
|
+
/** Panes a frame can tint: a pane is a draw per shadow it reaches, and panes are few. */
|
|
28
|
+
const MAX_TINT_DRAWS = 512;
|
|
29
|
+
/** The multiplying state: colour times what passes, clarity times clarity, order-free. */
|
|
30
|
+
export const GLASS_TINT_BLEND = {
|
|
31
|
+
color: { operation: 'add', srcFactor: 'dst', dstFactor: 'zero' },
|
|
32
|
+
alpha: { operation: 'add', srcFactor: 'dst-alpha', dstFactor: 'zero' },
|
|
33
|
+
};
|
|
34
|
+
export class GpuGlassTint {
|
|
35
|
+
frag;
|
|
36
|
+
layouts;
|
|
37
|
+
plainGroup = null;
|
|
38
|
+
groupVertBuffer = null;
|
|
39
|
+
groupFragBuffer = null;
|
|
40
|
+
cutoutGroups = new Map();
|
|
41
|
+
skinnedGroups = new Map();
|
|
42
|
+
device;
|
|
43
|
+
constructor(device) {
|
|
44
|
+
this.device = device;
|
|
45
|
+
this.frag = new UniformRing(device, FRAG.uniformSize, MAX_TINT_DRAWS, USAGE_UNIFORM_DST, 'glassTint.ring');
|
|
46
|
+
const vert = (size) => ({
|
|
47
|
+
binding: VERT.uniforms,
|
|
48
|
+
visibility: VISIBILITY_VERTEX,
|
|
49
|
+
buffer: { type: 'uniform', hasDynamicOffset: true, minBindingSize: size },
|
|
50
|
+
});
|
|
51
|
+
const frag = {
|
|
52
|
+
binding: FRAG.uniforms,
|
|
53
|
+
visibility: VISIBILITY_FRAGMENT,
|
|
54
|
+
buffer: { type: 'uniform', hasDynamicOffset: true, minBindingSize: FRAG.uniformSize },
|
|
55
|
+
};
|
|
56
|
+
this.layouts = {
|
|
57
|
+
plain: device.createBindGroupLayout({
|
|
58
|
+
label: 'glassTint.layout',
|
|
59
|
+
entries: [vert(VERT.uniformSize), frag],
|
|
60
|
+
}),
|
|
61
|
+
cutout: device.createBindGroupLayout({
|
|
62
|
+
label: 'glassTint.layout.cutout',
|
|
63
|
+
entries: [
|
|
64
|
+
vert(CUTOUT_VERT.uniformSize),
|
|
65
|
+
frag,
|
|
66
|
+
{
|
|
67
|
+
binding: CUTOUT_MAP.texture,
|
|
68
|
+
visibility: VISIBILITY_FRAGMENT,
|
|
69
|
+
texture: { sampleType: 'float' },
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
binding: CUTOUT_MAP.sampler,
|
|
73
|
+
visibility: VISIBILITY_FRAGMENT,
|
|
74
|
+
sampler: { type: 'filtering' },
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
}),
|
|
78
|
+
skinned: device.createBindGroupLayout({
|
|
79
|
+
label: 'glassTint.layout.skinned',
|
|
80
|
+
entries: [
|
|
81
|
+
{
|
|
82
|
+
binding: PALETTE.texture,
|
|
83
|
+
visibility: VISIBILITY_VERTEX,
|
|
84
|
+
texture: { sampleType: 'unfilterable-float' },
|
|
85
|
+
},
|
|
86
|
+
vert(VERT.uniformSize),
|
|
87
|
+
frag,
|
|
88
|
+
],
|
|
89
|
+
}),
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
/** One pane's block: what it lets through, how clear it is, and the light it is drawn for. */
|
|
93
|
+
writePane(slot, glass, light) {
|
|
94
|
+
const pane = paneScratch;
|
|
95
|
+
pane[0] = glass.transmission * glass.tint[0];
|
|
96
|
+
pane[1] = glass.transmission * glass.tint[1];
|
|
97
|
+
pane[2] = glass.transmission * glass.tint[2];
|
|
98
|
+
pane[3] = 1 - glass.frost;
|
|
99
|
+
this.frag.writeFloats(slot, PANE, pane);
|
|
100
|
+
this.frag.writeFloats(slot, LIGHT, light);
|
|
101
|
+
}
|
|
102
|
+
/** The plain group, rebuilt only when a ring has grown a new buffer under it. */
|
|
103
|
+
group(vertBuffer) {
|
|
104
|
+
if (this.plainGroup === null ||
|
|
105
|
+
this.groupVertBuffer !== vertBuffer ||
|
|
106
|
+
this.groupFragBuffer !== this.frag.buffer) {
|
|
107
|
+
this.cutoutGroups.clear();
|
|
108
|
+
this.skinnedGroups.clear();
|
|
109
|
+
this.groupVertBuffer = vertBuffer;
|
|
110
|
+
this.groupFragBuffer = this.frag.buffer;
|
|
111
|
+
this.plainGroup = this.device.createBindGroup({
|
|
112
|
+
label: 'glassTint.group',
|
|
113
|
+
layout: this.layouts.plain,
|
|
114
|
+
entries: [
|
|
115
|
+
{ binding: VERT.uniforms, resource: { buffer: vertBuffer, size: VERT.uniformSize } },
|
|
116
|
+
{
|
|
117
|
+
binding: FRAG.uniforms,
|
|
118
|
+
resource: { buffer: this.frag.buffer, size: FRAG.uniformSize },
|
|
119
|
+
},
|
|
120
|
+
],
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
return this.plainGroup;
|
|
124
|
+
}
|
|
125
|
+
/** A cutout pane's group, one per map, built the first time that map casts colour. */
|
|
126
|
+
cutoutGroup(vertBuffer, view, sampler) {
|
|
127
|
+
this.group(vertBuffer);
|
|
128
|
+
const held = this.cutoutGroups.get(view);
|
|
129
|
+
if (held !== undefined)
|
|
130
|
+
return held;
|
|
131
|
+
const made = this.device.createBindGroup({
|
|
132
|
+
label: 'glassTint.group.cutout',
|
|
133
|
+
layout: this.layouts.cutout,
|
|
134
|
+
entries: [
|
|
135
|
+
{
|
|
136
|
+
binding: CUTOUT_VERT.uniforms,
|
|
137
|
+
resource: { buffer: vertBuffer, size: CUTOUT_VERT.uniformSize },
|
|
138
|
+
},
|
|
139
|
+
{ binding: FRAG.uniforms, resource: { buffer: this.frag.buffer, size: FRAG.uniformSize } },
|
|
140
|
+
{ binding: CUTOUT_MAP.texture, resource: view },
|
|
141
|
+
{ binding: CUTOUT_MAP.sampler, resource: sampler },
|
|
142
|
+
],
|
|
143
|
+
});
|
|
144
|
+
this.cutoutGroups.set(view, made);
|
|
145
|
+
return made;
|
|
146
|
+
}
|
|
147
|
+
/** A skinned pane's group, one per palette view. */
|
|
148
|
+
skinnedGroup(vertBuffer, palette) {
|
|
149
|
+
this.group(vertBuffer);
|
|
150
|
+
const held = this.skinnedGroups.get(palette);
|
|
151
|
+
if (held !== undefined)
|
|
152
|
+
return held;
|
|
153
|
+
const made = this.device.createBindGroup({
|
|
154
|
+
label: 'glassTint.group.skinned',
|
|
155
|
+
layout: this.layouts.skinned,
|
|
156
|
+
entries: [
|
|
157
|
+
{ binding: PALETTE.texture, resource: palette },
|
|
158
|
+
{ binding: VERT.uniforms, resource: { buffer: vertBuffer, size: VERT.uniformSize } },
|
|
159
|
+
{ binding: FRAG.uniforms, resource: { buffer: this.frag.buffer, size: FRAG.uniformSize } },
|
|
160
|
+
],
|
|
161
|
+
});
|
|
162
|
+
this.skinnedGroups.set(palette, made);
|
|
163
|
+
return made;
|
|
164
|
+
}
|
|
165
|
+
/** The pipeline for one kind of caster, cull mode and vertex layout, cached by key. */
|
|
166
|
+
pipeline(cache, kind, key, present, cullMode) {
|
|
167
|
+
const cutout = kind === 'cutout' || kind === 'instancedCutout';
|
|
168
|
+
const instanced = kind === 'instanced' || kind === 'instancedCutout';
|
|
169
|
+
const layout = kind === 'skinned' ? this.layouts.skinned : cutout ? this.layouts.cutout : this.layouts.plain;
|
|
170
|
+
const vertex = kind === 'rigid'
|
|
171
|
+
? GLASS_TINT_VERT_WGSL
|
|
172
|
+
: kind === 'instanced'
|
|
173
|
+
? GLASS_TINT_INSTANCED_VERT_WGSL
|
|
174
|
+
: kind === 'skinned'
|
|
175
|
+
? GLASS_TINT_SKINNED_VERT_WGSL
|
|
176
|
+
: kind === 'cutout'
|
|
177
|
+
? GLASS_TINT_CUTOUT_VERT_WGSL
|
|
178
|
+
: GLASS_TINT_INSTANCED_CUTOUT_VERT_WGSL;
|
|
179
|
+
const label = `glass-tint|${kind}|${cullMode}|${key}`;
|
|
180
|
+
return cache.get(label, () => ({
|
|
181
|
+
label,
|
|
182
|
+
layout: this.device.createPipelineLayout({ bindGroupLayouts: [layout] }),
|
|
183
|
+
vertex: {
|
|
184
|
+
module: shaderModule(this.device, { label: `glassTint.${kind}.vert`, code: vertex }),
|
|
185
|
+
entryPoint: 'main',
|
|
186
|
+
buffers: vertexBufferLayouts(present, instanced),
|
|
187
|
+
},
|
|
188
|
+
fragment: {
|
|
189
|
+
module: shaderModule(this.device, {
|
|
190
|
+
label: cutout ? 'glassTint.cutout.frag' : 'glassTint.frag',
|
|
191
|
+
code: cutout ? GLASS_TINT_CUTOUT_FRAG_WGSL : GLASS_TINT_FRAG_WGSL,
|
|
192
|
+
}),
|
|
193
|
+
entryPoint: 'main',
|
|
194
|
+
targets: [{ format: 'rgba8unorm', blend: GLASS_TINT_BLEND }],
|
|
195
|
+
},
|
|
196
|
+
/* The depth pass's primitive state exactly — its winding included, for the reason
|
|
197
|
+
`depthPipeline` gives: this map is sampled, not presented. */
|
|
198
|
+
primitive: { topology: 'triangle-list', cullMode, frontFace: 'cw' },
|
|
199
|
+
}));
|
|
200
|
+
}
|
|
201
|
+
dispose() {
|
|
202
|
+
this.frag.dispose();
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
const paneScratch = new Float32Array(4);
|
|
@@ -59,6 +59,8 @@
|
|
|
59
59
|
* generated, so taking it mirrors the picture — and mirrors the winding with it, which is how it
|
|
60
60
|
* reads as a culling problem. `PassDevice` carries both matrices and says which is which.
|
|
61
61
|
*/
|
|
62
|
+
import { type GlassOptions } from '../../glass.ts';
|
|
63
|
+
import type { GlassShadows } from '../../renderQuality.ts';
|
|
62
64
|
import { type FogOptions } from '../../fog.ts';
|
|
63
65
|
import { StreamingScene } from '../../gpudriven/streamScene.ts';
|
|
64
66
|
import { type GpuDrivenTextures } from '../../gpudriven/materialTable.ts';
|
|
@@ -69,7 +71,7 @@ import type { PassContext, PassDefinition, PassDevice, PrepareContext } from '..
|
|
|
69
71
|
* Five blocks since 2026-09-17 — the three texture programs, the UV scale and the map strengths
|
|
70
72
|
* joined the eight — and `gpudriven/materialTable.ts` writes them.
|
|
71
73
|
*/
|
|
72
|
-
export declare const MATERIAL_FLOATS =
|
|
74
|
+
export declare const MATERIAL_FLOATS = 28;
|
|
73
75
|
/** Floats a vertex in the one interleaved buffer: position, normal, colour, uv. */
|
|
74
76
|
export declare const VERTEX_FLOATS = 12;
|
|
75
77
|
/**
|
|
@@ -186,6 +188,14 @@ export interface GpuDrivenMaterial {
|
|
|
186
188
|
* blend and said nothing else gets — visible, and therefore findable.
|
|
187
189
|
*/
|
|
188
190
|
readonly opacity?: number;
|
|
191
|
+
/**
|
|
192
|
+
* Glass: how much light passes, how milky it is, and the colour it takes — `GlassOptions`, as the
|
|
193
|
+
* forward path's `drawTranslucentMesh` takes it. Absent, or letting nothing through, is not glass.
|
|
194
|
+
*
|
|
195
|
+
* **A glass material is drawn in the blended half whatever `blend` says**, because a visibility
|
|
196
|
+
* buffer holds one surface a pixel and glass is the pane and what is behind it.
|
|
197
|
+
*/
|
|
198
|
+
readonly glass?: GlassOptions;
|
|
189
199
|
}
|
|
190
200
|
/** What the pass needs told once a frame, before `beginFrame`. */
|
|
191
201
|
export interface GpuDrivenView {
|
|
@@ -288,6 +298,12 @@ export interface GpuDrivenShadowOptions {
|
|
|
288
298
|
* texels, and reaches toward the sun as far as the scene does.
|
|
289
299
|
*/
|
|
290
300
|
readonly followRadius?: number;
|
|
301
|
+
/**
|
|
302
|
+
* What the sun keeps through glass: `RenderQualityOptions.glassShadows`, which a contributed pass
|
|
303
|
+
* is not handed and so takes here. `'full'` by default, as there; `'half'` halves the tint and
|
|
304
|
+
* `'off'` draws a glass material's shadow as nothing, which is what it cast before.
|
|
305
|
+
*/
|
|
306
|
+
readonly glass?: GlassShadows;
|
|
291
307
|
}
|
|
292
308
|
export declare class GpuDrivenPass implements PassDefinition {
|
|
293
309
|
readonly label = "driftengine.gpu-driven";
|
|
@@ -410,6 +426,30 @@ export declare class GpuDrivenPass implements PassDefinition {
|
|
|
410
426
|
private latentClamp;
|
|
411
427
|
private latentRepeat;
|
|
412
428
|
private shadowView;
|
|
429
|
+
/** The nearest pane's depth from the sun: the shadow texture's second layer, where glass casts. */
|
|
430
|
+
private glassDepthView;
|
|
431
|
+
/** What the panes let through, as the sun sees them, with the chain frost reads. */
|
|
432
|
+
private glassTintTexture;
|
|
433
|
+
private glassTintTarget;
|
|
434
|
+
private glassTintSampled;
|
|
435
|
+
private glassTintMips;
|
|
436
|
+
/** One white texel, bound where no glass casts, which the lookup reads as none. */
|
|
437
|
+
private glassTintNone;
|
|
438
|
+
private readonly glassMode;
|
|
439
|
+
/** Whether the sun's glass pass runs at all: a glass material, and glass shadows not off. */
|
|
440
|
+
private readonly castsGlass;
|
|
441
|
+
private glassList;
|
|
442
|
+
private glassArgs;
|
|
443
|
+
private glassLodBuffer;
|
|
444
|
+
private readonly lodParamsGlass;
|
|
445
|
+
private shadowCullSettingsGlass;
|
|
446
|
+
private glassLodGroup;
|
|
447
|
+
private glassCullGroup;
|
|
448
|
+
private glassCompactGroup;
|
|
449
|
+
private glassDepthPipeline;
|
|
450
|
+
private glassDepthGroup;
|
|
451
|
+
private glassTintPipeline;
|
|
452
|
+
private glassTintGroup;
|
|
413
453
|
/**
|
|
414
454
|
* What is bound as the probe where the frame has none.
|
|
415
455
|
*
|
|
@@ -521,7 +561,18 @@ export declare class GpuDrivenPass implements PassDefinition {
|
|
|
521
561
|
private visibilityTexture;
|
|
522
562
|
private depthTexture;
|
|
523
563
|
private colourTexture;
|
|
564
|
+
/** Level 0: what the shading writes, the resolve lays over and the blit presents. */
|
|
524
565
|
private colourView;
|
|
566
|
+
/** Every level, for glass to read at the level its frost picks. Level 0 alone with no glass. */
|
|
567
|
+
private colourSampledView;
|
|
568
|
+
/** The chain glass reads, filled from the shaded picture each frame; null in a scene with none. */
|
|
569
|
+
private colourMips;
|
|
570
|
+
/** Whether any material is glass, which is what earns the colour its chain: see `buildTargets`. */
|
|
571
|
+
private readonly hasGlass;
|
|
572
|
+
/** The pipelines the chain draws with, one a format. */
|
|
573
|
+
private readonly mipPipelineCache;
|
|
574
|
+
private readonly mipPipelines;
|
|
575
|
+
private glassSampler;
|
|
525
576
|
private visibility;
|
|
526
577
|
private hzb;
|
|
527
578
|
private levelStart;
|
|
@@ -794,8 +845,16 @@ export declare class GpuDrivenPass implements PassDefinition {
|
|
|
794
845
|
* second render pass where it ended, so `shadow` in the stage times is all of it.
|
|
795
846
|
*/
|
|
796
847
|
private drawShadow;
|
|
848
|
+
/**
|
|
849
|
+
* The sun's glass, after its opaque map: the glass cut from the light, then the panes drawn
|
|
850
|
+
* twice — where the nearest one is, and what they let through, multiplied — and the tint's
|
|
851
|
+
* chain filled for frost to read. The forward path's `flushSunGlass`, in this pipeline's terms.
|
|
852
|
+
*/
|
|
853
|
+
private drawShadowGlass;
|
|
797
854
|
/** One half of the map: the first clears it, the second draws over it and closes the stage's time. */
|
|
798
855
|
private drawShadowHalf;
|
|
856
|
+
/** The linear sampler glass reads the colour's and the tint's chains through, made once. */
|
|
857
|
+
private glassSamplerFor;
|
|
799
858
|
private drawPhase;
|
|
800
859
|
draw(ctx: PassContext): void;
|
|
801
860
|
dispose(device: PassDevice): void;
|