@driftengine/core 4.8.2 → 4.8.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/CHANGELOG.json +127 -0
- package/README.md +1 -1
- package/dist/geometry/meshConcat.js +2 -0
- package/dist/index.d.ts +11 -4
- package/dist/index.js +22 -1
- package/dist/math/scalar.js +1 -1
- package/dist/render/anisotropicLobe.d.ts +7 -0
- package/dist/render/anisotropicLobe.js +33 -0
- package/dist/render/backend/api.d.ts +41 -4
- package/dist/render/backend/materialChanges.d.ts +7 -2
- package/dist/render/backend/materialChanges.js +8 -3
- package/dist/render/backend/select.js +8 -0
- package/dist/render/backend/webgl2/clothTextures.d.ts +27 -0
- package/dist/render/backend/webgl2/clothTextures.js +93 -0
- package/dist/render/backend/webgl2/renderer.d.ts +159 -3
- package/dist/render/backend/webgl2/renderer.js +662 -80
- package/dist/render/backend/webgl2/skinScatter.d.ts +50 -0
- package/dist/render/backend/webgl2/skinScatter.js +256 -0
- package/dist/render/backend/webgpu/buffers.d.ts +25 -11
- package/dist/render/backend/webgpu/buffers.js +98 -49
- package/dist/render/backend/webgpu/causticsPass.js +2 -1
- package/dist/render/backend/webgpu/clothSolvePack.d.ts +27 -0
- package/dist/render/backend/webgpu/clothSolvePack.js +129 -0
- package/dist/render/backend/webgpu/clothTextures.d.ts +68 -0
- package/dist/render/backend/webgpu/clothTextures.js +145 -0
- package/dist/render/backend/webgpu/compressedUpload.d.ts +18 -0
- package/dist/render/backend/webgpu/compressedUpload.js +38 -0
- package/dist/render/backend/webgpu/computeHost.d.ts +21 -0
- package/dist/render/backend/webgpu/computeHost.js +5 -0
- package/dist/render/backend/webgpu/depthPass.d.ts +29 -9
- package/dist/render/backend/webgpu/depthPass.js +43 -12
- package/dist/render/backend/webgpu/drawCommand.js +6 -2
- package/dist/render/backend/webgpu/filmPass.js +2 -1
- package/dist/render/backend/webgpu/flatPass.d.ts +43 -4
- package/dist/render/backend/webgpu/flatPass.js +111 -13
- package/dist/render/backend/webgpu/gpuSkinnedCloth.d.ts +74 -0
- package/dist/render/backend/webgpu/gpuSkinnedCloth.js +452 -0
- package/dist/render/backend/webgpu/linePass.js +2 -1
- package/dist/render/backend/webgpu/motionPass.d.ts +20 -0
- package/dist/render/backend/webgpu/motionPass.js +106 -9
- package/dist/render/backend/webgpu/panelPass.js +2 -1
- package/dist/render/backend/webgpu/particlePass.js +2 -1
- package/dist/render/backend/webgpu/plumePass.js +2 -1
- package/dist/render/backend/webgpu/postPass.d.ts +15 -3
- package/dist/render/backend/webgpu/postPass.js +25 -8
- package/dist/render/backend/webgpu/renderer.d.ts +123 -6
- package/dist/render/backend/webgpu/renderer.js +534 -58
- package/dist/render/backend/webgpu/sdfTextPass.js +2 -1
- package/dist/render/backend/webgpu/shaders/clothSolve.wgsl.d.ts +33 -0
- package/dist/render/backend/webgpu/shaders/clothSolve.wgsl.js +469 -0
- package/dist/render/backend/webgpu/skinScatterPass.d.ts +51 -0
- package/dist/render/backend/webgpu/skinScatterPass.js +253 -0
- package/dist/render/backend/webgpu/surfaceTexturePass.d.ts +4 -1
- package/dist/render/backend/webgpu/surfaceTexturePass.js +37 -12
- package/dist/render/backend/webgpu/textPass.js +2 -1
- package/dist/render/backend/webgpu/waterPass.js +2 -1
- package/dist/render/backend/webgpu/windStreakPass.js +2 -1
- package/dist/render/boltBatch.js +2 -1
- package/dist/render/causticsRenderer.js +2 -1
- package/dist/render/clothBindingData.d.ts +41 -0
- package/dist/render/clothBindingData.js +72 -0
- package/dist/render/clothPlacement.d.ts +25 -0
- package/dist/render/clothPlacement.js +85 -0
- package/dist/render/compressedSource.d.ts +66 -0
- package/dist/render/compressedSource.js +138 -0
- package/dist/render/cutoutCaster.d.ts +5 -1
- package/dist/render/cutoutCaster.js +6 -0
- package/dist/render/cutoutDither.d.ts +51 -0
- package/dist/render/cutoutDither.js +90 -0
- package/dist/render/decalPass.js +2 -1
- package/dist/render/eyeRefraction.d.ts +35 -0
- package/dist/render/eyeRefraction.js +40 -0
- package/dist/render/glCompressed.d.ts +27 -0
- package/dist/render/glCompressed.js +53 -0
- package/dist/render/globalMediumPass.js +3 -2
- package/dist/render/hairLobes.d.ts +70 -0
- package/dist/render/hairLobes.js +120 -0
- package/dist/render/lightBudget.d.ts +22 -0
- package/dist/render/lightBudget.js +22 -0
- package/dist/render/lineBatch.js +5 -1
- package/dist/render/mesh.d.ts +7 -0
- package/dist/render/mesh.js +24 -0
- package/dist/render/oitPass.js +2 -1
- package/dist/render/particleBatch.js +3 -2
- package/dist/render/particlePool.d.ts +6 -2
- package/dist/render/plumeRenderer.js +3 -2
- package/dist/render/recon/motionVectors.d.ts +4 -2
- package/dist/render/recon/motionVectors.js +6 -3
- package/dist/render/renderQuality.d.ts +29 -2
- package/dist/render/renderQuality.js +5 -0
- package/dist/render/rendererHarness.js +4 -0
- package/dist/render/sceneCoverage.d.ts +54 -0
- package/dist/render/sceneCoverage.js +72 -0
- package/dist/render/sceneTarget.d.ts +12 -0
- package/dist/render/sceneTarget.js +14 -0
- package/dist/render/sdfTextRenderer.js +2 -1
- package/dist/render/shaders/clothBinding.d.ts +22 -0
- package/dist/render/shaders/clothBinding.js +80 -0
- package/dist/render/shaders/depth.js +45 -8
- package/dist/render/shaders/flat/anisotropic.d.ts +15 -0
- package/dist/render/shaders/flat/anisotropic.js +68 -0
- package/dist/render/shaders/flat/eye.d.ts +1 -0
- package/dist/render/shaders/flat/eye.js +81 -0
- package/dist/render/shaders/flat/hair.d.ts +1 -0
- package/dist/render/shaders/flat/hair.js +101 -0
- package/dist/render/shaders/flat/index.js +42 -3
- package/dist/render/shaders/flat/main.d.ts +1 -1
- package/dist/render/shaders/flat/main.js +113 -17
- package/dist/render/shaders/flat/models.d.ts +14 -0
- package/dist/render/shaders/flat/models.js +273 -0
- package/dist/render/shaders/flat/preamble.js +26 -24
- package/dist/render/shaders/flat/skin.d.ts +1 -0
- package/dist/render/shaders/flat/skin.js +114 -0
- package/dist/render/shaders/generated/depth.wgsl.d.ts +66 -24
- package/dist/render/shaders/generated/depth.wgsl.js +66 -24
- package/dist/render/shaders/generated/flat.wgsl.d.ts +1815 -1704
- package/dist/render/shaders/generated/flat.wgsl.js +1853 -1742
- 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 +3 -3
- package/dist/render/shaders/generated/particle.wgsl.js +3 -3
- package/dist/render/shaders/generated/rush.wgsl.d.ts +1 -1
- package/dist/render/shaders/generated/rush.wgsl.js +1 -1
- package/dist/render/shaders/generated/sdfText.wgsl.d.ts +1 -1
- package/dist/render/shaders/generated/sdfText.wgsl.js +1 -1
- package/dist/render/shaders/generated/skinBlur.wgsl.d.ts +48 -0
- package/dist/render/shaders/generated/skinBlur.wgsl.js +54 -0
- package/dist/render/shaders/generated/temporalResolve.wgsl.d.ts +1 -1
- package/dist/render/shaders/generated/temporalResolve.wgsl.js +1 -1
- package/dist/render/shaders/line.d.ts +1 -1
- package/dist/render/shaders/outputTransform.d.ts +14 -1
- package/dist/render/shaders/outputTransform.js +23 -1
- package/dist/render/shaders/particle.d.ts +3 -3
- package/dist/render/shaders/recon/motion.wgsl.d.ts +1 -1
- package/dist/render/shaders/recon/motion.wgsl.js +102 -0
- package/dist/render/shaders/recon/resolve.wgsl.js +15 -1
- package/dist/render/shaders/rush.js +13 -2
- package/dist/render/shaders/sdfText.d.ts +1 -1
- package/dist/render/shaders/skinBlur.d.ts +1 -0
- package/dist/render/shaders/skinBlur.js +103 -0
- package/dist/render/shaders/skinning.d.ts +3 -1
- package/dist/render/shaders/skinning.js +31 -4
- package/dist/render/shaders/temporalResolve.js +12 -5
- package/dist/render/shadowCasters.d.ts +13 -1
- package/dist/render/skinBlur.d.ts +41 -0
- package/dist/render/skinBlur.js +49 -0
- package/dist/render/skinScatter.d.ts +67 -0
- package/dist/render/skinScatter.js +80 -0
- package/dist/render/skinnedClothRun.d.ts +26 -0
- package/dist/render/skinnedClothRun.js +84 -0
- package/dist/render/ssrPass.js +2 -1
- package/dist/render/surfaceModel.d.ts +129 -0
- package/dist/render/surfaceModel.js +152 -0
- package/dist/render/surfaceTexture.d.ts +55 -4
- package/dist/render/surfaceTexture.js +60 -46
- package/dist/render/textRenderer.js +2 -1
- package/dist/render/vertexDefaults.js +8 -0
- package/dist/render/waterRenderer.js +2 -1
- package/dist/render/windStreakRenderer.js +2 -1
- package/package.json +6 -6
- package/src/geometry/meshConcat.ts +2 -0
- package/src/index.ts +53 -1
- package/src/math/scalar.ts +1 -1
- package/src/render/anisotropicLobe.ts +41 -0
- package/src/render/backend/api.ts +52 -3
- package/src/render/backend/materialChanges.ts +8 -3
- package/src/render/backend/select.ts +8 -0
- package/src/render/backend/webgl2/clothTextures.ts +120 -0
- package/src/render/backend/webgl2/renderer.ts +750 -80
- package/src/render/backend/webgl2/skinScatter.ts +309 -0
- package/src/render/backend/webgpu/buffers.ts +137 -63
- package/src/render/backend/webgpu/causticsPass.ts +2 -1
- package/src/render/backend/webgpu/clothSolvePack.ts +161 -0
- package/src/render/backend/webgpu/clothTextures.ts +194 -0
- package/src/render/backend/webgpu/compressedUpload.ts +65 -0
- package/src/render/backend/webgpu/computeHost.ts +25 -0
- package/src/render/backend/webgpu/depthPass.ts +43 -10
- package/src/render/backend/webgpu/drawCommand.ts +6 -2
- package/src/render/backend/webgpu/filmPass.ts +2 -1
- package/src/render/backend/webgpu/flatPass.ts +147 -8
- package/src/render/backend/webgpu/gpuSkinnedCloth.ts +502 -0
- package/src/render/backend/webgpu/linePass.ts +2 -1
- package/src/render/backend/webgpu/motionPass.ts +128 -9
- package/src/render/backend/webgpu/panelPass.ts +2 -1
- package/src/render/backend/webgpu/particlePass.ts +2 -1
- package/src/render/backend/webgpu/plumePass.ts +2 -1
- package/src/render/backend/webgpu/postPass.ts +25 -6
- package/src/render/backend/webgpu/renderer.ts +701 -52
- package/src/render/backend/webgpu/sdfTextPass.ts +2 -1
- package/src/render/backend/webgpu/shaders/clothSolve.wgsl.ts +470 -0
- package/src/render/backend/webgpu/skinScatterPass.ts +309 -0
- package/src/render/backend/webgpu/surfaceTexturePass.ts +42 -12
- package/src/render/backend/webgpu/textPass.ts +2 -1
- package/src/render/backend/webgpu/waterPass.ts +2 -1
- package/src/render/backend/webgpu/windStreakPass.ts +2 -1
- package/src/render/boltBatch.ts +2 -1
- package/src/render/causticsRenderer.ts +2 -1
- package/src/render/clothBindingData.ts +89 -0
- package/src/render/clothPlacement.ts +114 -0
- package/src/render/compressedSource.ts +198 -0
- package/src/render/cutoutCaster.ts +20 -2
- package/src/render/cutoutDither.ts +99 -0
- package/src/render/decalPass.ts +2 -1
- package/src/render/eyeRefraction.ts +72 -0
- package/src/render/glCompressed.ts +86 -0
- package/src/render/globalMediumPass.ts +3 -2
- package/src/render/hairLobes.ts +188 -0
- package/src/render/lightBudget.ts +25 -0
- package/src/render/lineBatch.ts +3 -1
- package/src/render/mesh.ts +23 -0
- package/src/render/oitPass.ts +2 -1
- package/src/render/particleBatch.ts +3 -2
- package/src/render/particlePool.ts +6 -2
- package/src/render/plumeRenderer.ts +3 -2
- package/src/render/recon/motionVectors.ts +6 -3
- package/src/render/renderQuality.ts +37 -2
- package/src/render/rendererHarness.ts +4 -0
- package/src/render/sceneCoverage.ts +78 -0
- package/src/render/sceneTarget.ts +21 -0
- package/src/render/sdfTextRenderer.ts +2 -1
- package/src/render/shaders/clothBinding.ts +81 -0
- package/src/render/shaders/depth.ts +45 -8
- package/src/render/shaders/flat/anisotropic.ts +68 -0
- package/src/render/shaders/flat/eye.ts +82 -0
- package/src/render/shaders/flat/hair.ts +102 -0
- package/src/render/shaders/flat/index.ts +42 -3
- package/src/render/shaders/flat/main.ts +113 -17
- package/src/render/shaders/flat/models.ts +286 -0
- package/src/render/shaders/flat/preamble.ts +26 -24
- package/src/render/shaders/flat/skin.ts +116 -0
- package/src/render/shaders/generated/depth.wgsl.ts +66 -24
- package/src/render/shaders/generated/flat.wgsl.ts +1853 -1742
- package/src/render/shaders/generated/line.wgsl.ts +1 -1
- package/src/render/shaders/generated/particle.wgsl.ts +3 -3
- package/src/render/shaders/generated/rush.wgsl.ts +1 -1
- package/src/render/shaders/generated/sdfText.wgsl.ts +1 -1
- package/src/render/shaders/generated/skinBlur.wgsl.ts +56 -0
- package/src/render/shaders/generated/temporalResolve.wgsl.ts +1 -1
- package/src/render/shaders/outputTransform.ts +24 -1
- package/src/render/shaders/recon/motion.wgsl.ts +102 -0
- package/src/render/shaders/recon/resolve.wgsl.ts +15 -1
- package/src/render/shaders/rush.ts +13 -2
- package/src/render/shaders/skinBlur.ts +105 -0
- package/src/render/shaders/skinning.ts +31 -4
- package/src/render/shaders/temporalResolve.ts +12 -5
- package/src/render/shadowCasters.ts +13 -0
- package/src/render/skinBlur.ts +53 -0
- package/src/render/skinScatter.ts +92 -0
- package/src/render/skinnedClothRun.ts +128 -0
- package/src/render/ssrPass.ts +2 -1
- package/src/render/surfaceModel.ts +274 -0
- package/src/render/surfaceTexture.ts +134 -63
- package/src/render/textRenderer.ts +2 -1
- package/src/render/vertexDefaults.ts +8 -0
- package/src/render/waterRenderer.ts +2 -1
- package/src/render/windStreakRenderer.ts +2 -1
- package/dist/math/exact.d.ts +0 -76
- package/dist/math/exact.js +0 -327
- package/src/math/exact.ts +0 -340
|
@@ -21,6 +21,7 @@ const RIGID = 0;
|
|
|
21
21
|
const SKINNED = 1;
|
|
22
22
|
const DYNAMIC = 2;
|
|
23
23
|
const INSTANCED = 3;
|
|
24
|
+
const CLOTH = 4;
|
|
24
25
|
|
|
25
26
|
/** An instanced record's per-draw matrices are not read; this fills their slot. */
|
|
26
27
|
const IDENTITY = new Float32Array([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
|
|
@@ -37,6 +38,22 @@ export class MotionPass {
|
|
|
37
38
|
/** A skinned record's two palettes, this frame's and last frame's, by record index. */
|
|
38
39
|
private readonly paletteNow: (GPUTextureView | null)[] = [];
|
|
39
40
|
private readonly paletteWas: (GPUTextureView | null)[] = [];
|
|
41
|
+
/** A cloth record's binding and its particles now and last frame, by record index. */
|
|
42
|
+
private readonly clothBinding: (GPUTextureView | null)[] = [];
|
|
43
|
+
private readonly clothNow: (GPUTextureView | null)[] = [];
|
|
44
|
+
private readonly clothWas: (GPUTextureView | null)[] = [];
|
|
45
|
+
private clothLayout: GPUBindGroupLayout | null = null;
|
|
46
|
+
private clothPipelineLayout: GPUPipelineLayout | null = null;
|
|
47
|
+
/** Keyed as `skinnedPipelines` is. */
|
|
48
|
+
private readonly clothPipelines = new Map<number, GPURenderPipeline>();
|
|
49
|
+
/**
|
|
50
|
+
* A bind group per particles now, particles then and binding. Weak at the top, by this frame's
|
|
51
|
+
* particles, so a character's groups go when its particles do; a steady garment settles on three.
|
|
52
|
+
*/
|
|
53
|
+
private clothGroups = new WeakMap<
|
|
54
|
+
GPUTextureView,
|
|
55
|
+
Map<GPUTextureView, Map<GPUTextureView, GPUBindGroup>>
|
|
56
|
+
>();
|
|
40
57
|
/** A rewritten record's last-frame rows, by record index. */
|
|
41
58
|
private readonly previousRows: (GPUBuffer | null)[] = [];
|
|
42
59
|
/** One pipeline per stride for rewritten meshes: current and previous rows at that stride. */
|
|
@@ -95,6 +112,28 @@ export class MotionPass {
|
|
|
95
112
|
this.paletteWas[at] = previousPalette;
|
|
96
113
|
}
|
|
97
114
|
|
|
115
|
+
/**
|
|
116
|
+
* A cloth-bound skinned draw: its skinned positions under both poses, each carried toward the
|
|
117
|
+
* cloth by its painted weight — this frame's `particles` and last frame's `previousParticles`.
|
|
118
|
+
*/
|
|
119
|
+
recordCloth(
|
|
120
|
+
mesh: GpuMesh,
|
|
121
|
+
model: ArrayLike<number>,
|
|
122
|
+
previousModel: ArrayLike<number>,
|
|
123
|
+
palette: GPUTextureView,
|
|
124
|
+
previousPalette: GPUTextureView,
|
|
125
|
+
binding: GPUTextureView,
|
|
126
|
+
particles: GPUTextureView,
|
|
127
|
+
previousParticles: GPUTextureView,
|
|
128
|
+
): void {
|
|
129
|
+
const at = this.take(mesh, model, previousModel, CLOTH);
|
|
130
|
+
this.paletteNow[at] = palette;
|
|
131
|
+
this.paletteWas[at] = previousPalette;
|
|
132
|
+
this.clothBinding[at] = binding;
|
|
133
|
+
this.clothNow[at] = particles;
|
|
134
|
+
this.clothWas[at] = previousParticles;
|
|
135
|
+
}
|
|
136
|
+
|
|
98
137
|
/** A rewritten mesh: its vertices as they were, read from `previous`, under last frame's model. */
|
|
99
138
|
recordDynamic(
|
|
100
139
|
mesh: GpuMesh,
|
|
@@ -188,6 +227,18 @@ export class MotionPass {
|
|
|
188
227
|
this.skinnedLayout = this.device.createPipelineLayout({
|
|
189
228
|
bindGroupLayouts: [this.layout, this.paletteLayout],
|
|
190
229
|
});
|
|
230
|
+
/* The binding and the two particle textures, read with `textureLoad` as the palettes are. */
|
|
231
|
+
this.clothLayout = this.device.createBindGroupLayout({
|
|
232
|
+
label: 'recon.motion.cloth',
|
|
233
|
+
entries: [0, 1, 2].map((binding) => ({
|
|
234
|
+
binding,
|
|
235
|
+
visibility: 0x1,
|
|
236
|
+
texture: { sampleType: 'unfilterable-float' as const },
|
|
237
|
+
})),
|
|
238
|
+
});
|
|
239
|
+
this.clothPipelineLayout = this.device.createPipelineLayout({
|
|
240
|
+
bindGroupLayouts: [this.layout, this.paletteLayout, this.clothLayout],
|
|
241
|
+
});
|
|
191
242
|
}
|
|
192
243
|
|
|
193
244
|
/**
|
|
@@ -198,20 +249,38 @@ export class MotionPass {
|
|
|
198
249
|
*/
|
|
199
250
|
private skinnedPipelineFor(
|
|
200
251
|
stride: number,
|
|
201
|
-
offsets: {
|
|
252
|
+
offsets: {
|
|
253
|
+
readonly joints: number;
|
|
254
|
+
readonly weights: number;
|
|
255
|
+
readonly joints2: number;
|
|
256
|
+
readonly weights2: number;
|
|
257
|
+
},
|
|
258
|
+
cloth = false,
|
|
202
259
|
): GPURenderPipeline | null {
|
|
203
|
-
|
|
204
|
-
const
|
|
260
|
+
/* A rig of eight takes the stage that sums the second four as well. See motion.wgsl.ts. */
|
|
261
|
+
const eight = offsets.joints2 >= 0 && offsets.weights2 >= 0;
|
|
262
|
+
/*
|
|
263
|
+
* Five byte counts, each under 256 because a vertex is at most 172 bytes, as five base-256
|
|
264
|
+
* digits: exact below 2^40, so two layouts can never share a key.
|
|
265
|
+
*/
|
|
266
|
+
const key =
|
|
267
|
+
(((stride * 256 + offsets.joints) * 256 + offsets.weights) * 256 + offsets.joints2 + 1) *
|
|
268
|
+
256 +
|
|
269
|
+
offsets.weights2 +
|
|
270
|
+
1;
|
|
271
|
+
const pipelines = cloth ? this.clothPipelines : this.skinnedPipelines;
|
|
272
|
+
const held = pipelines.get(key);
|
|
205
273
|
if (held !== undefined) return held;
|
|
206
274
|
const module = this.module;
|
|
207
|
-
const layout = this.skinnedLayout;
|
|
275
|
+
const layout = cloth ? this.clothPipelineLayout : this.skinnedLayout;
|
|
208
276
|
if (module === null || layout === null) return null;
|
|
277
|
+
const stage = cloth ? 'Cloth' : 'Skinned';
|
|
209
278
|
const pipeline = this.device.createRenderPipeline({
|
|
210
|
-
label: `recon.motion
|
|
279
|
+
label: `recon.motion.${cloth ? 'cloth' : 'skinned'}.${String(stride)}`,
|
|
211
280
|
layout,
|
|
212
281
|
vertex: {
|
|
213
282
|
module,
|
|
214
|
-
entryPoint:
|
|
283
|
+
entryPoint: eight ? `motion${stage}EightVert` : `motion${stage}Vert`,
|
|
215
284
|
buffers: [
|
|
216
285
|
{
|
|
217
286
|
arrayStride: stride,
|
|
@@ -219,6 +288,12 @@ export class MotionPass {
|
|
|
219
288
|
{ shaderLocation: 0, offset: 0, format: 'float32x3' },
|
|
220
289
|
{ shaderLocation: 11, offset: offsets.joints, format: 'float32x4' },
|
|
221
290
|
{ shaderLocation: 12, offset: offsets.weights, format: 'float32x4' },
|
|
291
|
+
...(eight
|
|
292
|
+
? ([
|
|
293
|
+
{ shaderLocation: 14, offset: offsets.joints2, format: 'float32x4' },
|
|
294
|
+
{ shaderLocation: 15, offset: offsets.weights2, format: 'float32x4' },
|
|
295
|
+
] as const)
|
|
296
|
+
: []),
|
|
222
297
|
],
|
|
223
298
|
},
|
|
224
299
|
],
|
|
@@ -231,7 +306,7 @@ export class MotionPass {
|
|
|
231
306
|
depthCompare: DEPTH_COMPARE_EQUAL,
|
|
232
307
|
},
|
|
233
308
|
});
|
|
234
|
-
|
|
309
|
+
pipelines.set(key, pipeline);
|
|
235
310
|
return pipeline;
|
|
236
311
|
}
|
|
237
312
|
|
|
@@ -342,6 +417,40 @@ export class MotionPass {
|
|
|
342
417
|
return group;
|
|
343
418
|
}
|
|
344
419
|
|
|
420
|
+
/** The bind group holding a cloth's binding and its two particle textures, built on first sight. */
|
|
421
|
+
private clothGroup(
|
|
422
|
+
binding: GPUTextureView,
|
|
423
|
+
now: GPUTextureView,
|
|
424
|
+
was: GPUTextureView,
|
|
425
|
+
): GPUBindGroup | null {
|
|
426
|
+
const layout = this.clothLayout;
|
|
427
|
+
if (layout === null) return null;
|
|
428
|
+
let byWas = this.clothGroups.get(now);
|
|
429
|
+
if (byWas === undefined) {
|
|
430
|
+
byWas = new Map();
|
|
431
|
+
this.clothGroups.set(now, byWas);
|
|
432
|
+
}
|
|
433
|
+
let byBinding = byWas.get(was);
|
|
434
|
+
if (byBinding === undefined) {
|
|
435
|
+
byBinding = new Map();
|
|
436
|
+
byWas.set(was, byBinding);
|
|
437
|
+
}
|
|
438
|
+
let group = byBinding.get(binding);
|
|
439
|
+
if (group === undefined) {
|
|
440
|
+
group = this.device.createBindGroup({
|
|
441
|
+
label: 'recon.motion.cloth',
|
|
442
|
+
layout,
|
|
443
|
+
entries: [
|
|
444
|
+
{ binding: 0, resource: binding },
|
|
445
|
+
{ binding: 1, resource: now },
|
|
446
|
+
{ binding: 2, resource: was },
|
|
447
|
+
],
|
|
448
|
+
});
|
|
449
|
+
byBinding.set(binding, group);
|
|
450
|
+
}
|
|
451
|
+
return group;
|
|
452
|
+
}
|
|
453
|
+
|
|
345
454
|
/** The pipeline for one vertex stride, built on first sight of it. */
|
|
346
455
|
private pipelineFor(stride: number): GPURenderPipeline | null {
|
|
347
456
|
const held = this.pipelines.get(stride);
|
|
@@ -497,14 +606,23 @@ export class MotionPass {
|
|
|
497
606
|
if (previous === null) continue;
|
|
498
607
|
pipeline = this.dynamicPipelineFor(mesh.vertexStride);
|
|
499
608
|
pass.setVertexBuffer(1, previous);
|
|
500
|
-
} else if (kind === SKINNED) {
|
|
609
|
+
} else if (kind === SKINNED || kind === CLOTH) {
|
|
501
610
|
const offsets = mesh.skinOffsets;
|
|
502
611
|
const now = this.paletteNow[i] ?? null;
|
|
503
612
|
const was = this.paletteWas[i] ?? null;
|
|
504
613
|
if (offsets === null || now === null || was === null) continue;
|
|
505
|
-
pipeline = this.skinnedPipelineFor(mesh.vertexStride, offsets);
|
|
614
|
+
pipeline = this.skinnedPipelineFor(mesh.vertexStride, offsets, kind === CLOTH);
|
|
506
615
|
const palettes = this.paletteGroup(now, was);
|
|
507
616
|
if (pipeline === null || palettes === null) continue;
|
|
617
|
+
if (kind === CLOTH) {
|
|
618
|
+
const binding = this.clothBinding[i] ?? null;
|
|
619
|
+
const particles = this.clothNow[i] ?? null;
|
|
620
|
+
const previous = this.clothWas[i] ?? null;
|
|
621
|
+
if (binding === null || particles === null || previous === null) continue;
|
|
622
|
+
const cloth = this.clothGroup(binding, particles, previous);
|
|
623
|
+
if (cloth === null) continue;
|
|
624
|
+
pass.setBindGroup(2, cloth);
|
|
625
|
+
}
|
|
508
626
|
pass.setBindGroup(1, palettes);
|
|
509
627
|
} else {
|
|
510
628
|
pipeline = this.pipelineFor(mesh.vertexStride);
|
|
@@ -526,6 +644,7 @@ export class MotionPass {
|
|
|
526
644
|
|
|
527
645
|
dispose(): void {
|
|
528
646
|
this.paletteGroups.clear();
|
|
647
|
+
this.clothGroups = new WeakMap();
|
|
529
648
|
this.frameBuffer?.destroy();
|
|
530
649
|
this.drawBuffer?.destroy();
|
|
531
650
|
this.frameBuffer = null;
|
|
@@ -7,6 +7,7 @@ import type { UniformFields } from './scatterPass.ts';
|
|
|
7
7
|
import { DEPTH_FORMAT } from './flatPass.ts';
|
|
8
8
|
import type { PipelineCache } from './pipelineCache.ts';
|
|
9
9
|
import { shaderModule } from './shaderModules.ts';
|
|
10
|
+
import { SCENE_ALPHA_COVERS } from '../../sceneCoverage.ts';
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* The panel pass: two triangles in screen space, one colour, one alpha.
|
|
@@ -121,7 +122,7 @@ export function panelPipeline(
|
|
|
121
122
|
format: cache.format,
|
|
122
123
|
blend: {
|
|
123
124
|
color: { srcFactor: 'src-alpha', dstFactor: 'one-minus-src-alpha', operation: 'add' },
|
|
124
|
-
alpha:
|
|
125
|
+
alpha: SCENE_ALPHA_COVERS,
|
|
125
126
|
},
|
|
126
127
|
},
|
|
127
128
|
],
|
|
@@ -8,6 +8,7 @@ import { DEPTH_FORMAT } from './flatPass.ts';
|
|
|
8
8
|
import type { PipelineCache } from './pipelineCache.ts';
|
|
9
9
|
import type { UniformFields } from './scatterPass.ts';
|
|
10
10
|
import { shaderModule } from './shaderModules.ts';
|
|
11
|
+
import { SCENE_ALPHA_COVERS } from '../../sceneCoverage.ts';
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* The particle pass: a crossed pair of quads per live particle, rebuilt every frame.
|
|
@@ -367,7 +368,7 @@ export function particlePipeline(
|
|
|
367
368
|
dstFactor: 'one-minus-src-alpha',
|
|
368
369
|
operation: 'add',
|
|
369
370
|
},
|
|
370
|
-
alpha:
|
|
371
|
+
alpha: SCENE_ALPHA_COVERS,
|
|
371
372
|
},
|
|
372
373
|
},
|
|
373
374
|
],
|
|
@@ -9,6 +9,7 @@ import { DEPTH_FORMAT } from './flatPass.ts';
|
|
|
9
9
|
import type { PipelineCache } from './pipelineCache.ts';
|
|
10
10
|
import type { UniformFields } from './scatterPass.ts';
|
|
11
11
|
import { shaderModule } from './shaderModules.ts';
|
|
12
|
+
import { SCENE_ALPHA_COVERS } from '../../sceneCoverage.ts';
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* The plume pass: crossed quads per plume, displaced and faded in the shaders.
|
|
@@ -251,7 +252,7 @@ function blendState(blend: 'additive' | 'alpha'): GPUBlendState {
|
|
|
251
252
|
}
|
|
252
253
|
: {
|
|
253
254
|
color: { srcFactor: 'src-alpha', dstFactor: 'one-minus-src-alpha', operation: 'add' },
|
|
254
|
-
alpha:
|
|
255
|
+
alpha: SCENE_ALPHA_COVERS,
|
|
255
256
|
};
|
|
256
257
|
}
|
|
257
258
|
|
|
@@ -39,6 +39,7 @@ import {
|
|
|
39
39
|
import type { UniformFields } from './scatterPass.ts';
|
|
40
40
|
import type { PipelineCache } from './pipelineCache.ts';
|
|
41
41
|
import { shaderModule } from './shaderModules.ts';
|
|
42
|
+
import { SCENE_ALPHA_KEEPS, SCENE_ALPHA_TRANSMITS } from '../../sceneCoverage.ts';
|
|
42
43
|
|
|
43
44
|
/**
|
|
44
45
|
* The composite: everything that happens to the frame after the world is drawn.
|
|
@@ -271,7 +272,7 @@ export function createPostStageLayout(
|
|
|
271
272
|
*/
|
|
272
273
|
export const OIT_COMPOSITE_BLEND: GPUBlendState = {
|
|
273
274
|
color: { srcFactor: 'one-minus-src-alpha', dstFactor: 'src-alpha', operation: 'add' },
|
|
274
|
-
alpha:
|
|
275
|
+
alpha: SCENE_ALPHA_TRANSMITS,
|
|
275
276
|
};
|
|
276
277
|
|
|
277
278
|
/**
|
|
@@ -290,17 +291,19 @@ export const OIT_COMPOSITE_BLEND: GPUBlendState = {
|
|
|
290
291
|
* exactly the integral — and the composite therefore never samples the colour it is modifying,
|
|
291
292
|
* which is the read both backends are entitled to call undefined.
|
|
292
293
|
*
|
|
293
|
-
* Alpha is
|
|
294
|
-
*
|
|
294
|
+
* Alpha is the transmittance again, `share * a`: the scene's alpha is how much of the pixel is
|
|
295
|
+
* still the opaque surface, which is what the composite lets ambient occlusion darken, and a
|
|
296
|
+
* medium thick enough to hide a corner hides its occlusion too (`sceneCoverage.ts`). It reaches
|
|
297
|
+
* no canvas: both are opaque, and the composite writes 1.
|
|
295
298
|
*/
|
|
296
299
|
export const MEDIUM_TRANSMIT_BLEND: GPUBlendState = {
|
|
297
300
|
color: { srcFactor: 'one', dstFactor: 'src-alpha', operation: 'add' },
|
|
298
|
-
alpha:
|
|
301
|
+
alpha: SCENE_ALPHA_TRANSMITS,
|
|
299
302
|
};
|
|
300
303
|
|
|
301
304
|
export const DECAL_MULTIPLY_BLEND: GPUBlendState = {
|
|
302
305
|
color: { srcFactor: 'zero', dstFactor: 'src', operation: 'add' },
|
|
303
|
-
alpha:
|
|
306
|
+
alpha: SCENE_ALPHA_KEEPS,
|
|
304
307
|
};
|
|
305
308
|
|
|
306
309
|
/**
|
|
@@ -316,6 +319,18 @@ export const PREMULTIPLIED_OVER_BLEND: GPUBlendState = {
|
|
|
316
319
|
alpha: { srcFactor: 'one', dstFactor: 'one-minus-src-alpha', operation: 'add' },
|
|
317
320
|
};
|
|
318
321
|
|
|
322
|
+
/**
|
|
323
|
+
* The same `over` for the resolve that lands a reflection on the scene, keeping the scene's alpha.
|
|
324
|
+
*
|
|
325
|
+
* A reflection is a layer of the surface it is seen in, so the surface's share of the pixel is
|
|
326
|
+
* unchanged (`sceneCoverage.ts`). The trace keeps `PREMULTIPLIED_OVER_BLEND`, because its target is
|
|
327
|
+
* the reflection's own and its alpha is the coverage this resolve reads.
|
|
328
|
+
*/
|
|
329
|
+
export const REFLECTION_OVER_BLEND: GPUBlendState = {
|
|
330
|
+
color: { srcFactor: 'one', dstFactor: 'one-minus-src-alpha', operation: 'add' },
|
|
331
|
+
alpha: SCENE_ALPHA_KEEPS,
|
|
332
|
+
};
|
|
333
|
+
|
|
319
334
|
export const ADDITIVE_BLEND: GPUBlendState = {
|
|
320
335
|
color: { srcFactor: 'one', dstFactor: 'one', operation: 'add' },
|
|
321
336
|
alpha: { srcFactor: 'one', dstFactor: 'one', operation: 'add' },
|
|
@@ -350,8 +365,10 @@ export function postPipelineTargets(
|
|
|
350
365
|
key: string,
|
|
351
366
|
fragment: string,
|
|
352
367
|
targets: GPUColorTargetState[],
|
|
368
|
+
/** For a pass drawn into the frame's own multisampled colour, which must match its count. */
|
|
369
|
+
sampleCount = 1,
|
|
353
370
|
): GPURenderPipeline {
|
|
354
|
-
return cache.get(key, () => describePost(device, layout, key, fragment, targets));
|
|
371
|
+
return cache.get(key, () => describePost(device, layout, key, fragment, targets, sampleCount));
|
|
355
372
|
}
|
|
356
373
|
|
|
357
374
|
function describePost(
|
|
@@ -360,8 +377,10 @@ function describePost(
|
|
|
360
377
|
key: string,
|
|
361
378
|
fragment: string,
|
|
362
379
|
targets: GPUColorTargetState[],
|
|
380
|
+
sampleCount = 1,
|
|
363
381
|
): GPURenderPipelineDescriptor {
|
|
364
382
|
return {
|
|
383
|
+
...(sampleCount > 1 ? { multisample: { count: sampleCount } } : {}),
|
|
365
384
|
label: key,
|
|
366
385
|
layout: device.createPipelineLayout({ bindGroupLayouts: [layout] }),
|
|
367
386
|
vertex: {
|