@driftengine/core 4.8.7 → 4.9.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 +61 -0
- package/README.md +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.js +7 -0
- package/dist/render/atmosphere.d.ts +13 -0
- package/dist/render/atmosphere.js +9 -1
- package/dist/render/backend/api.d.ts +9 -1
- package/dist/render/backend/createRenderer.d.ts +6 -0
- package/dist/render/backend/createRenderer.js +4 -1
- package/dist/render/backend/webgl2/renderer.d.ts +90 -2
- package/dist/render/backend/webgl2/renderer.js +297 -16
- package/dist/render/backend/webgpu/device.d.ts +7 -1
- package/dist/render/backend/webgpu/device.js +31 -3
- package/dist/render/backend/webgpu/flatPass.d.ts +16 -1
- package/dist/render/backend/webgpu/flatPass.js +58 -26
- package/dist/render/backend/webgpu/postPass.d.ts +51 -9
- package/dist/render/backend/webgpu/postPass.js +16 -2
- package/dist/render/backend/webgpu/reflectionSurfacePass.d.ts +30 -0
- package/dist/render/backend/webgpu/reflectionSurfacePass.js +100 -0
- package/dist/render/backend/webgpu/renderer.d.ts +131 -2
- package/dist/render/backend/webgpu/renderer.js +586 -70
- package/dist/render/displayRange.d.ts +31 -0
- package/dist/render/displayRange.js +47 -0
- package/dist/render/filmicCurve.d.ts +74 -0
- package/dist/render/filmicCurve.js +203 -0
- package/dist/render/fog.d.ts +4 -1
- package/dist/render/fog.js +12 -2
- package/dist/render/frame/resources.d.ts +2 -2
- package/dist/render/frame/resources.js +6 -0
- package/dist/render/frameReflections.d.ts +40 -0
- package/dist/render/frameReflections.js +48 -0
- package/dist/render/pass.d.ts +49 -0
- package/dist/render/reflectionSurfaceTargets.d.ts +28 -0
- package/dist/render/reflectionSurfaceTargets.js +99 -0
- package/dist/render/renderQuality.d.ts +39 -8
- package/dist/render/renderQuality.js +4 -0
- package/dist/render/sceneTarget.d.ts +5 -0
- package/dist/render/sceneTarget.js +24 -1
- package/dist/render/screenSpaceReflection.d.ts +5 -0
- package/dist/render/screenSpaceReflection.js +5 -0
- package/dist/render/shaders/arcane.d.ts +1 -1
- package/dist/render/shaders/bolt.d.ts +1 -1
- package/dist/render/shaders/caustics.d.ts +1 -1
- package/dist/render/shaders/film.d.ts +1 -1
- package/dist/render/shaders/filmLook.js +2 -1
- package/dist/render/shaders/fire.d.ts +1 -1
- package/dist/render/shaders/flat/glassTint.d.ts +1 -1
- package/dist/render/shaders/flat/glassTint.js +2 -0
- package/dist/render/shaders/flat/index.d.ts +10 -0
- package/dist/render/shaders/flat/index.js +6 -0
- package/dist/render/shaders/flat/main.d.ts +1 -1
- package/dist/render/shaders/flat/main.js +28 -0
- package/dist/render/shaders/flat/overlay.d.ts +16 -0
- package/dist/render/shaders/flat/overlay.js +117 -0
- package/dist/render/shaders/flat/pointShadow.js +1 -1
- package/dist/render/shaders/flat/reflectionSurface.d.ts +21 -0
- package/dist/render/shaders/flat/reflectionSurface.js +61 -0
- package/dist/render/shaders/fog.d.ts +1 -1
- package/dist/render/shaders/fog.js +9 -2
- package/dist/render/shaders/fringe.d.ts +29 -0
- package/dist/render/shaders/fringe.js +55 -0
- package/dist/render/shaders/generated/arcane.wgsl.d.ts +1 -1
- package/dist/render/shaders/generated/arcane.wgsl.js +1 -1
- package/dist/render/shaders/generated/bolt.wgsl.d.ts +1 -1
- package/dist/render/shaders/generated/bolt.wgsl.js +1 -1
- package/dist/render/shaders/generated/caustics.wgsl.d.ts +1 -1
- package/dist/render/shaders/generated/caustics.wgsl.js +1 -1
- package/dist/render/shaders/generated/film.wgsl.d.ts +1 -1
- package/dist/render/shaders/generated/film.wgsl.js +1 -1
- package/dist/render/shaders/generated/fire.wgsl.d.ts +1 -1
- package/dist/render/shaders/generated/fire.wgsl.js +1 -1
- package/dist/render/shaders/generated/flat.wgsl.d.ts +176 -16
- package/dist/render/shaders/generated/flat.wgsl.js +214 -54
- package/dist/render/shaders/generated/line.wgsl.d.ts +1 -1
- package/dist/render/shaders/generated/line.wgsl.js +1 -1
- package/dist/render/shaders/generated/particle.wgsl.d.ts +4 -4
- package/dist/render/shaders/generated/particle.wgsl.js +4 -4
- package/dist/render/shaders/generated/rush.wgsl.d.ts +56 -26
- package/dist/render/shaders/generated/rush.wgsl.js +56 -26
- package/dist/render/shaders/generated/scatter.wgsl.d.ts +1 -1
- package/dist/render/shaders/generated/scatter.wgsl.js +1 -1
- package/dist/render/shaders/generated/smoke.wgsl.d.ts +1 -1
- package/dist/render/shaders/generated/smoke.wgsl.js +1 -1
- package/dist/render/shaders/generated/ssrResolve.wgsl.d.ts +29 -0
- package/dist/render/shaders/generated/ssrResolve.wgsl.js +29 -0
- package/dist/render/shaders/generated/ssrTrace.wgsl.d.ts +22 -2
- package/dist/render/shaders/generated/ssrTrace.wgsl.js +22 -2
- package/dist/render/shaders/generated/water.wgsl.d.ts +1 -1
- package/dist/render/shaders/generated/water.wgsl.js +1 -1
- package/dist/render/shaders/gpudriven/fog.wgsl.d.ts +2 -2
- package/dist/render/shaders/gpudriven/fog.wgsl.js +11 -3
- package/dist/render/shaders/line.d.ts +1 -1
- package/dist/render/shaders/particle.d.ts +3 -3
- package/dist/render/shaders/rush.js +54 -11
- package/dist/render/shaders/scatter.d.ts +1 -1
- package/dist/render/shaders/smoke.d.ts +1 -1
- package/dist/render/shaders/ssrResolve.d.ts +17 -0
- package/dist/render/shaders/ssrResolve.js +51 -0
- package/dist/render/shaders/ssrTrace.js +26 -0
- package/dist/render/shaders/water.d.ts +1 -1
- package/dist/render/ssrPass.d.ts +16 -0
- package/dist/render/ssrPass.js +106 -1
- package/dist/render/surfaceOverlay.d.ts +132 -0
- package/dist/render/surfaceOverlay.js +85 -0
- package/dist/render/surfaceTexture.d.ts +19 -0
- package/dist/render/surfaceTexture.js +69 -0
- package/dist/render/temporalAa.d.ts +14 -0
- package/dist/render/temporalAa.js +20 -0
- package/dist/render/vertexDefaults.d.ts +17 -0
- package/dist/render/vertexDefaults.js +24 -0
- package/package.json +6 -6
- package/src/index.ts +16 -0
- package/src/render/atmosphere.ts +22 -1
- package/src/render/backend/api.ts +9 -0
- package/src/render/backend/createRenderer.ts +18 -1
- package/src/render/backend/webgl2/renderer.ts +357 -13
- package/src/render/backend/webgpu/device.ts +42 -3
- package/src/render/backend/webgpu/flatPass.ts +63 -26
- package/src/render/backend/webgpu/postPass.ts +18 -0
- package/src/render/backend/webgpu/reflectionSurfacePass.ts +114 -0
- package/src/render/backend/webgpu/renderer.ts +735 -83
- package/src/render/displayRange.ts +61 -0
- package/src/render/filmicCurve.ts +229 -0
- package/src/render/fog.ts +19 -3
- package/src/render/frame/resources.ts +6 -0
- package/src/render/frameReflections.ts +72 -0
- package/src/render/pass.ts +53 -1
- package/src/render/reflectionSurfaceTargets.ts +105 -0
- package/src/render/renderQuality.ts +44 -8
- package/src/render/sceneTarget.ts +30 -2
- package/src/render/screenSpaceReflection.ts +5 -0
- package/src/render/shaders/filmLook.ts +2 -1
- package/src/render/shaders/flat/glassTint.ts +5 -1
- package/src/render/shaders/flat/index.ts +16 -0
- package/src/render/shaders/flat/main.ts +28 -0
- package/src/render/shaders/flat/overlay.ts +117 -0
- package/src/render/shaders/flat/pointShadow.ts +1 -1
- package/src/render/shaders/flat/reflectionSurface.ts +61 -0
- package/src/render/shaders/fog.ts +9 -2
- package/src/render/shaders/fringe.ts +59 -0
- package/src/render/shaders/generated/arcane.wgsl.ts +1 -1
- package/src/render/shaders/generated/bolt.wgsl.ts +1 -1
- package/src/render/shaders/generated/caustics.wgsl.ts +1 -1
- package/src/render/shaders/generated/film.wgsl.ts +1 -1
- package/src/render/shaders/generated/fire.wgsl.ts +1 -1
- package/src/render/shaders/generated/flat.wgsl.ts +214 -54
- package/src/render/shaders/generated/line.wgsl.ts +1 -1
- package/src/render/shaders/generated/particle.wgsl.ts +4 -4
- package/src/render/shaders/generated/rush.wgsl.ts +56 -26
- package/src/render/shaders/generated/scatter.wgsl.ts +1 -1
- package/src/render/shaders/generated/smoke.wgsl.ts +1 -1
- package/src/render/shaders/generated/ssrResolve.wgsl.ts +30 -0
- package/src/render/shaders/generated/ssrTrace.wgsl.ts +22 -2
- package/src/render/shaders/generated/water.wgsl.ts +1 -1
- package/src/render/shaders/gpudriven/fog.wgsl.ts +11 -3
- package/src/render/shaders/rush.ts +54 -11
- package/src/render/shaders/ssrResolve.ts +52 -0
- package/src/render/shaders/ssrTrace.ts +26 -0
- package/src/render/ssrPass.ts +138 -1
- package/src/render/surfaceOverlay.ts +195 -0
- package/src/render/surfaceTexture.ts +67 -0
- package/src/render/temporalAa.ts +20 -0
- package/src/render/vertexDefaults.ts +28 -0
|
@@ -6,6 +6,11 @@
|
|
|
6
6
|
* split matters because these two fail for unrelated reasons: a device is lost by a driver
|
|
7
7
|
* reset the page did not cause, and a frame is wrong because of something the frame did.
|
|
8
8
|
*/
|
|
9
|
+
/** A canvas nobody asked to extend. */
|
|
10
|
+
const STANDARD_RANGE = {
|
|
11
|
+
range: 'standard',
|
|
12
|
+
reason: 'highDynamicRange was not asked for',
|
|
13
|
+
};
|
|
9
14
|
/**
|
|
10
15
|
* Take a canvas and a device, and hand back the surface the renderer draws into.
|
|
11
16
|
*
|
|
@@ -25,12 +30,23 @@
|
|
|
25
30
|
* consumer its GPU had failed every time it unmounted a canvas on purpose, so a disposed
|
|
26
31
|
* surface stays silent.
|
|
27
32
|
*/
|
|
28
|
-
export function createGpuSurface(canvas, device
|
|
33
|
+
export function createGpuSurface(canvas, device,
|
|
34
|
+
/** The range the profile and the display allow (`chooseDisplayRange`); standard unless given. */
|
|
35
|
+
wanted = STANDARD_RANGE) {
|
|
29
36
|
const context = canvas.getContext('webgpu');
|
|
30
37
|
if (context === null) {
|
|
31
38
|
throw new Error('createGpuSurface: the canvas would not give a webgpu context');
|
|
32
39
|
}
|
|
33
|
-
|
|
40
|
+
/*
|
|
41
|
+
* **A high range is half floats with extended tone mapping**: a value of 1 is the display's
|
|
42
|
+
* paper white, and what lies above it is shown up to the display's peak instead of clipped. The
|
|
43
|
+
* colour space stays sRGB, so the composite's encoding is the one it always wrote, carried past 1.
|
|
44
|
+
*/
|
|
45
|
+
const extended = wanted.range === 'high';
|
|
46
|
+
const format = extended
|
|
47
|
+
? 'rgba16float'
|
|
48
|
+
: navigator.gpu.getPreferredCanvasFormat();
|
|
49
|
+
let range = wanted;
|
|
34
50
|
const listeners = [];
|
|
35
51
|
let lost = false;
|
|
36
52
|
let disposed = false;
|
|
@@ -89,14 +105,26 @@ export function createGpuSurface(canvas, device) {
|
|
|
89
105
|
* has no use for a transparent canvas, and the opaque path is the one a compositor can
|
|
90
106
|
* take without a blend.
|
|
91
107
|
*/
|
|
92
|
-
context.configure(
|
|
108
|
+
context.configure(extended
|
|
109
|
+
? { device, format, alphaMode: 'opaque', toneMapping: { mode: 'extended' } }
|
|
110
|
+
: { device, format, alphaMode: 'opaque' });
|
|
93
111
|
};
|
|
94
112
|
configure(canvas.width, canvas.height);
|
|
113
|
+
/*
|
|
114
|
+
* **Read back, because a browser that does not know the option ignores it** and draws the
|
|
115
|
+
* standard range from an extended-range frame, clipped at paper white, which is the frame a game
|
|
116
|
+
* would grade for the standard range if it knew. So it is told.
|
|
117
|
+
*/
|
|
118
|
+
if (extended && context.getConfiguration?.()?.toneMapping?.mode !== 'extended') {
|
|
119
|
+
range = { range: 'standard', reason: 'this browser has no extended-range canvas' };
|
|
120
|
+
}
|
|
95
121
|
return {
|
|
96
122
|
device,
|
|
97
123
|
context,
|
|
98
124
|
canvas,
|
|
99
125
|
format,
|
|
126
|
+
displayRange: range.range,
|
|
127
|
+
displayRangeReason: range.reason,
|
|
100
128
|
get lost() {
|
|
101
129
|
return lost;
|
|
102
130
|
},
|
|
@@ -147,6 +147,16 @@ export declare const FLAT_VERT_FIELDS: {
|
|
|
147
147
|
* 144 bytes a slot and is what a single ring costs.
|
|
148
148
|
*/
|
|
149
149
|
export declare const FLAT_VERT_SIZE: number;
|
|
150
|
+
/**
|
|
151
|
+
* The most sampled textures and distinct samplers any lit variant carrying the environment probe
|
|
152
|
+
* binds in its fragment stage, counted from the generated bindings: what a device must allow per
|
|
153
|
+
* stage before the probe's permutation can be built. A sampler several textures share counts once,
|
|
154
|
+
* which is what `// wgsl:share` buys.
|
|
155
|
+
*/
|
|
156
|
+
export declare function probeStageCeilings(): {
|
|
157
|
+
readonly textures: number;
|
|
158
|
+
readonly samplers: number;
|
|
159
|
+
};
|
|
150
160
|
/** Everything the generator recorded about one permutation of the fragment stage. */
|
|
151
161
|
export declare function flatFragmentBindings(variant: FlatVariant): StageBindings;
|
|
152
162
|
/** The depth format both backends compare with. */
|
|
@@ -236,7 +246,12 @@ cloth?: boolean,
|
|
|
236
246
|
/** Which shading model its fragment stage shades by, null the standard. The key must carry it. */
|
|
237
247
|
model?: SurfaceModelKind | null,
|
|
238
248
|
/** Which half of a skin it draws. The key must carry it: `|ss`, `|sd` or `|sa`. See `SkinHalf`. */
|
|
239
|
-
skinPass?: SkinHalf
|
|
249
|
+
skinPass?: SkinHalf,
|
|
250
|
+
/**
|
|
251
|
+
* The reflection pass's surface half: the draw again, against its own depth, into the two
|
|
252
|
+
* targets `reflectionSurfacePass.ts` holds. The key must carry it: `|rs`.
|
|
253
|
+
*/
|
|
254
|
+
reflectionSurface?: boolean): GPURenderPipeline;
|
|
240
255
|
/**
|
|
241
256
|
* The same pipeline, compiled off the main thread.
|
|
242
257
|
*
|
|
@@ -5,6 +5,7 @@ import { FLAT_BINDINGS, FLAT_FRAG_WGSL, FLAT_VERT_WGSL, } from '../../shaders/ge
|
|
|
5
5
|
import { vertexBufferLayouts } from './buffers.js';
|
|
6
6
|
import { shaderModule } from './shaderModules.js';
|
|
7
7
|
import { SCENE_ALPHA_COVERS } from '../../sceneCoverage.js';
|
|
8
|
+
import { REFLECTION_SURFACE_FORMAT } from './reflectionSurfacePass.js';
|
|
8
9
|
/** The material maps the flat pass reads: `2d-array` colour, filtered, not shadow maps. */
|
|
9
10
|
const SURFACE_MAPS = new Set([
|
|
10
11
|
'uAlbedo',
|
|
@@ -144,6 +145,24 @@ export const FLAT_VERT_FIELDS = FLAT_BINDINGS.flatVert.none.fields;
|
|
|
144
145
|
*/
|
|
145
146
|
export const FLAT_VERT_SIZE = Math.max(...Object.values(VERTEX_BINDINGS).map((bindings) => bindings.uniformSize));
|
|
146
147
|
const FLAT_VERT_BINDING = PLAIN_VERTEX.uniforms;
|
|
148
|
+
/**
|
|
149
|
+
* The most sampled textures and distinct samplers any lit variant carrying the environment probe
|
|
150
|
+
* binds in its fragment stage, counted from the generated bindings: what a device must allow per
|
|
151
|
+
* stage before the probe's permutation can be built. A sampler several textures share counts once,
|
|
152
|
+
* which is what `// wgsl:share` buys.
|
|
153
|
+
*/
|
|
154
|
+
export function probeStageCeilings() {
|
|
155
|
+
let textures = 0;
|
|
156
|
+
let samplers = 0;
|
|
157
|
+
for (const [variant, bindings] of Object.entries(FLAT_BINDINGS.flatFrag)) {
|
|
158
|
+
if (!variant.includes('environmentProbe'))
|
|
159
|
+
continue;
|
|
160
|
+
const listed = Object.values(bindings.textures ?? {});
|
|
161
|
+
textures = Math.max(textures, listed.length);
|
|
162
|
+
samplers = Math.max(samplers, new Set(listed.map((entry) => entry.sampler)).size);
|
|
163
|
+
}
|
|
164
|
+
return { textures, samplers };
|
|
165
|
+
}
|
|
147
166
|
/** Everything the generator recorded about one permutation of the fragment stage. */
|
|
148
167
|
export function flatFragmentBindings(variant) {
|
|
149
168
|
const found = FRAGMENT_BINDINGS[variant];
|
|
@@ -160,7 +179,7 @@ export function flatFragmentBindings(variant) {
|
|
|
160
179
|
* "GLASS_SHADOWS" not found*, and the frame drew nothing. Every override the variant declares is
|
|
161
180
|
* set, so a switch added to the shader and not to the cache is refused here rather than defaulted.
|
|
162
181
|
*/
|
|
163
|
-
function flatFragmentConstants(variant, cache, model, skinPass = 'whole') {
|
|
182
|
+
function flatFragmentConstants(variant, cache, model, skinPass = 'whole', reflectionSurface = false) {
|
|
164
183
|
const overrides = flatFragmentBindings(variant).overrides;
|
|
165
184
|
if (overrides?.['GLASS_SHADOWS'] === undefined) {
|
|
166
185
|
throw new Error(`flatPass: variant "${variant}" has no glass switch`);
|
|
@@ -178,6 +197,11 @@ function flatFragmentConstants(variant, cache, model, skinPass = 'whole') {
|
|
|
178
197
|
constants[String(id)] = skinPass !== 'whole' && name === SKIN_HALF_SWITCH[skinPass] ? 1 : 0;
|
|
179
198
|
continue;
|
|
180
199
|
}
|
|
200
|
+
/* The reflection pass's surface half, set from the key too. See `reflectionSurface.ts`. */
|
|
201
|
+
if (name === 'REFLECTION_SURFACE') {
|
|
202
|
+
constants[String(id)] = reflectionSurface ? 1 : 0;
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
181
205
|
if (!(name in cache.litSwitches)) {
|
|
182
206
|
throw new Error(`flatPass: variant "${variant}" declares a switch "${name}" no cache sets`);
|
|
183
207
|
}
|
|
@@ -481,8 +505,13 @@ cloth = false,
|
|
|
481
505
|
/** Which shading model its fragment stage shades by, null the standard. The key must carry it. */
|
|
482
506
|
model = null,
|
|
483
507
|
/** Which half of a skin it draws. The key must carry it: `|ss`, `|sd` or `|sa`. See `SkinHalf`. */
|
|
484
|
-
skinPass = 'whole'
|
|
485
|
-
|
|
508
|
+
skinPass = 'whole',
|
|
509
|
+
/**
|
|
510
|
+
* The reflection pass's surface half: the draw again, against its own depth, into the two
|
|
511
|
+
* targets `reflectionSurfacePass.ts` holds. The key must carry it: `|rs`.
|
|
512
|
+
*/
|
|
513
|
+
reflectionSurface = false) {
|
|
514
|
+
return cache.get(key, () => flatDescriptor(cache, device, layout, variant, key, present, translucent, skinned, morphed, depthWrite, depthLayer, instanced, oit, doubleSided, alphaToCoverage, skinEight, cloth, model, skinPass, reflectionSurface), true);
|
|
486
515
|
}
|
|
487
516
|
/**
|
|
488
517
|
* The same pipeline, compiled off the main thread.
|
|
@@ -562,10 +591,11 @@ oit = 'none',
|
|
|
562
591
|
/** Culls nothing: a surface seen from both faces. */
|
|
563
592
|
doubleSided = false, alphaToCoverage = false, skinEight = false,
|
|
564
593
|
/** Whether its vertex stage places vertices by a cloth binding. See `clothBinding.ts`. */
|
|
565
|
-
cloth = false, model = null, skinPass = 'whole') {
|
|
594
|
+
cloth = false, model = null, skinPass = 'whole', reflectionSurface = false) {
|
|
566
595
|
const offset = depthOffsetForLayer(depthLayer);
|
|
567
|
-
/* The diffuse and colour halves are the same surface again, into the blur's targets
|
|
568
|
-
|
|
596
|
+
/* The diffuse and colour halves are the same surface again, into the blur's targets; and so is
|
|
597
|
+
the reflection pass's surface half, into its two. */
|
|
598
|
+
const diffuseAlone = skinPass === 'diffuse' || skinPass === 'albedo' || reflectionSurface;
|
|
569
599
|
return {
|
|
570
600
|
label: key,
|
|
571
601
|
layout: device.createPipelineLayout({ bindGroupLayouts: [layout] }),
|
|
@@ -590,31 +620,33 @@ cloth = false, model = null, skinPass = 'whole') {
|
|
|
590
620
|
}),
|
|
591
621
|
entryPoint: 'main',
|
|
592
622
|
/* Every variant declares it, so every lit pipeline may set it: see `PipelineCache`. */
|
|
593
|
-
constants: flatFragmentConstants(variant, cache, model, skinPass),
|
|
594
|
-
targets:
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
blend: {
|
|
600
|
-
color: { srcFactor: 'src-alpha', dstFactor: 'one', operation: 'add' },
|
|
601
|
-
alpha: { srcFactor: 'zero', dstFactor: 'one', operation: 'add' },
|
|
602
|
-
},
|
|
603
|
-
}
|
|
604
|
-
: translucent
|
|
623
|
+
constants: flatFragmentConstants(variant, cache, model, skinPass, reflectionSurface),
|
|
624
|
+
targets: reflectionSurface
|
|
625
|
+
? [null, { format: REFLECTION_SURFACE_FORMAT }, { format: REFLECTION_SURFACE_FORMAT }]
|
|
626
|
+
: [
|
|
627
|
+
oitTarget(oit) ??
|
|
628
|
+
(translucent === 'additive'
|
|
605
629
|
? {
|
|
606
630
|
format: cache.format,
|
|
607
631
|
blend: {
|
|
608
|
-
color: {
|
|
609
|
-
|
|
610
|
-
dstFactor: 'one-minus-src-alpha',
|
|
611
|
-
operation: 'add',
|
|
612
|
-
},
|
|
613
|
-
alpha: SCENE_ALPHA_COVERS,
|
|
632
|
+
color: { srcFactor: 'src-alpha', dstFactor: 'one', operation: 'add' },
|
|
633
|
+
alpha: { srcFactor: 'zero', dstFactor: 'one', operation: 'add' },
|
|
614
634
|
},
|
|
615
635
|
}
|
|
616
|
-
:
|
|
617
|
-
|
|
636
|
+
: translucent
|
|
637
|
+
? {
|
|
638
|
+
format: cache.format,
|
|
639
|
+
blend: {
|
|
640
|
+
color: {
|
|
641
|
+
srcFactor: 'src-alpha',
|
|
642
|
+
dstFactor: 'one-minus-src-alpha',
|
|
643
|
+
operation: 'add',
|
|
644
|
+
},
|
|
645
|
+
alpha: SCENE_ALPHA_COVERS,
|
|
646
|
+
},
|
|
647
|
+
}
|
|
648
|
+
: { format: cache.format }),
|
|
649
|
+
],
|
|
618
650
|
},
|
|
619
651
|
primitive: { topology: 'triangle-list', cullMode: doubleSided ? 'none' : 'back' },
|
|
620
652
|
/* Coverage only where a sample count can carry it: WebGPU refuses it at one sample. */
|
|
@@ -5,7 +5,7 @@ import { TEMPORAL_RESOLVE_FRAG_WGSL } from '../../shaders/generated/temporalReso
|
|
|
5
5
|
import { OIT_RESOLVE_FRAG_WGSL } from '../../shaders/generated/oitResolve.wgsl.ts';
|
|
6
6
|
import { DECAL_PROJECT_FRAG_WGSL } from '../../shaders/generated/decalProject.wgsl.ts';
|
|
7
7
|
import { SSR_TRACE_FRAG_WGSL } from '../../shaders/generated/ssrTrace.wgsl.ts';
|
|
8
|
-
import { SSR_RESOLVE_FRAG_WGSL } from '../../shaders/generated/ssrResolve.wgsl.ts';
|
|
8
|
+
import { SSR_MATERIAL_RESOLVE_FRAG_WGSL, SSR_RESOLVE_FRAG_WGSL } from '../../shaders/generated/ssrResolve.wgsl.ts';
|
|
9
9
|
import { MEDIUM_FRAG_WGSL, MEDIUM_UPSAMPLE_FRAG_WGSL } from '../../shaders/generated/globalMedium.wgsl.ts';
|
|
10
10
|
import type { UniformFields } from './scatterPass.ts';
|
|
11
11
|
import type { PipelineCache } from './pipelineCache.ts';
|
|
@@ -26,7 +26,7 @@ import type { PipelineCache } from './pipelineCache.ts';
|
|
|
26
26
|
* float target the generated shaders can sample as an ordinary texture.
|
|
27
27
|
*/
|
|
28
28
|
export declare const RUSH_FRAG_FIELDS: UniformFields;
|
|
29
|
-
export declare const RUSH_FRAG_SIZE:
|
|
29
|
+
export declare const RUSH_FRAG_SIZE: 272;
|
|
30
30
|
declare const RUSH_UNIFORMS: 1;
|
|
31
31
|
declare const RUSH_TEXTURES: {
|
|
32
32
|
readonly uScene: {
|
|
@@ -39,29 +39,34 @@ declare const RUSH_TEXTURES: {
|
|
|
39
39
|
readonly sampler: 35;
|
|
40
40
|
readonly type: "sampler2D";
|
|
41
41
|
};
|
|
42
|
-
readonly
|
|
42
|
+
readonly uMotion: {
|
|
43
43
|
readonly texture: 36;
|
|
44
44
|
readonly sampler: 37;
|
|
45
45
|
readonly type: "sampler2D";
|
|
46
46
|
};
|
|
47
|
-
readonly
|
|
47
|
+
readonly uAo: {
|
|
48
48
|
readonly texture: 38;
|
|
49
49
|
readonly sampler: 39;
|
|
50
50
|
readonly type: "sampler2D";
|
|
51
51
|
};
|
|
52
|
-
readonly
|
|
52
|
+
readonly uBloom: {
|
|
53
53
|
readonly texture: 40;
|
|
54
54
|
readonly sampler: 41;
|
|
55
55
|
readonly type: "sampler2D";
|
|
56
56
|
};
|
|
57
|
-
readonly
|
|
57
|
+
readonly uExposureHeld: {
|
|
58
58
|
readonly texture: 42;
|
|
59
59
|
readonly sampler: 43;
|
|
60
60
|
readonly type: "sampler2D";
|
|
61
61
|
};
|
|
62
|
-
readonly
|
|
62
|
+
readonly uExposureLocal: {
|
|
63
63
|
readonly texture: 44;
|
|
64
64
|
readonly sampler: 45;
|
|
65
|
+
readonly type: "sampler2D";
|
|
66
|
+
};
|
|
67
|
+
readonly uGradeLut: {
|
|
68
|
+
readonly texture: 46;
|
|
69
|
+
readonly sampler: 47;
|
|
65
70
|
readonly type: "sampler3D";
|
|
66
71
|
};
|
|
67
72
|
};
|
|
@@ -180,6 +185,12 @@ export declare const PREMULTIPLIED_OVER_BLEND: GPUBlendState;
|
|
|
180
185
|
* the reflection's own and its alpha is the coverage this resolve reads.
|
|
181
186
|
*/
|
|
182
187
|
export declare const REFLECTION_OVER_BLEND: GPUBlendState;
|
|
188
|
+
/**
|
|
189
|
+
* The frame's materials' reflection, added: the found colour times the tint, less the probe's share,
|
|
190
|
+
* which is negative where the probe was brighter than what replaced it. A half-float scene takes
|
|
191
|
+
* the negative addend as the subtraction it is. Its alpha kept.
|
|
192
|
+
*/
|
|
193
|
+
export declare const FRAME_REFLECTION_BLEND: GPUBlendState;
|
|
183
194
|
/**
|
|
184
195
|
* The bloom pyramid's way back up: an octave added onto a level that the blend multiplies by that
|
|
185
196
|
* level's tint first — the blend constant, which white makes `one, one` exactly. Into the pyramid's
|
|
@@ -276,7 +287,7 @@ export declare const DECAL_TEXTURES: {
|
|
|
276
287
|
* commands, so one block rewritten between two passes gives both passes the last write.
|
|
277
288
|
*/
|
|
278
289
|
export declare const SSR_FRAG_FIELDS: UniformFields;
|
|
279
|
-
export declare const SSR_FRAG_SIZE:
|
|
290
|
+
export declare const SSR_FRAG_SIZE: 288;
|
|
280
291
|
export declare const SSR_UNIFORMS: 1;
|
|
281
292
|
export declare const SSR_TEXTURES: {
|
|
282
293
|
readonly uSsrDepth: {
|
|
@@ -289,6 +300,16 @@ export declare const SSR_TEXTURES: {
|
|
|
289
300
|
readonly sampler: 35;
|
|
290
301
|
readonly type: "sampler2D";
|
|
291
302
|
};
|
|
303
|
+
readonly uSsrProbeMap: {
|
|
304
|
+
readonly texture: 36;
|
|
305
|
+
readonly sampler: 37;
|
|
306
|
+
readonly type: "sampler2D";
|
|
307
|
+
};
|
|
308
|
+
readonly uSsrTintMap: {
|
|
309
|
+
readonly texture: 38;
|
|
310
|
+
readonly sampler: 39;
|
|
311
|
+
readonly type: "sampler2D";
|
|
312
|
+
};
|
|
292
313
|
};
|
|
293
314
|
export declare const SSR_RESOLVE_TEXTURES: {
|
|
294
315
|
readonly uSsrReflection: {
|
|
@@ -297,6 +318,27 @@ export declare const SSR_RESOLVE_TEXTURES: {
|
|
|
297
318
|
readonly type: "sampler2D";
|
|
298
319
|
};
|
|
299
320
|
};
|
|
321
|
+
/** The material resolve's block — the blur — and its three inputs. See `frameReflections.ts`. */
|
|
322
|
+
export declare const SSR_MATERIAL_FIELDS: UniformFields;
|
|
323
|
+
export declare const SSR_MATERIAL_SIZE: 16;
|
|
324
|
+
export declare const SSR_MATERIAL_UNIFORMS: 1;
|
|
325
|
+
export declare const SSR_MATERIAL_TEXTURES: {
|
|
326
|
+
readonly uSsrReflection: {
|
|
327
|
+
readonly texture: 32;
|
|
328
|
+
readonly sampler: 33;
|
|
329
|
+
readonly type: "sampler2D";
|
|
330
|
+
};
|
|
331
|
+
readonly uSsrProbeMap: {
|
|
332
|
+
readonly texture: 34;
|
|
333
|
+
readonly sampler: 35;
|
|
334
|
+
readonly type: "sampler2D";
|
|
335
|
+
};
|
|
336
|
+
readonly uSsrTintMap: {
|
|
337
|
+
readonly texture: 36;
|
|
338
|
+
readonly sampler: 37;
|
|
339
|
+
readonly type: "sampler2D";
|
|
340
|
+
};
|
|
341
|
+
};
|
|
300
342
|
/**
|
|
301
343
|
* The resolve's layout: one texture and no uniform block.
|
|
302
344
|
*
|
|
@@ -341,7 +383,7 @@ export declare const MEDIUM_UPSAMPLE_TEXTURES: {
|
|
|
341
383
|
readonly type: "sampler2D";
|
|
342
384
|
};
|
|
343
385
|
};
|
|
344
|
-
export { RUSH_FRAG_WGSL, AO_FRAG_WGSL, AO_BLUR_FRAG_WGSL, TEMPORAL_RESOLVE_FRAG_WGSL, OIT_RESOLVE_FRAG_WGSL, DECAL_PROJECT_FRAG_WGSL, SSR_TRACE_FRAG_WGSL, SSR_RESOLVE_FRAG_WGSL, };
|
|
386
|
+
export { RUSH_FRAG_WGSL, AO_FRAG_WGSL, AO_BLUR_FRAG_WGSL, TEMPORAL_RESOLVE_FRAG_WGSL, OIT_RESOLVE_FRAG_WGSL, DECAL_PROJECT_FRAG_WGSL, SSR_TRACE_FRAG_WGSL, SSR_RESOLVE_FRAG_WGSL, SSR_MATERIAL_RESOLVE_FRAG_WGSL, };
|
|
345
387
|
export { BLOOM_PREFILTER_FRAG_WGSL, BLOOM_DOWNSAMPLE_FRAG_WGSL, BLOOM_UPSAMPLE_FRAG_WGSL };
|
|
346
388
|
export { RUSH_UNIFORMS, RUSH_TEXTURES };
|
|
347
389
|
export declare const AO_UNIFORMS: 1;
|
|
@@ -6,7 +6,7 @@ import { TEMPORALRESOLVE_BINDINGS as TAA_BINDINGS, TEMPORAL_RESOLVE_FRAG_WGSL, }
|
|
|
6
6
|
import { OITRESOLVE_BINDINGS as OIT_BINDINGS, OIT_RESOLVE_FRAG_WGSL, } from '../../shaders/generated/oitResolve.wgsl.js';
|
|
7
7
|
import { DECALPROJECT_BINDINGS as DECAL_BINDINGS, DECAL_PROJECT_FRAG_WGSL, } from '../../shaders/generated/decalProject.wgsl.js';
|
|
8
8
|
import { SSRTRACE_BINDINGS as SSR_BINDINGS, SSR_TRACE_FRAG_WGSL, } from '../../shaders/generated/ssrTrace.wgsl.js';
|
|
9
|
-
import { SSRRESOLVE_BINDINGS as SSR_RESOLVE_BINDINGS, SSR_RESOLVE_FRAG_WGSL, } from '../../shaders/generated/ssrResolve.wgsl.js';
|
|
9
|
+
import { SSRRESOLVE_BINDINGS as SSR_RESOLVE_BINDINGS, SSR_MATERIAL_RESOLVE_FRAG_WGSL, SSR_RESOLVE_FRAG_WGSL, } from '../../shaders/generated/ssrResolve.wgsl.js';
|
|
10
10
|
import { GLOBALMEDIUM_BINDINGS as MEDIUM_BINDINGS, MEDIUM_FRAG_WGSL, MEDIUM_UPSAMPLE_FRAG_WGSL, } from '../../shaders/generated/globalMedium.wgsl.js';
|
|
11
11
|
import { shaderModule } from './shaderModules.js';
|
|
12
12
|
import { SCENE_ALPHA_KEEPS, SCENE_ALPHA_TRANSMITS } from '../../sceneCoverage.js';
|
|
@@ -252,6 +252,15 @@ export const REFLECTION_OVER_BLEND = {
|
|
|
252
252
|
color: { srcFactor: 'one', dstFactor: 'one-minus-src-alpha', operation: 'add' },
|
|
253
253
|
alpha: SCENE_ALPHA_KEEPS,
|
|
254
254
|
};
|
|
255
|
+
/**
|
|
256
|
+
* The frame's materials' reflection, added: the found colour times the tint, less the probe's share,
|
|
257
|
+
* which is negative where the probe was brighter than what replaced it. A half-float scene takes
|
|
258
|
+
* the negative addend as the subtraction it is. Its alpha kept.
|
|
259
|
+
*/
|
|
260
|
+
export const FRAME_REFLECTION_BLEND = {
|
|
261
|
+
color: { srcFactor: 'one', dstFactor: 'one', operation: 'add' },
|
|
262
|
+
alpha: SCENE_ALPHA_KEEPS,
|
|
263
|
+
};
|
|
255
264
|
/**
|
|
256
265
|
* The bloom pyramid's way back up: an octave added onto a level that the blend multiplies by that
|
|
257
266
|
* level's tint first — the blend constant, which white makes `one, one` exactly. Into the pyramid's
|
|
@@ -340,6 +349,11 @@ export const SSR_FRAG_SIZE = SSR_BINDINGS.SSR_TRACE_FRAG.uniformSize;
|
|
|
340
349
|
export const SSR_UNIFORMS = SSR_BINDINGS.SSR_TRACE_FRAG.uniforms;
|
|
341
350
|
export const SSR_TEXTURES = SSR_BINDINGS.SSR_TRACE_FRAG.textures;
|
|
342
351
|
export const SSR_RESOLVE_TEXTURES = SSR_RESOLVE_BINDINGS.SSR_RESOLVE_FRAG.textures;
|
|
352
|
+
/** The material resolve's block — the blur — and its three inputs. See `frameReflections.ts`. */
|
|
353
|
+
export const SSR_MATERIAL_FIELDS = SSR_RESOLVE_BINDINGS.SSR_MATERIAL_RESOLVE_FRAG.fields;
|
|
354
|
+
export const SSR_MATERIAL_SIZE = SSR_RESOLVE_BINDINGS.SSR_MATERIAL_RESOLVE_FRAG.uniformSize;
|
|
355
|
+
export const SSR_MATERIAL_UNIFORMS = SSR_RESOLVE_BINDINGS.SSR_MATERIAL_RESOLVE_FRAG.uniforms;
|
|
356
|
+
export const SSR_MATERIAL_TEXTURES = SSR_RESOLVE_BINDINGS.SSR_MATERIAL_RESOLVE_FRAG.textures;
|
|
343
357
|
/**
|
|
344
358
|
* The resolve's layout: one texture and no uniform block.
|
|
345
359
|
*
|
|
@@ -390,7 +404,7 @@ export const MEDIUM_UNIFORMS = MEDIUM_BINDINGS.MEDIUM_FRAG.uniforms;
|
|
|
390
404
|
export const MEDIUM_TEXTURES = MEDIUM_BINDINGS.MEDIUM_FRAG.textures;
|
|
391
405
|
export const MEDIUM_UPSAMPLE_UNIFORMS = MEDIUM_BINDINGS.MEDIUM_UPSAMPLE_FRAG.uniforms;
|
|
392
406
|
export const MEDIUM_UPSAMPLE_TEXTURES = MEDIUM_BINDINGS.MEDIUM_UPSAMPLE_FRAG.textures;
|
|
393
|
-
export { RUSH_FRAG_WGSL, AO_FRAG_WGSL, AO_BLUR_FRAG_WGSL, TEMPORAL_RESOLVE_FRAG_WGSL, OIT_RESOLVE_FRAG_WGSL, DECAL_PROJECT_FRAG_WGSL, SSR_TRACE_FRAG_WGSL, SSR_RESOLVE_FRAG_WGSL, };
|
|
407
|
+
export { RUSH_FRAG_WGSL, AO_FRAG_WGSL, AO_BLUR_FRAG_WGSL, TEMPORAL_RESOLVE_FRAG_WGSL, OIT_RESOLVE_FRAG_WGSL, DECAL_PROJECT_FRAG_WGSL, SSR_TRACE_FRAG_WGSL, SSR_RESOLVE_FRAG_WGSL, SSR_MATERIAL_RESOLVE_FRAG_WGSL, };
|
|
394
408
|
export { BLOOM_PREFILTER_FRAG_WGSL, BLOOM_DOWNSAMPLE_FRAG_WGSL, BLOOM_UPSAMPLE_FRAG_WGSL };
|
|
395
409
|
export { RUSH_UNIFORMS, RUSH_TEXTURES };
|
|
396
410
|
export const AO_UNIFORMS = AO_BINDINGS.AO_FRAG.uniforms;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { DrawCommand } from './drawCommand.ts';
|
|
2
|
+
/** Both targets' format: linear light and a tint, which an eight-bit target would clip and band. */
|
|
3
|
+
export declare const REFLECTION_SURFACE_FORMAT: GPUTextureFormat;
|
|
4
|
+
export declare class ReflectionSurfacePass {
|
|
5
|
+
private readonly device;
|
|
6
|
+
private readonly commands;
|
|
7
|
+
private probe;
|
|
8
|
+
private tint;
|
|
9
|
+
/** The environment as the frame shows it, and the roughness in alpha. */
|
|
10
|
+
probeView: GPUTextureView | null;
|
|
11
|
+
/** What a found reflection is multiplied by. */
|
|
12
|
+
tintView: GPUTextureView | null;
|
|
13
|
+
constructor(device: GPUDevice);
|
|
14
|
+
/** A command for one opaque lit draw's surface half, filled by the caller. */
|
|
15
|
+
take(): DrawCommand;
|
|
16
|
+
/** How many draws the frame kept. */
|
|
17
|
+
get kept(): number;
|
|
18
|
+
/** A new frame keeps nothing yet. */
|
|
19
|
+
reset(): void;
|
|
20
|
+
/** The two targets at the frame's size, made again only when it changes. */
|
|
21
|
+
size(width: number, height: number): void;
|
|
22
|
+
/**
|
|
23
|
+
* Every kept draw into the two targets against the frame's depth, which it reads and does not
|
|
24
|
+
* write; both cleared first, so a pixel no lit surface reached reflects nothing. Called with no
|
|
25
|
+
* pass open on `encoder`, and drawn even with nothing kept, since the clear is what the trace
|
|
26
|
+
* reads there.
|
|
27
|
+
*/
|
|
28
|
+
draw(encoder: GPUCommandEncoder, depth: GPUTextureView, issue: (pass: GPURenderPassEncoder, command: DrawCommand) => void): void;
|
|
29
|
+
release(): void;
|
|
30
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The surface half of a reflection traced through the frame's materials, on this backend: the
|
|
3
|
+
* frame's opaque lit draws again, against the depth they wrote, into two half-float targets — the
|
|
4
|
+
* environment as the frame shows it with the surface's roughness, and what a reflection found in the
|
|
5
|
+
* frame is multiplied by to land in its place. `shaders/flat/reflectionSurface.ts` is what the two
|
|
6
|
+
* hold and why the swap is exact; this is where they are drawn.
|
|
7
|
+
*
|
|
8
|
+
* **Why a second pass and not a second output of the frame's.** Every pipeline drawn into the
|
|
9
|
+
* frame's pass would have to declare a target it never writes — the sky, water, particles, text and
|
|
10
|
+
* every pass a consumer registers — so the frame keeps its one attachment, and the lit stage's two
|
|
11
|
+
* extra outputs land nowhere there. Here they land: the same pipelines with `REFLECTION_SURFACE` on,
|
|
12
|
+
* which leaves before the lamps, the same bind groups and ring slots, tested `equal` against the
|
|
13
|
+
* frame's depth so only what the frame kept writes.
|
|
14
|
+
*
|
|
15
|
+
* **The draws are commands, kept the way the skin's halves are** (`skinScatterPass.ts`): the frame
|
|
16
|
+
* graph's pool is spent at every flush, and these are replayed after the flush that ends the frame's
|
|
17
|
+
* pass. Each holds the ring slots its frame draw used, which stay valid until the frame's last
|
|
18
|
+
* submit, after this has run.
|
|
19
|
+
*
|
|
20
|
+
* **What it costs**: every opaque lit draw twice, the second without its lamps; two half-float
|
|
21
|
+
* targets the size of the frame. Single-sampled only, as the trace that reads them is.
|
|
22
|
+
*/
|
|
23
|
+
import { createCommandPool, resetPool, takeCommand } from './drawCommand.js';
|
|
24
|
+
/** Both targets' format: linear light and a tint, which an eight-bit target would clip and band. */
|
|
25
|
+
export const REFLECTION_SURFACE_FORMAT = 'rgba16float';
|
|
26
|
+
const USAGE_TARGET = 0x10 | 0x4; // RENDER_ATTACHMENT | TEXTURE_BINDING
|
|
27
|
+
export class ReflectionSurfacePass {
|
|
28
|
+
device;
|
|
29
|
+
commands = createCommandPool(256);
|
|
30
|
+
probe = null;
|
|
31
|
+
tint = null;
|
|
32
|
+
/** The environment as the frame shows it, and the roughness in alpha. */
|
|
33
|
+
probeView = null;
|
|
34
|
+
/** What a found reflection is multiplied by. */
|
|
35
|
+
tintView = null;
|
|
36
|
+
constructor(device) {
|
|
37
|
+
this.device = device;
|
|
38
|
+
}
|
|
39
|
+
/** A command for one opaque lit draw's surface half, filled by the caller. */
|
|
40
|
+
take() {
|
|
41
|
+
return this.commands.commands[takeCommand(this.commands)];
|
|
42
|
+
}
|
|
43
|
+
/** How many draws the frame kept. */
|
|
44
|
+
get kept() {
|
|
45
|
+
return this.commands.taken;
|
|
46
|
+
}
|
|
47
|
+
/** A new frame keeps nothing yet. */
|
|
48
|
+
reset() {
|
|
49
|
+
resetPool(this.commands);
|
|
50
|
+
}
|
|
51
|
+
/** The two targets at the frame's size, made again only when it changes. */
|
|
52
|
+
size(width, height) {
|
|
53
|
+
if (this.probe !== null && this.probe.width === width && this.probe.height === height)
|
|
54
|
+
return;
|
|
55
|
+
this.release();
|
|
56
|
+
const make = (label) => this.device.createTexture({
|
|
57
|
+
label,
|
|
58
|
+
size: [width, height],
|
|
59
|
+
format: REFLECTION_SURFACE_FORMAT,
|
|
60
|
+
usage: USAGE_TARGET,
|
|
61
|
+
});
|
|
62
|
+
this.probe = make('reflection.probe');
|
|
63
|
+
this.tint = make('reflection.tint');
|
|
64
|
+
this.probeView = this.probe.createView();
|
|
65
|
+
this.tintView = this.tint.createView();
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Every kept draw into the two targets against the frame's depth, which it reads and does not
|
|
69
|
+
* write; both cleared first, so a pixel no lit surface reached reflects nothing. Called with no
|
|
70
|
+
* pass open on `encoder`, and drawn even with nothing kept, since the clear is what the trace
|
|
71
|
+
* reads there.
|
|
72
|
+
*/
|
|
73
|
+
draw(encoder, depth, issue) {
|
|
74
|
+
const probe = this.probeView;
|
|
75
|
+
const tint = this.tintView;
|
|
76
|
+
if (probe === null || tint === null)
|
|
77
|
+
return;
|
|
78
|
+
const pass = encoder.beginRenderPass({
|
|
79
|
+
label: 'reflection.surface',
|
|
80
|
+
colorAttachments: [
|
|
81
|
+
null,
|
|
82
|
+
{ view: probe, clearValue: [0, 0, 0, 1], loadOp: 'clear', storeOp: 'store' },
|
|
83
|
+
{ view: tint, clearValue: [0, 0, 0, 0], loadOp: 'clear', storeOp: 'store' },
|
|
84
|
+
],
|
|
85
|
+
depthStencilAttachment: { view: depth, depthReadOnly: true },
|
|
86
|
+
});
|
|
87
|
+
for (let i = 0; i < this.commands.taken; i += 1) {
|
|
88
|
+
issue(pass, this.commands.commands[i]);
|
|
89
|
+
}
|
|
90
|
+
pass.end();
|
|
91
|
+
}
|
|
92
|
+
release() {
|
|
93
|
+
this.probe?.destroy();
|
|
94
|
+
this.tint?.destroy();
|
|
95
|
+
this.probe = null;
|
|
96
|
+
this.tint = null;
|
|
97
|
+
this.probeView = null;
|
|
98
|
+
this.tintView = null;
|
|
99
|
+
}
|
|
100
|
+
}
|