@driftengine/core 4.9.0 → 4.11.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 +133 -11
- package/README.md +43 -38
- package/dist/index.d.ts +7 -4
- package/dist/index.js +5 -4
- package/dist/render/ambientHarmonics.d.ts +1 -1
- package/dist/render/ambientHarmonics.js +1 -1
- package/dist/render/areaLights.d.ts +4 -4
- package/dist/render/areaLights.js +1 -1
- package/dist/render/backend/api.d.ts +10 -3
- package/dist/render/backend/select.js +11 -5
- package/dist/render/backend/webgl2/boneAnimations.d.ts +29 -0
- package/dist/render/backend/webgl2/boneAnimations.js +80 -0
- package/dist/render/backend/webgl2/instanced.d.ts +5 -1
- package/dist/render/backend/webgl2/instanced.js +13 -1
- package/dist/render/backend/webgl2/renderer.d.ts +189 -4
- package/dist/render/backend/webgl2/renderer.js +614 -66
- package/dist/render/backend/webgl2/skinPaletteTexture.d.ts +5 -3
- package/dist/render/backend/webgl2/skinPaletteTexture.js +6 -4
- package/dist/render/backend/webgpu/boneAnimations.d.ts +34 -0
- package/dist/render/backend/webgpu/boneAnimations.js +76 -0
- package/dist/render/backend/webgpu/buffers.d.ts +24 -4
- package/dist/render/backend/webgpu/buffers.js +116 -59
- package/dist/render/backend/webgpu/clothKernels.d.ts +8 -0
- package/dist/render/backend/webgpu/clothKernels.js +76 -0
- package/dist/render/backend/webgpu/clothOps.d.ts +39 -0
- package/dist/render/backend/webgpu/clothOps.js +78 -0
- package/dist/render/backend/webgpu/clothSetLayout.d.ts +25 -0
- package/dist/render/backend/webgpu/clothSetLayout.js +84 -0
- package/dist/render/backend/webgpu/clothSetPack.d.ts +33 -0
- package/dist/render/backend/webgpu/clothSetPack.js +144 -0
- package/dist/render/backend/webgpu/compressedUpload.d.ts +0 -1
- package/dist/render/backend/webgpu/compressedUpload.js +53 -8
- package/dist/render/backend/webgpu/depthPass.d.ts +59 -3
- package/dist/render/backend/webgpu/depthPass.js +49 -14
- package/dist/render/backend/webgpu/drawCommand.d.ts +20 -4
- package/dist/render/backend/webgpu/drawCommand.js +11 -3
- package/dist/render/backend/webgpu/flatPass.d.ts +85 -42
- package/dist/render/backend/webgpu/flatPass.js +137 -20
- package/dist/render/backend/webgpu/gpuClothSet.d.ts +80 -0
- package/dist/render/backend/webgpu/gpuClothSet.js +462 -0
- package/dist/render/backend/webgpu/instanced.d.ts +14 -1
- package/dist/render/backend/webgpu/instanced.js +24 -1
- package/dist/render/backend/webgpu/latePass.js +1 -0
- package/dist/render/backend/webgpu/materialStore.d.ts +101 -0
- package/dist/render/backend/webgpu/materialStore.js +265 -0
- package/dist/render/backend/webgpu/motionPass.js +15 -6
- package/dist/render/backend/webgpu/pipelineCache.d.ts +28 -1
- package/dist/render/backend/webgpu/pipelineCache.js +46 -1
- package/dist/render/backend/webgpu/postPass.d.ts +1 -1
- package/dist/render/backend/webgpu/renderer.d.ts +200 -35
- package/dist/render/backend/webgpu/renderer.js +993 -168
- package/dist/render/backend/webgpu/shaders/clothSolve.wgsl.d.ts +9 -2
- package/dist/render/backend/webgpu/shaders/clothSolve.wgsl.js +121 -47
- package/dist/render/backend/webgpu/skinPaletteRing.d.ts +7 -3
- package/dist/render/backend/webgpu/skinPaletteRing.js +13 -7
- package/dist/render/backend/webgpu/skinPaletteTexture.d.ts +6 -0
- package/dist/render/backend/webgpu/skinPaletteTexture.js +7 -1
- package/dist/render/backend/webgpu/staticBundles.d.ts +125 -0
- package/dist/render/backend/webgpu/staticBundles.js +242 -0
- package/dist/render/backend/webgpu/surfaceTexturePass.d.ts +10 -3
- package/dist/render/backend/webgpu/surfaceTexturePass.js +20 -2
- package/dist/render/backend/webgpu/uniformRing.d.ts +21 -0
- package/dist/render/backend/webgpu/uniformRing.js +9 -1
- package/dist/render/backend/webgpu/vertexFormats.d.ts +22 -0
- package/dist/render/backend/webgpu/vertexFormats.js +97 -0
- package/dist/render/bloomChain.d.ts +3 -3
- package/dist/render/boneAnimation.d.ts +92 -0
- package/dist/render/boneAnimation.js +133 -0
- package/dist/render/compressedSource.d.ts +33 -13
- package/dist/render/compressedSource.js +70 -25
- package/dist/render/glCompressed.js +83 -0
- package/dist/render/globalMediumPass.d.ts +2 -0
- package/dist/render/globalMediumPass.js +1 -0
- package/dist/render/indexWidth.d.ts +17 -0
- package/dist/render/indexWidth.js +23 -0
- package/dist/render/instances.d.ts +26 -0
- package/dist/render/lightBudget.d.ts +10 -0
- package/dist/render/lightBudget.js +10 -0
- package/dist/render/lightMatrix.d.ts +11 -0
- package/dist/render/lightMatrix.js +14 -0
- package/dist/render/lightmap.d.ts +1 -1
- package/dist/render/mesh.d.ts +14 -0
- package/dist/render/mesh.js +44 -14
- package/dist/render/pointLightSelection.d.ts +4 -4
- package/dist/render/renderQuality.d.ts +30 -0
- package/dist/render/renderQuality.js +5 -0
- package/dist/render/rendererHarness.d.ts +7 -0
- package/dist/render/rendererHarness.js +12 -0
- package/dist/render/screenSpaceReflection.d.ts +2 -1
- package/dist/render/shader.d.ts +15 -0
- package/dist/render/shader.js +41 -0
- package/dist/render/shaders/boneAnimation.d.ts +19 -0
- package/dist/render/shaders/boneAnimation.js +63 -0
- package/dist/render/shaders/depth.d.ts +7 -0
- package/dist/render/shaders/depth.js +35 -10
- package/dist/render/shaders/flat/directionalShadow.js +84 -10
- package/dist/render/shaders/flat/glassTint.d.ts +1 -1
- package/dist/render/shaders/flat/glassTint.js +3 -0
- package/dist/render/shaders/flat/index.d.ts +21 -0
- package/dist/render/shaders/flat/index.js +42 -7
- package/dist/render/shaders/flat/layered.d.ts +19 -0
- package/dist/render/shaders/flat/layered.js +115 -0
- package/dist/render/shaders/flat/main.d.ts +1 -1
- package/dist/render/shaders/flat/main.js +58 -21
- package/dist/render/shaders/flat/mapReads.d.ts +10 -0
- package/dist/render/shaders/flat/mapReads.js +38 -0
- package/dist/render/shaders/flat/models.js +1 -1
- package/dist/render/shaders/flat/movingSun.d.ts +21 -0
- package/dist/render/shaders/flat/movingSun.js +46 -0
- package/dist/render/shaders/flat/normalMap.d.ts +6 -2
- package/dist/render/shaders/flat/normalMap.js +14 -3
- package/dist/render/shaders/flat/overlay.d.ts +3 -2
- package/dist/render/shaders/flat/overlay.js +42 -20
- package/dist/render/shaders/flat/pointShadow.js +2 -2
- package/dist/render/shaders/flat/preamble.js +59 -27
- package/dist/render/shaders/flat/worldUv.d.ts +22 -0
- package/dist/render/shaders/flat/worldUv.js +113 -0
- package/dist/render/shaders/generated/depth.wgsl.d.ts +93 -0
- package/dist/render/shaders/generated/depth.wgsl.js +93 -0
- package/dist/render/shaders/generated/flat.wgsl.d.ts +3616 -3042
- package/dist/render/shaders/generated/flat.wgsl.js +3688 -3113
- package/dist/render/shaders/generated/globalMedium.wgsl.d.ts +8 -3
- package/dist/render/shaders/generated/globalMedium.wgsl.js +8 -3
- package/dist/render/shaders/generated/lightVolume.wgsl.d.ts +15 -10
- package/dist/render/shaders/generated/lightVolume.wgsl.js +16 -11
- package/dist/render/shaders/globalMedium.js +9 -1
- package/dist/render/shaders/lightVolume.js +9 -1
- package/dist/render/shaders/outputTransform.d.ts +7 -0
- package/dist/render/shaders/outputTransform.js +28 -14
- package/dist/render/shaders/tangentFrame.d.ts +1 -1
- package/dist/render/shaders/tangentFrame.js +16 -3
- package/dist/render/shaders/vertexChannel.d.ts +7 -0
- package/dist/render/shaders/vertexChannel.js +26 -0
- package/dist/render/skinnedClothRun.d.ts +28 -0
- package/dist/render/skinnedClothRun.js +103 -35
- package/dist/render/staticDraws.d.ts +47 -0
- package/dist/render/staticDraws.js +43 -0
- package/dist/render/surfaceLayers.d.ts +39 -0
- package/dist/render/surfaceLayers.js +26 -0
- package/dist/render/surfaceOverlay.d.ts +16 -3
- package/dist/render/surfaceOverlay.js +11 -6
- package/dist/render/surfaceProjection.d.ts +34 -0
- package/dist/render/surfaceProjection.js +30 -0
- package/dist/render/surfaceTexture.d.ts +68 -7
- package/dist/render/surfaceTexture.js +56 -17
- package/dist/render/vertexPacking.d.ts +48 -0
- package/dist/render/vertexPacking.js +68 -0
- package/package.json +6 -6
- package/src/index.ts +12 -4
- package/src/render/ambientHarmonics.ts +1 -1
- package/src/render/areaLights.ts +4 -4
- package/src/render/backend/api.ts +13 -3
- package/src/render/backend/select.ts +10 -5
- package/src/render/backend/webgl2/boneAnimations.ts +105 -0
- package/src/render/backend/webgl2/instanced.ts +20 -1
- package/src/render/backend/webgl2/renderer.ts +723 -79
- package/src/render/backend/webgl2/skinPaletteTexture.ts +6 -4
- package/src/render/backend/webgpu/boneAnimations.ts +97 -0
- package/src/render/backend/webgpu/buffers.ts +195 -70
- package/src/render/backend/webgpu/clothKernels.ts +86 -0
- package/src/render/backend/webgpu/clothOps.ts +86 -0
- package/src/render/backend/webgpu/clothSetLayout.ts +102 -0
- package/src/render/backend/webgpu/clothSetPack.ts +197 -0
- package/src/render/backend/webgpu/compressedUpload.ts +59 -9
- package/src/render/backend/webgpu/depthPass.ts +51 -10
- package/src/render/backend/webgpu/drawCommand.ts +25 -4
- package/src/render/backend/webgpu/flatPass.ts +212 -41
- package/src/render/backend/webgpu/gpuClothSet.ts +564 -0
- package/src/render/backend/webgpu/instanced.ts +32 -1
- package/src/render/backend/webgpu/latePass.ts +1 -0
- package/src/render/backend/webgpu/materialStore.ts +276 -0
- package/src/render/backend/webgpu/motionPass.ts +18 -7
- package/src/render/backend/webgpu/pipelineCache.ts +53 -7
- package/src/render/backend/webgpu/renderer.ts +1201 -202
- package/src/render/backend/webgpu/shaders/clothSolve.wgsl.ts +121 -47
- package/src/render/backend/webgpu/skinPaletteRing.ts +13 -7
- package/src/render/backend/webgpu/skinPaletteTexture.ts +7 -1
- package/src/render/backend/webgpu/staticBundles.ts +364 -0
- package/src/render/backend/webgpu/surfaceTexturePass.ts +29 -3
- package/src/render/backend/webgpu/uniformRing.ts +10 -1
- package/src/render/backend/webgpu/vertexFormats.ts +113 -0
- package/src/render/bloomChain.ts +3 -3
- package/src/render/boneAnimation.ts +223 -0
- package/src/render/compressedSource.ts +121 -29
- package/src/render/glCompressed.ts +83 -0
- package/src/render/globalMediumPass.ts +7 -0
- package/src/render/indexWidth.ts +27 -0
- package/src/render/instances.ts +27 -0
- package/src/render/lightBudget.ts +11 -0
- package/src/render/lightMatrix.ts +15 -0
- package/src/render/lightmap.ts +1 -1
- package/src/render/mesh.ts +72 -14
- package/src/render/pointLightSelection.ts +4 -4
- package/src/render/renderQuality.ts +38 -0
- package/src/render/rendererHarness.ts +15 -0
- package/src/render/screenSpaceReflection.ts +2 -1
- package/src/render/shader.ts +59 -0
- package/src/render/shaders/boneAnimation.ts +63 -0
- package/src/render/shaders/depth.ts +45 -10
- package/src/render/shaders/flat/directionalShadow.ts +84 -10
- package/src/render/shaders/flat/glassTint.ts +7 -1
- package/src/render/shaders/flat/index.ts +63 -7
- package/src/render/shaders/flat/layered.ts +115 -0
- package/src/render/shaders/flat/main.ts +58 -21
- package/src/render/shaders/flat/mapReads.ts +38 -0
- package/src/render/shaders/flat/models.ts +1 -1
- package/src/render/shaders/flat/movingSun.ts +46 -0
- package/src/render/shaders/flat/normalMap.ts +14 -3
- package/src/render/shaders/flat/overlay.ts +42 -20
- package/src/render/shaders/flat/pointShadow.ts +2 -2
- package/src/render/shaders/flat/preamble.ts +59 -27
- package/src/render/shaders/flat/worldUv.ts +113 -0
- package/src/render/shaders/generated/depth.wgsl.ts +95 -0
- package/src/render/shaders/generated/flat.wgsl.ts +3688 -3113
- package/src/render/shaders/generated/globalMedium.wgsl.ts +8 -3
- package/src/render/shaders/generated/lightVolume.wgsl.ts +16 -11
- package/src/render/shaders/globalMedium.ts +9 -1
- package/src/render/shaders/lightVolume.ts +9 -1
- package/src/render/shaders/outputTransform.ts +30 -14
- package/src/render/shaders/tangentFrame.ts +16 -3
- package/src/render/shaders/vertexChannel.ts +27 -0
- package/src/render/skinnedClothRun.ts +138 -38
- package/src/render/staticDraws.ts +95 -0
- package/src/render/surfaceLayers.ts +57 -0
- package/src/render/surfaceOverlay.ts +24 -7
- package/src/render/surfaceProjection.ts +57 -0
- package/src/render/surfaceTexture.ts +124 -27
- package/src/render/vertexPacking.ts +109 -0
- package/dist/render/backend/webgpu/gpuSkinnedCloth.d.ts +0 -74
- package/dist/render/backend/webgpu/gpuSkinnedCloth.js +0 -452
- package/src/render/backend/webgpu/gpuSkinnedCloth.ts +0 -502
package/src/render/mesh.ts
CHANGED
|
@@ -3,6 +3,13 @@
|
|
|
3
3
|
import { MorphTexture } from './backend/webgl2/morphTexture.ts';
|
|
4
4
|
import { ABSENT_ATTRIBUTE } from './vertexDefaults.ts';
|
|
5
5
|
import { UPLOAD_BYTES_PER_STEP } from './uploadStep.ts';
|
|
6
|
+
import { compactIndices } from './indexWidth.ts';
|
|
7
|
+
import {
|
|
8
|
+
fixedArray,
|
|
9
|
+
sharedValue,
|
|
10
|
+
vertexPackingOf,
|
|
11
|
+
type AttributePacking,
|
|
12
|
+
} from './vertexPacking.ts';
|
|
6
13
|
|
|
7
14
|
/*
|
|
8
15
|
* `MeshData` and its validator live in `@driftengine/drft`, because the container's whole
|
|
@@ -92,7 +99,14 @@ export class Mesh {
|
|
|
92
99
|
private readonly vao: WebGLVertexArrayObject;
|
|
93
100
|
private readonly buffers: WebGLBuffer[] = [];
|
|
94
101
|
/** Every attribute bound from a buffer, so a batch can build a vertex array of its own. */
|
|
95
|
-
private readonly layout: {
|
|
102
|
+
private readonly layout: {
|
|
103
|
+
location: number;
|
|
104
|
+
buffer: WebGLBuffer;
|
|
105
|
+
size: number;
|
|
106
|
+
/** `FLOAT`, or a sixteen-bit type read normalised: `vertexPacking.ts`. */
|
|
107
|
+
type: number;
|
|
108
|
+
normalized: boolean;
|
|
109
|
+
}[] = [];
|
|
96
110
|
private indexBuffer: WebGLBuffer | null = null;
|
|
97
111
|
/**
|
|
98
112
|
* The position and normal buffers, kept so `update` can rewrite them.
|
|
@@ -110,6 +124,8 @@ export class Mesh {
|
|
|
110
124
|
* same frame.
|
|
111
125
|
*/
|
|
112
126
|
readonly indexCount: number;
|
|
127
|
+
/** `UNSIGNED_SHORT` or `UNSIGNED_INT`, as `compactIndices` stored them: every draw says which. */
|
|
128
|
+
private readonly indexType: number;
|
|
113
129
|
/**
|
|
114
130
|
* The constant values this mesh's *absent* attributes are shaded with, re-applied on
|
|
115
131
|
* every draw.
|
|
@@ -149,6 +165,11 @@ export class Mesh {
|
|
|
149
165
|
readonly isSkinnedEight: boolean;
|
|
150
166
|
/** Whether it has texture coordinates, without which a material's maps read one texel. */
|
|
151
167
|
readonly hasUvs: boolean;
|
|
168
|
+
/**
|
|
169
|
+
* Whether it carries a grain lane, which is where second coordinates ride (`lightmap.ts`): what
|
|
170
|
+
* a bone animation reads each vertex's bone from.
|
|
171
|
+
*/
|
|
172
|
+
readonly hasGrain: boolean;
|
|
152
173
|
/** How many vertices it has, which a cloth binding is checked against. */
|
|
153
174
|
readonly vertexCount: number;
|
|
154
175
|
|
|
@@ -221,11 +242,13 @@ export class Mesh {
|
|
|
221
242
|
* that has been told a lie every frame is the shape of a stall nobody can find.
|
|
222
243
|
*/
|
|
223
244
|
const usage = dynamic ? gl.DYNAMIC_DRAW : gl.STATIC_DRAW;
|
|
245
|
+
/* How each attribute travels: sixteen-bit fixed point, or one value as a constant. */
|
|
246
|
+
const packing = vertexPackingOf(data, dynamic);
|
|
224
247
|
const positions = this.attachAttribute(gl, ATTR_POSITION, data.positions, 3, usage);
|
|
225
|
-
const normals = this.attachAttribute(gl, ATTR_NORMAL, data.normals, 3, usage);
|
|
248
|
+
const normals = this.attachAttribute(gl, ATTR_NORMAL, data.normals, 3, usage, packing.normals);
|
|
226
249
|
if (dynamic) this.deformable = { positions, normals };
|
|
227
|
-
this.
|
|
228
|
-
this.
|
|
250
|
+
this.attachShared(gl, ATTR_COLOR, data.colors, 3, packing.colors);
|
|
251
|
+
this.attachShared(gl, ATTR_EMISSIVE, data.emissive, 1, packing.emissive);
|
|
229
252
|
/*
|
|
230
253
|
* Absent means "not shiny", supplied as a constant rather than as a buffer of
|
|
231
254
|
* zeroes. `vertexAttrib1f` sets the value a *disabled* attribute reads, so this
|
|
@@ -299,7 +322,7 @@ export class Mesh {
|
|
|
299
322
|
this.constants.push({ location: ATTR_WEIGHTS, value: ABSENT_ATTRIBUTE['weights'] });
|
|
300
323
|
} else {
|
|
301
324
|
this.attachAttribute(gl, ATTR_JOINTS, data.joints, 4);
|
|
302
|
-
this.attachAttribute(gl, ATTR_WEIGHTS, data.weights, 4);
|
|
325
|
+
this.attachAttribute(gl, ATTR_WEIGHTS, data.weights, 4, gl.STATIC_DRAW, packing.weights);
|
|
303
326
|
}
|
|
304
327
|
/* The fifth to eighth influences, or zeros, which add nothing. See `isSkinnedEight`. */
|
|
305
328
|
this.isSkinnedEight = this.isSkinned && data.joints2 !== undefined;
|
|
@@ -308,7 +331,7 @@ export class Mesh {
|
|
|
308
331
|
this.constants.push({ location: ATTR_WEIGHTS2, value: ABSENT_ATTRIBUTE['weights2'] });
|
|
309
332
|
} else {
|
|
310
333
|
this.attachAttribute(gl, ATTR_JOINTS2, data.joints2, 4);
|
|
311
|
-
this.attachAttribute(gl, ATTR_WEIGHTS2, data.weights2, 4);
|
|
334
|
+
this.attachAttribute(gl, ATTR_WEIGHTS2, data.weights2, 4, gl.STATIC_DRAW, packing.weights2);
|
|
312
335
|
}
|
|
313
336
|
|
|
314
337
|
this.hasTangents = data.tangents !== undefined;
|
|
@@ -316,9 +339,10 @@ export class Mesh {
|
|
|
316
339
|
gl.disableVertexAttribArray(ATTR_TANGENT);
|
|
317
340
|
this.constants.push({ location: ATTR_TANGENT, value: ABSENT_ATTRIBUTE['tangents'] });
|
|
318
341
|
} else {
|
|
319
|
-
this.attachAttribute(gl, ATTR_TANGENT, data.tangents, 4);
|
|
342
|
+
this.attachAttribute(gl, ATTR_TANGENT, data.tangents, 4, gl.STATIC_DRAW, packing.tangents);
|
|
320
343
|
}
|
|
321
344
|
|
|
345
|
+
this.hasGrain = data.grain !== undefined;
|
|
322
346
|
if (data.grain === undefined) {
|
|
323
347
|
gl.disableVertexAttribArray(ATTR_GRAIN);
|
|
324
348
|
this.constants.push({ location: ATTR_GRAIN, value: ABSENT_ATTRIBUTE['grain'] });
|
|
@@ -345,7 +369,9 @@ export class Mesh {
|
|
|
345
369
|
this.buffers.push(indexBuffer);
|
|
346
370
|
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
|
|
347
371
|
this.indexBuffer = indexBuffer;
|
|
348
|
-
|
|
372
|
+
const indices = compactIndices(data.indices, this.vertexCount);
|
|
373
|
+
this.indexType = indices instanceof Uint16Array ? gl.UNSIGNED_SHORT : gl.UNSIGNED_INT;
|
|
374
|
+
this.allocate(gl, gl.ELEMENT_ARRAY_BUFFER, indexBuffer, indices, gl.STATIC_DRAW);
|
|
349
375
|
|
|
350
376
|
gl.bindVertexArray(null);
|
|
351
377
|
}
|
|
@@ -364,7 +390,7 @@ export class Mesh {
|
|
|
364
390
|
const value = constant.value;
|
|
365
391
|
applyConstant(gl, constant.location, value);
|
|
366
392
|
}
|
|
367
|
-
gl.drawElements(gl.TRIANGLES, this.indexCount,
|
|
393
|
+
gl.drawElements(gl.TRIANGLES, this.indexCount, this.indexType, 0);
|
|
368
394
|
}
|
|
369
395
|
|
|
370
396
|
/**
|
|
@@ -388,7 +414,14 @@ export class Mesh {
|
|
|
388
414
|
for (const attribute of this.layout) {
|
|
389
415
|
gl.bindBuffer(gl.ARRAY_BUFFER, attribute.buffer);
|
|
390
416
|
gl.enableVertexAttribArray(attribute.location);
|
|
391
|
-
gl.vertexAttribPointer(
|
|
417
|
+
gl.vertexAttribPointer(
|
|
418
|
+
attribute.location,
|
|
419
|
+
attribute.size,
|
|
420
|
+
attribute.type,
|
|
421
|
+
attribute.normalized,
|
|
422
|
+
0,
|
|
423
|
+
0,
|
|
424
|
+
);
|
|
392
425
|
}
|
|
393
426
|
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
|
|
394
427
|
gl.bindBuffer(gl.ARRAY_BUFFER, instances);
|
|
@@ -418,7 +451,7 @@ export class Mesh {
|
|
|
418
451
|
const value = constant.value;
|
|
419
452
|
applyConstant(gl, constant.location, value);
|
|
420
453
|
}
|
|
421
|
-
gl.drawElementsInstanced(gl.TRIANGLES, this.indexCount,
|
|
454
|
+
gl.drawElementsInstanced(gl.TRIANGLES, this.indexCount, this.indexType, 0, count);
|
|
422
455
|
}
|
|
423
456
|
|
|
424
457
|
dispose(gl: WebGL2RenderingContext): void {
|
|
@@ -462,24 +495,49 @@ export class Mesh {
|
|
|
462
495
|
}
|
|
463
496
|
}
|
|
464
497
|
|
|
498
|
+
/**
|
|
499
|
+
* One attribute's buffer, as floats or in its sixteen-bit fixed point (`vertexPacking.ts`), which
|
|
500
|
+
* WebGL2 reads back through a normalised `SHORT` or `UNSIGNED_SHORT`: three lanes wide where
|
|
501
|
+
* WebGPU needs four, so a normal costs six bytes here.
|
|
502
|
+
*/
|
|
465
503
|
private attachAttribute(
|
|
466
504
|
gl: WebGL2RenderingContext,
|
|
467
505
|
location: number,
|
|
468
506
|
data: Float32Array,
|
|
469
507
|
size: number,
|
|
470
508
|
usage: number = gl.STATIC_DRAW,
|
|
509
|
+
packing: AttributePacking = 'float',
|
|
471
510
|
): WebGLBuffer {
|
|
472
511
|
const buffer = gl.createBuffer();
|
|
473
512
|
if (buffer === null) throw new Error('createBuffer failed');
|
|
474
513
|
this.buffers.push(buffer);
|
|
475
514
|
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
476
|
-
|
|
515
|
+
const fixed = packing === 'snorm16' || packing === 'unorm16';
|
|
516
|
+
this.allocate(gl, gl.ARRAY_BUFFER, buffer, fixed ? fixedArray(data, packing) : data, usage);
|
|
517
|
+
const type =
|
|
518
|
+
packing === 'snorm16' ? gl.SHORT : packing === 'unorm16' ? gl.UNSIGNED_SHORT : gl.FLOAT;
|
|
477
519
|
gl.enableVertexAttribArray(location);
|
|
478
|
-
gl.vertexAttribPointer(location, size,
|
|
479
|
-
this.layout.push({ location, buffer, size });
|
|
520
|
+
gl.vertexAttribPointer(location, size, type, fixed, 0, 0);
|
|
521
|
+
this.layout.push({ location, buffer, size, type, normalized: fixed });
|
|
480
522
|
return buffer;
|
|
481
523
|
}
|
|
482
524
|
|
|
525
|
+
/** A buffer, or the one value every vertex shares as a constant, as the packing says. */
|
|
526
|
+
private attachShared(
|
|
527
|
+
gl: WebGL2RenderingContext,
|
|
528
|
+
location: number,
|
|
529
|
+
data: Float32Array,
|
|
530
|
+
size: number,
|
|
531
|
+
packing: AttributePacking,
|
|
532
|
+
): void {
|
|
533
|
+
if (packing !== 'constant') {
|
|
534
|
+
this.attachAttribute(gl, location, data, size, gl.STATIC_DRAW, packing);
|
|
535
|
+
return;
|
|
536
|
+
}
|
|
537
|
+
gl.disableVertexAttribArray(location);
|
|
538
|
+
this.constants.push({ location, value: sharedValue(data, size) });
|
|
539
|
+
}
|
|
540
|
+
|
|
483
541
|
/**
|
|
484
542
|
* Give a bound buffer its storage, and its contents now or later.
|
|
485
543
|
*
|
|
@@ -204,10 +204,10 @@ export interface PointLightSource {
|
|
|
204
204
|
inLightField?: boolean;
|
|
205
205
|
/**
|
|
206
206
|
* How the light fades with distance when it names its own way: `(1 - (d/R)^2)^n` with no distance
|
|
207
|
-
* term, `R` its radius and `n` this.
|
|
208
|
-
* so a rig authored
|
|
209
|
-
* the space it was authored for rather than one that ends a few metres out. Absent or
|
|
210
|
-
* frame's own falloff (`pointLightFalloff`), which is every light before 4.8.7.
|
|
207
|
+
* term, `R` its radius and `n` this. The usual falloff for a light without inverse-square
|
|
208
|
+
* falloff, so a rig authored that way — a fill of brightness 160 across 164 m, a key at exponent
|
|
209
|
+
* 8 — lights the space it was authored for rather than one that ends a few metres out. Absent or
|
|
210
|
+
* 0, the frame's own falloff (`pointLightFalloff`), which is every light before 4.8.7.
|
|
211
211
|
*/
|
|
212
212
|
falloffExponent?: number;
|
|
213
213
|
}
|
|
@@ -50,6 +50,9 @@ export type ShadowFilterTaps = 4 | 8 | 12;
|
|
|
50
50
|
export type DirectionalShadowDepthLayers = 1 | 2;
|
|
51
51
|
export type WaterReflectionFilterTaps = 1 | 5 | 9;
|
|
52
52
|
|
|
53
|
+
/** What a draw does when its pipeline has not compiled yet: see `RenderQuality.pipelineCompile`. */
|
|
54
|
+
export type PipelineCompile = 'wait' | 'skip';
|
|
55
|
+
|
|
53
56
|
/** How light through glass is coloured: see `RenderQuality.glassShadows`. */
|
|
54
57
|
export type GlassShadows = 'full' | 'half' | 'off';
|
|
55
58
|
|
|
@@ -220,6 +223,34 @@ export interface RenderQuality {
|
|
|
220
223
|
* lot of glass; that is what `'half'` is for. See `glassShadow.ts`.
|
|
221
224
|
*/
|
|
222
225
|
readonly glassShadows: GlassShadows;
|
|
226
|
+
/**
|
|
227
|
+
* What a lit draw does when the pipeline it needs has not compiled: one first needed inside a
|
|
228
|
+
* frame, by a material's own state — two-sided, cut out, a surface model — or a draw state a
|
|
229
|
+
* mesh's creation did not warm.
|
|
230
|
+
*
|
|
231
|
+
* **`'wait'`, the default**: the pipeline is built where the draw asks for it, and on WebGPU the
|
|
232
|
+
* browser compiles it on its GPU process's main thread, holding the frame — 130 to 400 ms a
|
|
233
|
+
* pipeline was reported on a phone, for a material first drawn mid-scene. **`'skip'`** starts the
|
|
234
|
+
* compile off that thread and leaves the draw out until it lands, a few frames to a few dozen,
|
|
235
|
+
* and the draw then appears; nothing waits. Static draws always wait, since a recorded list keeps
|
|
236
|
+
* what it recorded, and a compile that fails is built where it is next asked for, so the device
|
|
237
|
+
* says why rather than the draw vanishing for good.
|
|
238
|
+
*
|
|
239
|
+
* **The way to have neither** is to draw what a scene will use once, behind a loading screen, and
|
|
240
|
+
* await `ready()`, which waits for every compile started — whichever this says. What would make
|
|
241
|
+
* `'skip'` wrong is a frame that must hold everything it was given, such as a capture of the first
|
|
242
|
+
* frame of a scene not awaited.
|
|
243
|
+
*
|
|
244
|
+
* **Measured on a desktop GPU** (`demo/dev/pipelineCompile.html`, eight new variants at once): on
|
|
245
|
+
* WebGPU the frame that met them took 700 to 3,700 ms waiting and 17 ms skipping, the draws
|
|
246
|
+
* landing 21 to 26 frames later. WebGL2 compiles its lit programs when it is made, all but a
|
|
247
|
+
* surface model's, which it compiles at the first draw that wants one: there `'skip'` asks the
|
|
248
|
+
* driver through `KHR_parallel_shader_compile` and waits where a context does not offer it — which
|
|
249
|
+
* ANGLE on Vulkan does not. Where it is offered, ANGLE on OpenGL, the longest frame went from 820 to
|
|
250
|
+
* 1,120 ms to 630 to 700 ms: the driver still finishes its own compile at the program's first
|
|
251
|
+
* draw, which nothing above it can move.
|
|
252
|
+
*/
|
|
253
|
+
readonly pipelineCompile: PipelineCompile;
|
|
223
254
|
/**
|
|
224
255
|
* How light that scatters beneath skin is drawn, for a material whose model is `skinModel`.
|
|
225
256
|
*
|
|
@@ -973,6 +1004,7 @@ export const DEFAULT_RENDER_QUALITY: Readonly<RenderQuality> = Object.freeze({
|
|
|
973
1004
|
lightVolumeSamples: 32,
|
|
974
1005
|
directionalShadowDepthLayers: 2,
|
|
975
1006
|
glassShadows: 'full',
|
|
1007
|
+
pipelineCompile: 'wait',
|
|
976
1008
|
skinScattering: 'pre-integrated',
|
|
977
1009
|
directionalShadowMaxDistance: 6,
|
|
978
1010
|
directionalShadowMaxSlope: 3,
|
|
@@ -1140,6 +1172,7 @@ export function resolveRenderQuality(options: RenderQualityOptions = {}): Readon
|
|
|
1140
1172
|
directionalShadowDepthLayers:
|
|
1141
1173
|
options.directionalShadowDepthLayers ?? DEFAULT_RENDER_QUALITY.directionalShadowDepthLayers,
|
|
1142
1174
|
glassShadows: options.glassShadows ?? DEFAULT_RENDER_QUALITY.glassShadows,
|
|
1175
|
+
pipelineCompile: options.pipelineCompile ?? DEFAULT_RENDER_QUALITY.pipelineCompile,
|
|
1143
1176
|
skinScattering: options.skinScattering ?? DEFAULT_RENDER_QUALITY.skinScattering,
|
|
1144
1177
|
directionalShadowMaxDistance:
|
|
1145
1178
|
options.directionalShadowMaxDistance ?? DEFAULT_RENDER_QUALITY.directionalShadowMaxDistance,
|
|
@@ -1298,6 +1331,11 @@ export function resolveRenderQuality(options: RenderQualityOptions = {}): Readon
|
|
|
1298
1331
|
`RenderQuality.glassShadows must be 'full', 'half' or 'off', got ${String(quality.glassShadows)}`,
|
|
1299
1332
|
);
|
|
1300
1333
|
}
|
|
1334
|
+
if (quality.pipelineCompile !== 'wait' && quality.pipelineCompile !== 'skip') {
|
|
1335
|
+
throw new Error(
|
|
1336
|
+
`RenderQuality.pipelineCompile must be 'wait' or 'skip', got ${String(quality.pipelineCompile)}`,
|
|
1337
|
+
);
|
|
1338
|
+
}
|
|
1301
1339
|
if (quality.skinScattering !== 'pre-integrated' && quality.skinScattering !== 'screen-space') {
|
|
1302
1340
|
throw new Error(
|
|
1303
1341
|
`RenderQuality.skinScattering must be 'pre-integrated' or 'screen-space', got ${String(quality.skinScattering)}`,
|
|
@@ -58,8 +58,14 @@ export function recordingGl(
|
|
|
58
58
|
* recording.
|
|
59
59
|
*/
|
|
60
60
|
readonly uniforms?: readonly string[];
|
|
61
|
+
/**
|
|
62
|
+
* Whether a program started under `KHR_parallel_shader_compile` has finished, which the test
|
|
63
|
+
* flips: `COMPLETION_STATUS_KHR` answers `done`. Finished by default, as every program here is.
|
|
64
|
+
*/
|
|
65
|
+
readonly compiling?: { done: boolean };
|
|
61
66
|
} = {},
|
|
62
67
|
) {
|
|
68
|
+
const compiling = options.compiling ?? { done: true };
|
|
63
69
|
const extensions = new Set(options.extensions ?? []);
|
|
64
70
|
const uniforms = options.uniforms ?? [];
|
|
65
71
|
/* What `clearDepth` last set, so a module that borrows the value can be seen to put it back. */
|
|
@@ -136,6 +142,13 @@ export function recordingGl(
|
|
|
136
142
|
HALF_FLOAT: 0x140b,
|
|
137
143
|
DEPTH_COMPONENT: 0x1902,
|
|
138
144
|
UNSIGNED_INT: 0x1405,
|
|
145
|
+
/* Named so a mesh's index width and each attribute's type can be read back: the buffer its
|
|
146
|
+
indices fill, the type every draw of it names, and how each attribute is read. See
|
|
147
|
+
`mesh.test.ts`. */
|
|
148
|
+
UNSIGNED_SHORT: 0x1403,
|
|
149
|
+
SHORT: 0x1402,
|
|
150
|
+
FLOAT: 0x1406,
|
|
151
|
+
ELEMENT_ARRAY_BUFFER: 0x8893,
|
|
139
152
|
LINEAR: 0x2601,
|
|
140
153
|
COLOR_BUFFER_BIT: 0x00004000,
|
|
141
154
|
/* Named so a test can tell a mesh that declared itself deforming from one that did not. */
|
|
@@ -173,6 +186,7 @@ export function recordingGl(
|
|
|
173
186
|
if (name === 'EXT_clip_control') {
|
|
174
187
|
return { LOWER_LEFT_EXT: 0x8ca1, ZERO_TO_ONE_EXT: 0x935f, clipControlEXT: () => undefined };
|
|
175
188
|
}
|
|
189
|
+
if (name === 'KHR_parallel_shader_compile') return { COMPLETION_STATUS_KHR: 0x91b1 };
|
|
176
190
|
return {};
|
|
177
191
|
},
|
|
178
192
|
getShaderParameter: () => true,
|
|
@@ -200,6 +214,7 @@ export function recordingGl(
|
|
|
200
214
|
/* Linked yes; zero active uniforms and attributes, which ends every reflection loop at once
|
|
201
215
|
and is why this harness does not have to know a single uniform name. */
|
|
202
216
|
getProgramParameter: (program: unknown, pname: unknown) => {
|
|
217
|
+
if (pname === 0x91b1) return compiling.done;
|
|
203
218
|
if (pname === constants.ACTIVE_UNIFORMS) return uniforms.length;
|
|
204
219
|
if (pname === constants.ACTIVE_ATTRIBUTES) return 0;
|
|
205
220
|
if (pname !== constants.LINK_STATUS) return true;
|
|
@@ -370,7 +370,8 @@ export interface ReflectiveSurfaceOptions extends DecalBox {
|
|
|
370
370
|
* box. Each pixel then returns `F0 · A + B` of what its ray finds, the split-sum environment BRDF
|
|
371
371
|
* at its own view and `roughness` — Karis's fit, the one the lit stage reflects its environment
|
|
372
372
|
* by — so a floor returns more toward the horizon than underfoot, and the share follows the
|
|
373
|
-
* camera as
|
|
373
|
+
* camera as a physically based renderer weighs its reflections. **False by default**, the one
|
|
374
|
+
* share as before.
|
|
374
375
|
*
|
|
375
376
|
* **What it gives up**: the pass has no material buffer, so the roughness and F0 are the box's,
|
|
376
377
|
* not each pixel's, and nothing occludes the reflection where the lit stage's ambient occlusion
|
package/src/render/shader.ts
CHANGED
|
@@ -26,6 +26,65 @@ export function compileProgram(
|
|
|
26
26
|
return program;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
/**
|
|
30
|
+
* A program compiled and linked without asking whether that worked, since asking waits for the
|
|
31
|
+
* driver to finish: for a context offering `KHR_parallel_shader_compile`, whose
|
|
32
|
+
* `COMPLETION_STATUS_KHR` says when asking no longer waits. `finishProgram` asks then, and fails
|
|
33
|
+
* as loudly as `compileProgram` does; the stages are kept until it does, for their logs.
|
|
34
|
+
*/
|
|
35
|
+
export interface StartedProgram {
|
|
36
|
+
readonly program: WebGLProgram;
|
|
37
|
+
readonly vertex: WebGLShader;
|
|
38
|
+
readonly fragment: WebGLShader;
|
|
39
|
+
readonly label: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function startProgram(
|
|
43
|
+
gl: WebGL2RenderingContext,
|
|
44
|
+
vertexSource: string,
|
|
45
|
+
fragmentSource: string,
|
|
46
|
+
label: string,
|
|
47
|
+
): StartedProgram {
|
|
48
|
+
const stage = (type: number, source: string, name: string): WebGLShader => {
|
|
49
|
+
const shader = gl.createShader(type);
|
|
50
|
+
if (shader === null) throw new Error(`[${label}.${name}] createShader failed`);
|
|
51
|
+
gl.shaderSource(shader, source);
|
|
52
|
+
gl.compileShader(shader);
|
|
53
|
+
return shader;
|
|
54
|
+
};
|
|
55
|
+
const vertex = stage(gl.VERTEX_SHADER, vertexSource, 'vert');
|
|
56
|
+
const fragment = stage(gl.FRAGMENT_SHADER, fragmentSource, 'frag');
|
|
57
|
+
const program = gl.createProgram();
|
|
58
|
+
if (program === null) throw new Error(`[${label}] createProgram failed`);
|
|
59
|
+
gl.attachShader(program, vertex);
|
|
60
|
+
gl.attachShader(program, fragment);
|
|
61
|
+
gl.linkProgram(program);
|
|
62
|
+
return { program, vertex, fragment, label };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** A started program, checked as `compileProgram` checks one: its stages, then its link. */
|
|
66
|
+
export function finishProgram(gl: WebGL2RenderingContext, started: StartedProgram): WebGLProgram {
|
|
67
|
+
const { program, vertex, fragment, label } = started;
|
|
68
|
+
const fail = (what: string, log: string | null): never => {
|
|
69
|
+
gl.deleteShader(vertex);
|
|
70
|
+
gl.deleteShader(fragment);
|
|
71
|
+
gl.deleteProgram(program);
|
|
72
|
+
throw new Error(`[${label}${what}] ${log ?? 'no log'}`);
|
|
73
|
+
};
|
|
74
|
+
if (!gl.getShaderParameter(vertex, gl.COMPILE_STATUS)) {
|
|
75
|
+
fail('.vert compile failed:', gl.getShaderInfoLog(vertex));
|
|
76
|
+
}
|
|
77
|
+
if (!gl.getShaderParameter(fragment, gl.COMPILE_STATUS)) {
|
|
78
|
+
fail('.frag compile failed:', gl.getShaderInfoLog(fragment));
|
|
79
|
+
}
|
|
80
|
+
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
81
|
+
fail(' link failed:', gl.getProgramInfoLog(program));
|
|
82
|
+
}
|
|
83
|
+
gl.deleteShader(vertex);
|
|
84
|
+
gl.deleteShader(fragment);
|
|
85
|
+
return program;
|
|
86
|
+
}
|
|
87
|
+
|
|
29
88
|
/**
|
|
30
89
|
* Whether a uniform lookup that cannot reach the GPU is reported.
|
|
31
90
|
*
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The vertex-stage bone animation: a crowd instance's vertex turned and placed by its bone, at its
|
|
3
|
+
* instance's moment of the clip — the GLSL of `boneAnimation.ts`'s `animateBoneVertex`, line for
|
|
4
|
+
* line. Shared by the lit stage and the depth stage, so a crowd's shadow moves with it.
|
|
5
|
+
*
|
|
6
|
+
* **Three textures, read by index and never filtered**: the places and the turns, a texel a bone a
|
|
7
|
+
* frame (bones across, frames down, sizes read with `textureSize` so no uniform says them), and the
|
|
8
|
+
* batch's clocks, two floats an instance wrapped onto rows, read at `gl_InstanceID`. The clip's speed
|
|
9
|
+
* and its bone scale are the one uniform, `uBoneClip`; the scene's time is the pass's `uSceneTime`.
|
|
10
|
+
*
|
|
11
|
+
* **The bone is read from the grain lane**, which is where a mesh's second coordinates ride, stored
|
|
12
|
+
* as `-1 - u` (`lightmap.ts`). An instanced batch reads no grain of its own from that lane: a crowd's
|
|
13
|
+
* mesh carries second coordinates, which is what makes it one.
|
|
14
|
+
*
|
|
15
|
+
* Integer arithmetic for the lattice, by the 2026-09-20 rule, except where a float is clamped onto
|
|
16
|
+
* it: the first frame is `min(floor(wrapped), frames - 1)`, so the wrap that division-by-reciprocal
|
|
17
|
+
* lands on `frames` is the last frame fully blended into the first — the first, which is right.
|
|
18
|
+
*/
|
|
19
|
+
export const BONE_ANIMATION_GLSL = `
|
|
20
|
+
uniform highp sampler2D uBonePlaces;
|
|
21
|
+
uniform highp sampler2D uBoneTurns;
|
|
22
|
+
uniform highp sampler2D uInstanceClocks;
|
|
23
|
+
/** x the clip's frames a second, y how many bones one unit of the second coordinates' u counts. */
|
|
24
|
+
uniform vec2 uBoneClip;
|
|
25
|
+
|
|
26
|
+
/** v turned by the unit quaternion q. */
|
|
27
|
+
vec3 boneTurn(vec4 q, vec3 v) {
|
|
28
|
+
return v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Where the clip puts this vertex, from its place at rest; its normal and tangent turned with it.
|
|
33
|
+
*/
|
|
34
|
+
vec3 boneAnimate(vec3 position, inout vec3 normal, inout vec3 tangent) {
|
|
35
|
+
ivec2 size = textureSize(uBonePlaces, 0);
|
|
36
|
+
int clocksWidth = textureSize(uInstanceClocks, 0).x;
|
|
37
|
+
vec2 clock = texelFetch(
|
|
38
|
+
uInstanceClocks,
|
|
39
|
+
ivec2(gl_InstanceID % clocksWidth, gl_InstanceID / clocksWidth),
|
|
40
|
+
0
|
|
41
|
+
).xy;
|
|
42
|
+
float moment = (uSceneTime * clock.y + clock.x) * uBoneClip.x;
|
|
43
|
+
float frames = float(size.y);
|
|
44
|
+
float wrapped = moment - frames * floor(moment / frames);
|
|
45
|
+
int first = min(int(floor(wrapped)), size.y - 1);
|
|
46
|
+
int second = first + 1 == size.y ? 0 : first + 1;
|
|
47
|
+
float blend = clamp(wrapped - float(first), 0.0, 1.0);
|
|
48
|
+
int bone = clamp(int(floor((-1.0 - aGrain) * uBoneClip.y + 0.5)), 0, size.x - 1);
|
|
49
|
+
vec4 q0 = texelFetch(uBoneTurns, ivec2(bone, first), 0);
|
|
50
|
+
vec4 q1 = texelFetch(uBoneTurns, ivec2(bone, second), 0);
|
|
51
|
+
/* The shorter arc: a quaternion and its negation are one turn. */
|
|
52
|
+
if (dot(q0, q1) < 0.0) q1 = -q1;
|
|
53
|
+
vec4 q = normalize(mix(q0, q1, blend));
|
|
54
|
+
vec3 place = mix(
|
|
55
|
+
texelFetch(uBonePlaces, ivec2(bone, first), 0).xyz,
|
|
56
|
+
texelFetch(uBonePlaces, ivec2(bone, second), 0).xyz,
|
|
57
|
+
blend
|
|
58
|
+
);
|
|
59
|
+
normal = boneTurn(q, normal);
|
|
60
|
+
tangent = boneTurn(q, tangent);
|
|
61
|
+
return boneTurn(q, position) + place;
|
|
62
|
+
}
|
|
63
|
+
`;
|
|
@@ -5,6 +5,7 @@ import { CUTOUT_DITHER_GLSL } from '../cutoutDither.ts';
|
|
|
5
5
|
import { SKINNING_GLSL } from './skinning.ts';
|
|
6
6
|
import { CLOTH_BINDING_GLSL } from './clothBinding.ts';
|
|
7
7
|
import { CHANNEL_ATTRIBUTE, CHANNEL_BEND } from './vertexChannel.ts';
|
|
8
|
+
import { BONE_ANIMATION_GLSL } from './boneAnimation.ts';
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Depth-only shadow pass. Its optional peel mode rejects the first recorded
|
|
@@ -78,6 +79,17 @@ uniform vec2 uUvOffset;
|
|
|
78
79
|
uniform vec2 uAlphaCutout;
|
|
79
80
|
#endif
|
|
80
81
|
|
|
82
|
+
#if ANIMATED
|
|
83
|
+
/*
|
|
84
|
+
* **A bone animation's, after every other declaration** so no field of the variants before it
|
|
85
|
+
* moves: the grain lane the vertex's bone rides in, the scene's clock, and the chunk the colour
|
|
86
|
+
* pass runs — the same expression, or a crowd's shadow stands still while the crowd moves.
|
|
87
|
+
*/
|
|
88
|
+
layout(location = 8) in float aGrain;
|
|
89
|
+
uniform float uSceneTime;
|
|
90
|
+
${BONE_ANIMATION_GLSL}
|
|
91
|
+
#endif
|
|
92
|
+
|
|
81
93
|
out vec4 vLightPosition;
|
|
82
94
|
#if CUTOUT
|
|
83
95
|
/* The texture coordinate and, in z, the texture-array layer the face wears. */
|
|
@@ -99,6 +111,12 @@ void main() {
|
|
|
99
111
|
#else
|
|
100
112
|
vec4 local = vec4(aPosition, 1.0);
|
|
101
113
|
#endif
|
|
114
|
+
#if ANIMATED
|
|
115
|
+
/* Turned and placed as the colour pass turns and places it; its normal and tangent unused. */
|
|
116
|
+
vec3 animatedNormal = vec3(0.0, 1.0, 0.0);
|
|
117
|
+
vec3 animatedTangent = vec3(1.0, 0.0, 0.0);
|
|
118
|
+
local = vec4(boneAnimate(local.xyz, animatedNormal, animatedTangent), 1.0);
|
|
119
|
+
#endif
|
|
102
120
|
#if INSTANCED
|
|
103
121
|
mat4 model = mat4(aInstanceModel0, aInstanceModel1, aInstanceModel2, aInstanceModel3);
|
|
104
122
|
/* The bottom row is the instance's texture cell, rebuilt as the row it stands for: see flat. */
|
|
@@ -148,14 +166,14 @@ void main() {
|
|
|
148
166
|
/** The rigid variant: the world, a prop, a mesh with no rig behind it. */
|
|
149
167
|
export const DEPTH_VERT = resolveConditionals(
|
|
150
168
|
DEPTH_VERT_SOURCE,
|
|
151
|
-
{ SKINNED: false, INSTANCED: false, CUTOUT: false, GLASS: false },
|
|
169
|
+
{ SKINNED: false, INSTANCED: false, CUTOUT: false, GLASS: false, ANIMATED: false },
|
|
152
170
|
'depth',
|
|
153
171
|
);
|
|
154
172
|
|
|
155
173
|
/** The skinned variant, which reads a joint palette and moves the vertex by it. */
|
|
156
174
|
export const DEPTH_SKINNED_VERT = resolveConditionals(
|
|
157
175
|
DEPTH_VERT_SOURCE,
|
|
158
|
-
{ SKINNED: true, INSTANCED: false, CUTOUT: false, GLASS: false },
|
|
176
|
+
{ SKINNED: true, INSTANCED: false, CUTOUT: false, GLASS: false, ANIMATED: false },
|
|
159
177
|
'depth-skinned',
|
|
160
178
|
);
|
|
161
179
|
|
|
@@ -169,7 +187,7 @@ export const DEPTH_SKINNED_VERT = resolveConditionals(
|
|
|
169
187
|
*/
|
|
170
188
|
export const DEPTH_INSTANCED_VERT = resolveConditionals(
|
|
171
189
|
DEPTH_VERT_SOURCE,
|
|
172
|
-
{ SKINNED: false, INSTANCED: true, CUTOUT: false, GLASS: false },
|
|
190
|
+
{ SKINNED: false, INSTANCED: true, CUTOUT: false, GLASS: false, ANIMATED: false },
|
|
173
191
|
'depth-instanced',
|
|
174
192
|
);
|
|
175
193
|
|
|
@@ -185,16 +203,33 @@ export const DEPTH_INSTANCED_VERT = resolveConditionals(
|
|
|
185
203
|
*/
|
|
186
204
|
export const DEPTH_CUTOUT_VERT = resolveConditionals(
|
|
187
205
|
DEPTH_VERT_SOURCE,
|
|
188
|
-
{ SKINNED: false, INSTANCED: false, CUTOUT: true, GLASS: false },
|
|
206
|
+
{ SKINNED: false, INSTANCED: false, CUTOUT: true, GLASS: false, ANIMATED: false },
|
|
189
207
|
'depth-cutout',
|
|
190
208
|
);
|
|
191
209
|
|
|
192
210
|
export const DEPTH_INSTANCED_CUTOUT_VERT = resolveConditionals(
|
|
193
211
|
DEPTH_VERT_SOURCE,
|
|
194
|
-
{ SKINNED: false, INSTANCED: true, CUTOUT: true, GLASS: false },
|
|
212
|
+
{ SKINNED: false, INSTANCED: true, CUTOUT: true, GLASS: false, ANIMATED: false },
|
|
195
213
|
'depth-instanced-cutout',
|
|
196
214
|
);
|
|
197
215
|
|
|
216
|
+
/**
|
|
217
|
+
* The variants a crowd casts through: an instanced batch playing a bone animation, its vertices
|
|
218
|
+
* where the clip puts them at each instance's moment. See `shaders/boneAnimation.ts`. No glass
|
|
219
|
+
* variant: a crowd is not glass, and a glass batch that animates casts its tint from rest.
|
|
220
|
+
*/
|
|
221
|
+
export const DEPTH_INSTANCED_ANIMATED_VERT = resolveConditionals(
|
|
222
|
+
DEPTH_VERT_SOURCE,
|
|
223
|
+
{ SKINNED: false, INSTANCED: true, CUTOUT: false, GLASS: false, ANIMATED: true },
|
|
224
|
+
'depth-instanced-animated',
|
|
225
|
+
);
|
|
226
|
+
|
|
227
|
+
export const DEPTH_INSTANCED_ANIMATED_CUTOUT_VERT = resolveConditionals(
|
|
228
|
+
DEPTH_VERT_SOURCE,
|
|
229
|
+
{ SKINNED: false, INSTANCED: true, CUTOUT: true, GLASS: false, ANIMATED: true },
|
|
230
|
+
'depth-instanced-animated-cutout',
|
|
231
|
+
);
|
|
232
|
+
|
|
198
233
|
export const DEPTH_FRAG = `#version 300 es
|
|
199
234
|
precision highp float;
|
|
200
235
|
in vec4 vLightPosition;
|
|
@@ -269,27 +304,27 @@ void main() {
|
|
|
269
304
|
*/
|
|
270
305
|
export const GLASS_TINT_VERT = resolveConditionals(
|
|
271
306
|
DEPTH_VERT_SOURCE,
|
|
272
|
-
{ SKINNED: false, INSTANCED: false, CUTOUT: false, GLASS: true },
|
|
307
|
+
{ SKINNED: false, INSTANCED: false, CUTOUT: false, GLASS: true, ANIMATED: false },
|
|
273
308
|
'glass-tint',
|
|
274
309
|
);
|
|
275
310
|
export const GLASS_TINT_SKINNED_VERT = resolveConditionals(
|
|
276
311
|
DEPTH_VERT_SOURCE,
|
|
277
|
-
{ SKINNED: true, INSTANCED: false, CUTOUT: false, GLASS: true },
|
|
312
|
+
{ SKINNED: true, INSTANCED: false, CUTOUT: false, GLASS: true, ANIMATED: false },
|
|
278
313
|
'glass-tint-skinned',
|
|
279
314
|
);
|
|
280
315
|
export const GLASS_TINT_INSTANCED_VERT = resolveConditionals(
|
|
281
316
|
DEPTH_VERT_SOURCE,
|
|
282
|
-
{ SKINNED: false, INSTANCED: true, CUTOUT: false, GLASS: true },
|
|
317
|
+
{ SKINNED: false, INSTANCED: true, CUTOUT: false, GLASS: true, ANIMATED: false },
|
|
283
318
|
'glass-tint-instanced',
|
|
284
319
|
);
|
|
285
320
|
export const GLASS_TINT_CUTOUT_VERT = resolveConditionals(
|
|
286
321
|
DEPTH_VERT_SOURCE,
|
|
287
|
-
{ SKINNED: false, INSTANCED: false, CUTOUT: true, GLASS: true },
|
|
322
|
+
{ SKINNED: false, INSTANCED: false, CUTOUT: true, GLASS: true, ANIMATED: false },
|
|
288
323
|
'glass-tint-cutout',
|
|
289
324
|
);
|
|
290
325
|
export const GLASS_TINT_INSTANCED_CUTOUT_VERT = resolveConditionals(
|
|
291
326
|
DEPTH_VERT_SOURCE,
|
|
292
|
-
{ SKINNED: false, INSTANCED: true, CUTOUT: true, GLASS: true },
|
|
327
|
+
{ SKINNED: false, INSTANCED: true, CUTOUT: true, GLASS: true, ANIMATED: false },
|
|
293
328
|
'glass-tint-instanced-cutout',
|
|
294
329
|
);
|
|
295
330
|
|