@driftengine/core 4.10.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 +71 -0
- package/README.md +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.js +1 -1
- package/dist/render/backend/webgl2/renderer.d.ts +99 -2
- package/dist/render/backend/webgl2/renderer.js +361 -42
- package/dist/render/backend/webgpu/buffers.d.ts +5 -0
- package/dist/render/backend/webgpu/buffers.js +98 -48
- 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/drawCommand.d.ts +2 -0
- package/dist/render/backend/webgpu/drawCommand.js +1 -0
- package/dist/render/backend/webgpu/flatPass.d.ts +1 -1
- package/dist/render/backend/webgpu/flatPass.js +2 -1
- package/dist/render/backend/webgpu/gpuClothSet.d.ts +80 -0
- package/dist/render/backend/webgpu/gpuClothSet.js +462 -0
- package/dist/render/backend/webgpu/latePass.js +1 -0
- package/dist/render/backend/webgpu/motionPass.js +15 -6
- package/dist/render/backend/webgpu/pipelineCache.d.ts +22 -1
- package/dist/render/backend/webgpu/pipelineCache.js +39 -1
- package/dist/render/backend/webgpu/postPass.d.ts +1 -1
- package/dist/render/backend/webgpu/renderer.d.ts +48 -0
- package/dist/render/backend/webgpu/renderer.js +207 -27
- 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/staticBundles.js +2 -1
- package/dist/render/backend/webgpu/vertexFormats.d.ts +22 -0
- package/dist/render/backend/webgpu/vertexFormats.js +97 -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/lightMatrix.d.ts +11 -0
- package/dist/render/lightMatrix.js +14 -0
- package/dist/render/mesh.d.ts +9 -0
- package/dist/render/mesh.js +38 -14
- 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/shader.d.ts +15 -0
- package/dist/render/shader.js +41 -0
- 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 +15 -0
- package/dist/render/shaders/flat/index.js +15 -2
- 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 +43 -16
- package/dist/render/shaders/flat/mapReads.d.ts +10 -0
- package/dist/render/shaders/flat/mapReads.js +38 -0
- 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 +41 -19
- package/dist/render/shaders/flat/preamble.js +23 -5
- package/dist/render/shaders/flat/worldUv.d.ts +22 -0
- package/dist/render/shaders/flat/worldUv.js +113 -0
- package/dist/render/shaders/generated/flat.wgsl.d.ts +768 -368
- package/dist/render/shaders/generated/flat.wgsl.js +791 -391
- 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/tangentFrame.d.ts +1 -1
- package/dist/render/shaders/tangentFrame.js +16 -3
- package/dist/render/skinnedClothRun.d.ts +28 -0
- package/dist/render/skinnedClothRun.js +103 -35
- 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 +30 -0
- package/dist/render/vertexPacking.d.ts +48 -0
- package/dist/render/vertexPacking.js +68 -0
- package/package.json +6 -6
- package/src/index.ts +4 -2
- package/src/render/backend/webgl2/renderer.ts +408 -55
- package/src/render/backend/webgpu/buffers.ts +153 -54
- 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/drawCommand.ts +3 -0
- package/src/render/backend/webgpu/flatPass.ts +26 -28
- package/src/render/backend/webgpu/gpuClothSet.ts +564 -0
- package/src/render/backend/webgpu/latePass.ts +1 -0
- package/src/render/backend/webgpu/motionPass.ts +18 -7
- package/src/render/backend/webgpu/pipelineCache.ts +46 -7
- package/src/render/backend/webgpu/renderer.ts +274 -48
- package/src/render/backend/webgpu/shaders/clothSolve.wgsl.ts +121 -47
- package/src/render/backend/webgpu/staticBundles.ts +2 -1
- package/src/render/backend/webgpu/vertexFormats.ts +113 -0
- package/src/render/globalMediumPass.ts +7 -0
- package/src/render/indexWidth.ts +27 -0
- package/src/render/lightMatrix.ts +15 -0
- package/src/render/mesh.ts +66 -14
- package/src/render/renderQuality.ts +38 -0
- package/src/render/rendererHarness.ts +15 -0
- package/src/render/shader.ts +59 -0
- 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 +30 -2
- package/src/render/shaders/flat/layered.ts +115 -0
- package/src/render/shaders/flat/main.ts +43 -16
- package/src/render/shaders/flat/mapReads.ts +38 -0
- 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 +41 -19
- package/src/render/shaders/flat/preamble.ts +23 -5
- package/src/render/shaders/flat/worldUv.ts +113 -0
- package/src/render/shaders/generated/flat.wgsl.ts +791 -391
- 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/tangentFrame.ts +16 -3
- package/src/render/skinnedClothRun.ts +138 -38
- 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 +30 -0
- 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
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { vertexPackingOf } from '../../vertexPacking.ts';
|
|
2
|
+
import { markPacking, markPackingOfKey, packingKey } from './vertexFormats.ts';
|
|
1
3
|
import { mat4 } from 'gl-matrix';
|
|
2
4
|
import type { ProbeBakeOptions } from '../../reflectionProbe.ts';
|
|
3
5
|
import { probeFaceRange } from '../../reflectionProbe.ts';
|
|
@@ -194,6 +196,10 @@ import {
|
|
|
194
196
|
packSurfaceOverlay,
|
|
195
197
|
type SurfaceOverlay,
|
|
196
198
|
} from '../../surfaceOverlay.ts';
|
|
199
|
+
import { PROJECTION_FLOATS, packSurfaceProjection } from '../../surfaceProjection.ts';
|
|
200
|
+
import { orthographicDepthSpan } from '../../lightMatrix.ts';
|
|
201
|
+
import { LAYER_FLOATS, packSurfaceLayers } from '../../surfaceLayers.ts';
|
|
202
|
+
import type { SurfaceLayers } from '../../surfaceLayers.ts';
|
|
197
203
|
import {
|
|
198
204
|
frameReflectionsRefused,
|
|
199
205
|
resolveFrameReflections,
|
|
@@ -1530,7 +1536,21 @@ export class WebGPURenderer implements RendererApi {
|
|
|
1530
1536
|
* flight at the time, so a consumer that builds more meshes later can wait again.
|
|
1531
1537
|
*/
|
|
1532
1538
|
async ready(): Promise<void> {
|
|
1533
|
-
await Promise.all(this.
|
|
1539
|
+
await Promise.all(this.pipelineCaches().map((cache) => cache.ready()));
|
|
1540
|
+
}
|
|
1541
|
+
|
|
1542
|
+
/** Every distinct cache a lit draw reaches: the frame's, the canvas's, the late pass's, skin's. */
|
|
1543
|
+
private pipelineCaches(): PipelineCache[] {
|
|
1544
|
+
const caches = [...this.pipelineTargets];
|
|
1545
|
+
for (const cache of [this.latePipelines, this.skinPipelines]) {
|
|
1546
|
+
if (cache !== null && !caches.includes(cache)) caches.push(cache);
|
|
1547
|
+
}
|
|
1548
|
+
return caches;
|
|
1549
|
+
}
|
|
1550
|
+
|
|
1551
|
+
/** Whether a lit draw whose pipeline is not built is left out while it compiles. */
|
|
1552
|
+
private skipCompiling(skips: boolean): void {
|
|
1553
|
+
for (const cache of this.pipelineCaches()) cache.skipsCompiling = skips;
|
|
1534
1554
|
}
|
|
1535
1555
|
|
|
1536
1556
|
private presentedFrameCount = 0;
|
|
@@ -2927,6 +2947,7 @@ export class WebGPURenderer implements RendererApi {
|
|
|
2927
2947
|
}
|
|
2928
2948
|
filmCommand.vertexCount = geometry.vertexBuffers.length;
|
|
2929
2949
|
filmCommand.indexBuffer = geometry.indexBuffer;
|
|
2950
|
+
filmCommand.indexFormat = geometry.indexFormat;
|
|
2930
2951
|
filmCommand.indexed = true;
|
|
2931
2952
|
filmCommand.count = geometry.indexCount;
|
|
2932
2953
|
} else {
|
|
@@ -2937,7 +2958,7 @@ export class WebGPURenderer implements RendererApi {
|
|
|
2937
2958
|
for (let index = 0; index < geometry.vertexBuffers.length; index++) {
|
|
2938
2959
|
pass.setVertexBuffer(index, geometry.vertexBuffers[index] as GPUBuffer);
|
|
2939
2960
|
}
|
|
2940
|
-
pass.setIndexBuffer(geometry.indexBuffer,
|
|
2961
|
+
pass.setIndexBuffer(geometry.indexBuffer, geometry.indexFormat);
|
|
2941
2962
|
pass.drawIndexed(geometry.indexCount);
|
|
2942
2963
|
}
|
|
2943
2964
|
}
|
|
@@ -2974,6 +2995,11 @@ export class WebGPURenderer implements RendererApi {
|
|
|
2974
2995
|
private modelMap: GpuSurfaceTexture | null = null;
|
|
2975
2996
|
/** The material's shading model, which picks the lit pipeline: null the standard. */
|
|
2976
2997
|
private materialModel: SurfaceModel | null = null;
|
|
2998
|
+
/** `uWorldUv`, the material's projection packed by `packSurfaceProjection`. */
|
|
2999
|
+
private readonly projection = new Float32Array(PROJECTION_FLOATS);
|
|
3000
|
+
/** `uLayers`, the material's layers packed by `packSurfaceLayers`. */
|
|
3001
|
+
private readonly layerFloats = new Float32Array(LAYER_FLOATS);
|
|
3002
|
+
private warnedLayersModelMap = false;
|
|
2977
3003
|
/** Its numbers, `uModelParams`, packed by `packModel`. */
|
|
2978
3004
|
private readonly modelParams = new Float32Array(MODEL_PARAM_FLOATS);
|
|
2979
3005
|
/**
|
|
@@ -3448,7 +3474,10 @@ export class WebGPURenderer implements RendererApi {
|
|
|
3448
3474
|
const normal = (material?.normal ?? null) as GpuSurfaceTexture | null;
|
|
3449
3475
|
const orm = (material?.orm ?? null) as GpuSurfaceTexture | null;
|
|
3450
3476
|
const emissiveMap = (material?.emissive ?? null) as GpuSurfaceTexture | null;
|
|
3451
|
-
const
|
|
3477
|
+
const ownModelMap = (material?.modelMap ?? null) as GpuSurfaceTexture | null;
|
|
3478
|
+
/* A layered material's mask goes where a model's map would: see `SurfaceMaterial.layers`. */
|
|
3479
|
+
const layers = this.layersOf(material);
|
|
3480
|
+
const modelMap = ownModelMap ?? ((layers?.mask ?? null) as GpuSurfaceTexture | null);
|
|
3452
3481
|
this.materialModel = material?.model ?? null;
|
|
3453
3482
|
const reflectivity = material?.reflectivity;
|
|
3454
3483
|
const environmentGain = material?.environmentGain;
|
|
@@ -3459,7 +3488,7 @@ export class WebGPURenderer implements RendererApi {
|
|
|
3459
3488
|
this.writeEnvironmentDials();
|
|
3460
3489
|
/* What the blur spreads this skin by: the last material to name a profile says. */
|
|
3461
3490
|
const model = material?.model;
|
|
3462
|
-
warnUnpagedLightmap(model,
|
|
3491
|
+
warnUnpagedLightmap(model, ownModelMap);
|
|
3463
3492
|
if (model?.kind === 'skin' && this.skinScatter !== null) {
|
|
3464
3493
|
this.skinScatter.setProfile(
|
|
3465
3494
|
model.profile,
|
|
@@ -3518,12 +3547,23 @@ export class WebGPURenderer implements RendererApi {
|
|
|
3518
3547
|
/* The model's numbers and whether its map is bound. See `packModel`. */
|
|
3519
3548
|
packModel(
|
|
3520
3549
|
material?.model ?? null,
|
|
3521
|
-
|
|
3550
|
+
ownModelMap !== null,
|
|
3522
3551
|
this.modelParams,
|
|
3523
3552
|
material?.physicalSpecular === true,
|
|
3524
3553
|
);
|
|
3525
3554
|
/* The first physical highlight asked for is when the lit pipelines start carrying one. */
|
|
3526
3555
|
if (material?.physicalSpecular === true) this.enableLit('PHYSICAL_SPECULAR');
|
|
3556
|
+
/* Maps placed by the world: the first material that asks is when lit pipelines carry it. */
|
|
3557
|
+
packSurfaceProjection(material?.projection, this.projection);
|
|
3558
|
+
f.set(this.projection, this.materialField('uWorldUv'));
|
|
3559
|
+
/* How much light from behind it lets through, in the glass tint's spare lane. */
|
|
3560
|
+
f[this.materialField('uGlassTint') + 3] =
|
|
3561
|
+
Math.min(Math.max(material?.diffuseTransmission ?? 0, 0), 1) || 0;
|
|
3562
|
+
if ((this.projection[0] as number) > 0) this.enableLit('WORLD_UVS');
|
|
3563
|
+
/* And its layers, the first time a material blends any: layered.ts. */
|
|
3564
|
+
packSurfaceLayers(layers, this.layerFloats);
|
|
3565
|
+
f.set(this.layerFloats, this.materialField('uLayers'));
|
|
3566
|
+
if (layers !== null) this.enableLit('LAYERED');
|
|
3527
3567
|
f.set(this.modelParams, this.materialField('uModelParams'));
|
|
3528
3568
|
});
|
|
3529
3569
|
/*
|
|
@@ -3731,6 +3771,14 @@ export class WebGPURenderer implements RendererApi {
|
|
|
3731
3771
|
this.materials.dirty();
|
|
3732
3772
|
}
|
|
3733
3773
|
|
|
3774
|
+
/** Whether the draws that follow spend their own opacity on that screen door. See `renderer.ts`. */
|
|
3775
|
+
setDitherOpacity(on: boolean): void {
|
|
3776
|
+
if (this.surface.lost) return;
|
|
3777
|
+
/* The third lane of `uWriteMode`, beside the fade. */
|
|
3778
|
+
this.perFrameFloats[this.materialField('uWriteMode') + 2] = on ? 1 : 0;
|
|
3779
|
+
this.materials.dirty();
|
|
3780
|
+
}
|
|
3781
|
+
|
|
3734
3782
|
/**
|
|
3735
3783
|
* How strong the microscopic relief on the surfaces drawn next is, and how coarse.
|
|
3736
3784
|
*
|
|
@@ -5228,6 +5276,11 @@ export class WebGPURenderer implements RendererApi {
|
|
|
5228
5276
|
at('uLightViewProj'),
|
|
5229
5277
|
env === undefined ? NO_LIGHT_MATRIX : (env.lightViewProj as Float32Array),
|
|
5230
5278
|
);
|
|
5279
|
+
ring.writeFloats(
|
|
5280
|
+
fragmentSlot,
|
|
5281
|
+
at('uMovingLightViewProj'),
|
|
5282
|
+
env === undefined ? NO_LIGHT_MATRIX : (this.movingLightFor(env) as Float32Array),
|
|
5283
|
+
);
|
|
5231
5284
|
ring.writeFloat(fragmentSlot, at('uShadowMapSize'), this.quality.directionalShadowMapSize);
|
|
5232
5285
|
/* Sampled only where a pass filled it — see `peelFilled` for why existing is not enough. */
|
|
5233
5286
|
ring.writeInt(fragmentSlot, at('uPeeledShadowEnabled'), this.peelFilled ? 1 : 0);
|
|
@@ -5267,6 +5320,7 @@ export class WebGPURenderer implements RendererApi {
|
|
|
5267
5320
|
}
|
|
5268
5321
|
volumeCommand.vertexCount = mesh.vertexBuffers.length;
|
|
5269
5322
|
volumeCommand.indexBuffer = mesh.indexBuffer;
|
|
5323
|
+
volumeCommand.indexFormat = mesh.indexFormat;
|
|
5270
5324
|
volumeCommand.indexed = true;
|
|
5271
5325
|
volumeCommand.count = mesh.indexCount;
|
|
5272
5326
|
} else {
|
|
@@ -5275,7 +5329,7 @@ export class WebGPURenderer implements RendererApi {
|
|
|
5275
5329
|
for (let index = 0; index < mesh.vertexBuffers.length; index++) {
|
|
5276
5330
|
pass.setVertexBuffer(index, mesh.vertexBuffers[index] as GPUBuffer);
|
|
5277
5331
|
}
|
|
5278
|
-
pass.setIndexBuffer(mesh.indexBuffer,
|
|
5332
|
+
pass.setIndexBuffer(mesh.indexBuffer, mesh.indexFormat);
|
|
5279
5333
|
pass.drawIndexed(mesh.indexCount);
|
|
5280
5334
|
}
|
|
5281
5335
|
}
|
|
@@ -6116,6 +6170,22 @@ export class WebGPURenderer implements RendererApi {
|
|
|
6116
6170
|
* the texel-for-texel comparison that settled it.
|
|
6117
6171
|
*/
|
|
6118
6172
|
private readonly correctedLightViewProj = new Float32Array(16);
|
|
6173
|
+
/**
|
|
6174
|
+
* What a receiver projects through to read the sun's static layers: the environment's
|
|
6175
|
+
* `lightViewProj`, taken at `bindMeshPass` as WebGL2 takes it there.
|
|
6176
|
+
*
|
|
6177
|
+
* **It was the last shadow pass's matrix**, which is the environment's wherever both layers are
|
|
6178
|
+
* drawn with one and the moving layer's wherever they are not: the static layer was then read
|
|
6179
|
+
* through the moving layer's tight square, and a distant pillar lost its shadow on WebGPU and kept
|
|
6180
|
+
* it on WebGL2, measured on demo/dev/sunLayers.html?moving=tight.
|
|
6181
|
+
*/
|
|
6182
|
+
private readonly receiverLightViewProj = new Float32Array(16);
|
|
6183
|
+
/**
|
|
6184
|
+
* The matrix the sun's dynamic shadow pass was last drawn with, uncorrected as the lit stage
|
|
6185
|
+
* projects with, and whether one has been. See `movingLightFor`.
|
|
6186
|
+
*/
|
|
6187
|
+
private readonly movingLightViewProj = new Float32Array(16);
|
|
6188
|
+
private movingLightKnown = false;
|
|
6119
6189
|
/**
|
|
6120
6190
|
* The same matrix *uncorrected*, which is what the flat shader must project with.
|
|
6121
6191
|
*
|
|
@@ -6246,6 +6316,48 @@ export class WebGPURenderer implements RendererApi {
|
|
|
6246
6316
|
this.enableLit('GLASS_SHADOWS');
|
|
6247
6317
|
}
|
|
6248
6318
|
|
|
6319
|
+
/**
|
|
6320
|
+
* A material's layers where they can be drawn: none asked, or a model's map in the mask's place,
|
|
6321
|
+
* said once, leave one layer.
|
|
6322
|
+
*/
|
|
6323
|
+
private layersOf(
|
|
6324
|
+
material: SurfaceMaterial<GpuSurfaceTexture> | null,
|
|
6325
|
+
): SurfaceLayers<GpuSurfaceTexture> | null {
|
|
6326
|
+
const layers = material?.layers ?? null;
|
|
6327
|
+
if (layers === null || layers.repeats.length === 0) return null;
|
|
6328
|
+
if ((material?.modelMap ?? null) === null) return layers;
|
|
6329
|
+
if (!this.warnedLayersModelMap) {
|
|
6330
|
+
this.warnedLayersModelMap = true;
|
|
6331
|
+
console.warn(
|
|
6332
|
+
"WebGPU: a material's layers are drawn as one: its mask is read where a model's map goes, " +
|
|
6333
|
+
'and this material carries a `modelMap` too.',
|
|
6334
|
+
);
|
|
6335
|
+
}
|
|
6336
|
+
return null;
|
|
6337
|
+
}
|
|
6338
|
+
|
|
6339
|
+
/**
|
|
6340
|
+
* What the sun's moving layer is read through: the matrix its shadow pass was last drawn with,
|
|
6341
|
+
* where the lit pipelines carry one (`MOVING_SUN`); the environment's otherwise, which every caller
|
|
6342
|
+
* drawing both layers with one matrix hands it anyway.
|
|
6343
|
+
*/
|
|
6344
|
+
private movingLightFor(env: Environment): ReadonlyMat4 {
|
|
6345
|
+
return this.movingLightKnown && this.pipelines.litSwitches.MOVING_SUN
|
|
6346
|
+
? this.movingLightViewProj
|
|
6347
|
+
: env.lightViewProj;
|
|
6348
|
+
}
|
|
6349
|
+
|
|
6350
|
+
/** The moving layer's own matrix on, the first time a frame draws that layer with one. */
|
|
6351
|
+
private enableMovingSun(env: Environment): void {
|
|
6352
|
+
if (this.pipelines.litSwitches.MOVING_SUN || !this.movingLightKnown) return;
|
|
6353
|
+
for (let k = 0; k < 16; k++) {
|
|
6354
|
+
if (this.movingLightViewProj[k] !== env.lightViewProj[k]) {
|
|
6355
|
+
this.enableLit('MOVING_SUN');
|
|
6356
|
+
return;
|
|
6357
|
+
}
|
|
6358
|
+
}
|
|
6359
|
+
}
|
|
6360
|
+
|
|
6249
6361
|
/** One of the lit stage's switches on, in every cache a lit pipeline can come from. */
|
|
6250
6362
|
private enableLit(feature: LitSwitch): void {
|
|
6251
6363
|
if (this.pipelines.litSwitches[feature]) return;
|
|
@@ -6311,7 +6423,7 @@ export class WebGPURenderer implements RendererApi {
|
|
|
6311
6423
|
for (let index = 0; index < geometry.vertexBuffers.length; index++) {
|
|
6312
6424
|
pass.setVertexBuffer(index, geometry.vertexBuffers[index] as GPUBuffer);
|
|
6313
6425
|
}
|
|
6314
|
-
pass.setIndexBuffer(geometry.indexBuffer,
|
|
6426
|
+
pass.setIndexBuffer(geometry.indexBuffer, geometry.indexFormat);
|
|
6315
6427
|
pass.drawIndexed(geometry.indexCount);
|
|
6316
6428
|
},
|
|
6317
6429
|
/**
|
|
@@ -6401,7 +6513,7 @@ export class WebGPURenderer implements RendererApi {
|
|
|
6401
6513
|
pass.setVertexBuffer(index, geometry.vertexBuffers[index] as GPUBuffer);
|
|
6402
6514
|
}
|
|
6403
6515
|
pass.setVertexBuffer(index, gpuBatch.buffer);
|
|
6404
|
-
pass.setIndexBuffer(geometry.indexBuffer,
|
|
6516
|
+
pass.setIndexBuffer(geometry.indexBuffer, geometry.indexFormat);
|
|
6405
6517
|
pass.drawIndexed(geometry.indexCount, count);
|
|
6406
6518
|
},
|
|
6407
6519
|
skinnedMesh: (mesh, model, palette, material, cloth) => {
|
|
@@ -6463,7 +6575,7 @@ export class WebGPURenderer implements RendererApi {
|
|
|
6463
6575
|
for (let index = 0; index < geometry.vertexBuffers.length; index++) {
|
|
6464
6576
|
pass.setVertexBuffer(index, geometry.vertexBuffers[index] as GPUBuffer);
|
|
6465
6577
|
}
|
|
6466
|
-
pass.setIndexBuffer(geometry.indexBuffer,
|
|
6578
|
+
pass.setIndexBuffer(geometry.indexBuffer, geometry.indexFormat);
|
|
6467
6579
|
pass.drawIndexed(geometry.indexCount);
|
|
6468
6580
|
},
|
|
6469
6581
|
/**
|
|
@@ -6886,6 +6998,8 @@ export class WebGPURenderer implements RendererApi {
|
|
|
6886
6998
|
this.overlayPipelines === this.pipelines
|
|
6887
6999
|
? [this.pipelines]
|
|
6888
7000
|
: [this.pipelines, this.overlayPipelines];
|
|
7001
|
+
/* A lit draw first needed inside a frame waits for its compile or is left out while it runs. */
|
|
7002
|
+
this.skipCompiling(quality.pipelineCompile === 'skip');
|
|
6889
7003
|
this.variant = flatVariant({
|
|
6890
7004
|
directionalShadows: quality.directionalShadows,
|
|
6891
7005
|
/* No `bakeReflectionProbe` here; see the field. */
|
|
@@ -8138,6 +8252,8 @@ export class WebGPURenderer implements RendererApi {
|
|
|
8138
8252
|
present['layers'] = key.includes(':layers');
|
|
8139
8253
|
/* Nor is a dynamic mesh's split, which moves positions and normals into buffers of their own. */
|
|
8140
8254
|
present['dynamic'] = key.includes(':dynamic');
|
|
8255
|
+
/* Nor how each attribute travels, which moves every field after a packed one. */
|
|
8256
|
+
markPackingOfKey(present, key);
|
|
8141
8257
|
return present;
|
|
8142
8258
|
}
|
|
8143
8259
|
|
|
@@ -8447,6 +8563,13 @@ export class WebGPURenderer implements RendererApi {
|
|
|
8447
8563
|
present['dynamic'] = true;
|
|
8448
8564
|
key += ':dynamic';
|
|
8449
8565
|
}
|
|
8566
|
+
/*
|
|
8567
|
+
* And how each attribute travels (`vertexPacking.ts`): a field read as sixteen bits rather than
|
|
8568
|
+
* thirty-two, or not interleaved at all, moves every field after it, so the key says so.
|
|
8569
|
+
*/
|
|
8570
|
+
const packing = vertexPackingOf(data, dynamic);
|
|
8571
|
+
markPacking(present, packing);
|
|
8572
|
+
key += packingKey(packing);
|
|
8450
8573
|
const fullKey = `${this.variant}|${key}`;
|
|
8451
8574
|
/*
|
|
8452
8575
|
* **For every target this mesh can land on, which is two when the overlay is its own.**
|
|
@@ -8691,6 +8814,8 @@ export class WebGPURenderer implements RendererApi {
|
|
|
8691
8814
|
*/
|
|
8692
8815
|
bindMeshPass(camera: Camera, env: Environment): void {
|
|
8693
8816
|
if (this.surface.lost) return;
|
|
8817
|
+
/* The matrix every receiver projects through: the environment's, as WebGL2's. See the field. */
|
|
8818
|
+
this.receiverLightViewProj.set(env.lightViewProj as Float32Array);
|
|
8694
8819
|
|
|
8695
8820
|
/* Rectangles past the fixed arm's are the froxel table's, and without it nobody shades them. */
|
|
8696
8821
|
if (
|
|
@@ -8809,6 +8934,12 @@ export class WebGPURenderer implements RendererApi {
|
|
|
8809
8934
|
this.surfaceFog = FOG_RECEDE;
|
|
8810
8935
|
/* Every material switch off — albedo, ORM map, emissive map, two-sided — as WebGL2 resets them. */
|
|
8811
8936
|
i.fill(0, at('uMaterialFlags'), at('uMaterialFlags') + 4);
|
|
8937
|
+
/* And no projection: maps follow the mesh's coordinates until a material asks otherwise. */
|
|
8938
|
+
f.fill(0, at('uWorldUv'), at('uWorldUv') + 4);
|
|
8939
|
+
/* Nor light through from behind. See `SurfaceMaterial.diffuseTransmission`. */
|
|
8940
|
+
f[at('uGlassTint') + 3] = 0;
|
|
8941
|
+
/* Nor layers: one layer until a material asks for more. */
|
|
8942
|
+
f.fill(0, at('uLayers'), at('uLayers') + LAYER_FLOATS);
|
|
8812
8943
|
f[at('uCutout')] = 0;
|
|
8813
8944
|
f[at('uCutout') + 1] = 0;
|
|
8814
8945
|
this.cutoutResolveStaged = 'hard';
|
|
@@ -8891,6 +9022,7 @@ export class WebGPURenderer implements RendererApi {
|
|
|
8891
9022
|
/* No weighting and no dither until a pass or a crossfade asks. See `setDitherFade`. */
|
|
8892
9023
|
f[at('uWriteMode')] = 0;
|
|
8893
9024
|
f[at('uWriteMode') + 1] = 0;
|
|
9025
|
+
f[at('uWriteMode') + 2] = 0;
|
|
8894
9026
|
/* 1, not 0: a multiplier's identity is one. See `setEnvironmentGain`. */
|
|
8895
9027
|
f[at('uEnvironmentDials') + 2] = 1;
|
|
8896
9028
|
/* No overlay until a draw sets one. See `setSurfaceOverlay`. */
|
|
@@ -9184,6 +9316,11 @@ export class WebGPURenderer implements RendererApi {
|
|
|
9184
9316
|
f[at('uShadowStrength')] = env.shadowStrength;
|
|
9185
9317
|
f[at('uShadowMapSize')] = this.quality.directionalShadowMapSize;
|
|
9186
9318
|
f[at('uShadowDepthSpan')] = env.shadowDepthSpan;
|
|
9319
|
+
/* The moving layer's own matrix and span, where the lit stage reads one: `movingLightFor`. */
|
|
9320
|
+
this.enableMovingSun(env);
|
|
9321
|
+
const moving = this.movingLightFor(env);
|
|
9322
|
+
f.set(moving as Float32Array, at('uMovingLightViewProj'));
|
|
9323
|
+
f[at('uMovingShadowDepthSpan')] = orthographicDepthSpan(moving);
|
|
9187
9324
|
f[at('uShadowMaxDistance')] = this.quality.directionalShadowMaxDistance;
|
|
9188
9325
|
f[at('uShadowMaxSlope')] = this.quality.directionalShadowMaxSlope;
|
|
9189
9326
|
/* Sampled only where a pass filled it — see `peelFilled` for why existing is not enough. */
|
|
@@ -9386,7 +9523,7 @@ export class WebGPURenderer implements RendererApi {
|
|
|
9386
9523
|
/** A view block: the camera, the light's matrix and the frame's wind, into `ring` at `slot`. */
|
|
9387
9524
|
private writeView(ring: UniformRing, slot: number, viewProj: Float32Array): void {
|
|
9388
9525
|
ring.writeFloats(slot, FLAT_VIEW_FIELDS.uViewProj.offset, viewProj);
|
|
9389
|
-
ring.writeFloats(slot, FLAT_VIEW_FIELDS.uLightViewProj.offset, this.
|
|
9526
|
+
ring.writeFloats(slot, FLAT_VIEW_FIELDS.uLightViewProj.offset, this.receiverLightViewProj);
|
|
9390
9527
|
/* The scene's clock, which a bone animation's instances read their moment from. */
|
|
9391
9528
|
ring.writeFloat(slot, FLAT_VIEW_FIELDS.uSceneTime.offset, this.animationTime);
|
|
9392
9529
|
const d = this.frameWind;
|
|
@@ -9793,8 +9930,8 @@ export class WebGPURenderer implements RendererApi {
|
|
|
9793
9930
|
* thrown error in the middle of one.
|
|
9794
9931
|
*/
|
|
9795
9932
|
const pipelines = blend ? this.blendedPipelines(lands) : this.targetPipelines();
|
|
9796
|
-
let pipeline = pipelines.peek(key);
|
|
9797
|
-
if (pipeline ===
|
|
9933
|
+
let pipeline: GPURenderPipeline | null = pipelines.peek(key) ?? null;
|
|
9934
|
+
if (pipeline === null) {
|
|
9798
9935
|
const present = this.meshPresent.get(base);
|
|
9799
9936
|
if (present === undefined) {
|
|
9800
9937
|
throw new Error(`WebGPU: no pipeline for ${key}; createMesh builds it`);
|
|
@@ -9821,6 +9958,14 @@ export class WebGPURenderer implements RendererApi {
|
|
|
9821
9958
|
splits ? 'scene' : 'whole',
|
|
9822
9959
|
);
|
|
9823
9960
|
}
|
|
9961
|
+
/* A split skin draws its three halves or none of them. */
|
|
9962
|
+
if (
|
|
9963
|
+
pipeline !== null &&
|
|
9964
|
+
splits &&
|
|
9965
|
+
!this.skinHalvesReady(key, base, skinned, morphed, layer, eight, clothed)
|
|
9966
|
+
) {
|
|
9967
|
+
pipeline = null;
|
|
9968
|
+
}
|
|
9824
9969
|
|
|
9825
9970
|
/*
|
|
9826
9971
|
* Guards the draw call only, not the restore below.
|
|
@@ -9838,8 +9983,9 @@ export class WebGPURenderer implements RendererApi {
|
|
|
9838
9983
|
* close to the 256-slot budget before the gateway, the play controls, the waveform, the
|
|
9839
9984
|
* label handles and the sparkles are even counted.
|
|
9840
9985
|
*/
|
|
9841
|
-
|
|
9842
|
-
|
|
9986
|
+
/* A draw whose pipeline is still compiling is left out, its state restored all the same. */
|
|
9987
|
+
const material = pipeline === null ? null : this.materialSlotForDraw();
|
|
9988
|
+
if (pipeline !== null && material !== null) {
|
|
9843
9989
|
/*
|
|
9844
9990
|
* Record rather than issue. Every per-draw value is already in `slot` and `material` —
|
|
9845
9991
|
* the uniform rings are the state arena this design would otherwise have had to build —
|
|
@@ -9861,6 +10007,7 @@ export class WebGPURenderer implements RendererApi {
|
|
|
9861
10007
|
}
|
|
9862
10008
|
command.vertexCount = mesh.vertexBuffers.length;
|
|
9863
10009
|
command.indexBuffer = mesh.indexBuffer;
|
|
10010
|
+
command.indexFormat = mesh.indexFormat;
|
|
9864
10011
|
command.indexed = true;
|
|
9865
10012
|
command.count = mesh.indexCount;
|
|
9866
10013
|
} else {
|
|
@@ -9876,7 +10023,7 @@ export class WebGPURenderer implements RendererApi {
|
|
|
9876
10023
|
for (let index = 0; index < mesh.vertexBuffers.length; index++) {
|
|
9877
10024
|
pass.setVertexBuffer(index, mesh.vertexBuffers[index] as GPUBuffer);
|
|
9878
10025
|
}
|
|
9879
|
-
pass.setIndexBuffer(mesh.indexBuffer,
|
|
10026
|
+
pass.setIndexBuffer(mesh.indexBuffer, mesh.indexFormat);
|
|
9880
10027
|
pass.drawIndexed(mesh.indexCount);
|
|
9881
10028
|
}
|
|
9882
10029
|
if (splits) {
|
|
@@ -10355,8 +10502,8 @@ export class WebGPURenderer implements RendererApi {
|
|
|
10355
10502
|
`${modelKind === null ? '' : `|m:${modelKind}`}`;
|
|
10356
10503
|
|
|
10357
10504
|
const pipelines = blend ? this.blendedPipelines(lands) : this.targetPipelines();
|
|
10358
|
-
let pipeline = pipelines.peek(key);
|
|
10359
|
-
if (pipeline ===
|
|
10505
|
+
let pipeline: GPURenderPipeline | null = pipelines.peek(key) ?? null;
|
|
10506
|
+
if (pipeline === null) {
|
|
10360
10507
|
const present = this.meshPresent.get(base);
|
|
10361
10508
|
if (present === undefined) {
|
|
10362
10509
|
throw new Error(`WebGPU: no mesh attributes recorded for ${base}; createMesh records them`);
|
|
@@ -10386,8 +10533,9 @@ export class WebGPURenderer implements RendererApi {
|
|
|
10386
10533
|
);
|
|
10387
10534
|
}
|
|
10388
10535
|
|
|
10389
|
-
|
|
10390
|
-
|
|
10536
|
+
/* A batch whose pipeline is still compiling is left out, as a mesh is. */
|
|
10537
|
+
const material = pipeline === null ? null : this.materialSlotForDraw();
|
|
10538
|
+
if (pipeline !== null && material !== null) {
|
|
10391
10539
|
const command = blend
|
|
10392
10540
|
? this.recordBlended(0, lands)
|
|
10393
10541
|
: this.recordDraw(0, this.currentTarget());
|
|
@@ -10409,6 +10557,7 @@ export class WebGPURenderer implements RendererApi {
|
|
|
10409
10557
|
command.vertexBuffers[index] = instanceBuffer;
|
|
10410
10558
|
command.vertexCount = mesh.vertexBuffers.length + 1;
|
|
10411
10559
|
command.indexBuffer = mesh.indexBuffer;
|
|
10560
|
+
command.indexFormat = mesh.indexFormat;
|
|
10412
10561
|
command.indexed = true;
|
|
10413
10562
|
command.count = mesh.indexCount;
|
|
10414
10563
|
command.instances = count;
|
|
@@ -10429,7 +10578,7 @@ export class WebGPURenderer implements RendererApi {
|
|
|
10429
10578
|
pass.setVertexBuffer(index, mesh.vertexBuffers[index] as GPUBuffer);
|
|
10430
10579
|
}
|
|
10431
10580
|
pass.setVertexBuffer(index, instanceBuffer);
|
|
10432
|
-
pass.setIndexBuffer(mesh.indexBuffer,
|
|
10581
|
+
pass.setIndexBuffer(mesh.indexBuffer, mesh.indexFormat);
|
|
10433
10582
|
if (cut === null) pass.drawIndexed(mesh.indexCount, count);
|
|
10434
10583
|
else pass.drawIndexedIndirect(cut.args, 0);
|
|
10435
10584
|
}
|
|
@@ -10664,6 +10813,11 @@ export class WebGPURenderer implements RendererApi {
|
|
|
10664
10813
|
if (view === null) return false;
|
|
10665
10814
|
|
|
10666
10815
|
this.lightViewProj.set(lightViewProj as Float32Array);
|
|
10816
|
+
/* The moving layer is read through the matrix it is drawn with: see `movingLightFor`. */
|
|
10817
|
+
if (dynamic) {
|
|
10818
|
+
this.movingLightViewProj.set(lightViewProj as Float32Array);
|
|
10819
|
+
this.movingLightKnown = true;
|
|
10820
|
+
}
|
|
10667
10821
|
this.reopenViews();
|
|
10668
10822
|
mat4.multiply(this.correctedLightViewProj, SHADOW_CLIP_CORRECTION, lightViewProj);
|
|
10669
10823
|
this.shadowLayerIsPeel = peel;
|
|
@@ -10975,10 +11129,13 @@ export class WebGPURenderer implements RendererApi {
|
|
|
10975
11129
|
this.lateViewBlock.slot = list.viewOffset(0);
|
|
10976
11130
|
this.materials.dirty();
|
|
10977
11131
|
this.staticRecording = recording;
|
|
11132
|
+
/* A recorded list keeps what it recorded, so every draw of it waits for its pipeline. */
|
|
11133
|
+
this.skipCompiling(false);
|
|
10978
11134
|
try {
|
|
10979
11135
|
this.sceneCasterMaterial = undefined;
|
|
10980
11136
|
replayStaticDraws(list, this.sceneCasterSink);
|
|
10981
11137
|
} finally {
|
|
11138
|
+
this.skipCompiling(this.quality.pipelineCompile === 'skip');
|
|
10982
11139
|
this.staticRecording = null;
|
|
10983
11140
|
this.perDraw = perDraw;
|
|
10984
11141
|
this.passRing = passRing;
|
|
@@ -11285,7 +11442,7 @@ export class WebGPURenderer implements RendererApi {
|
|
|
11285
11442
|
for (let index = 0; index < geometry.vertexBuffers.length; index++) {
|
|
11286
11443
|
pass.setVertexBuffer(index, geometry.vertexBuffers[index] as GPUBuffer);
|
|
11287
11444
|
}
|
|
11288
|
-
pass.setIndexBuffer(geometry.indexBuffer,
|
|
11445
|
+
pass.setIndexBuffer(geometry.indexBuffer, geometry.indexFormat);
|
|
11289
11446
|
pass.drawIndexed(geometry.indexCount);
|
|
11290
11447
|
},
|
|
11291
11448
|
instanced: (batch, data, material, glass) => {
|
|
@@ -11330,7 +11487,7 @@ export class WebGPURenderer implements RendererApi {
|
|
|
11330
11487
|
pass.setVertexBuffer(index, geometry.vertexBuffers[index] as GPUBuffer);
|
|
11331
11488
|
}
|
|
11332
11489
|
pass.setVertexBuffer(index, gpuBatch.buffer);
|
|
11333
|
-
pass.setIndexBuffer(geometry.indexBuffer,
|
|
11490
|
+
pass.setIndexBuffer(geometry.indexBuffer, geometry.indexFormat);
|
|
11334
11491
|
pass.drawIndexed(geometry.indexCount, count);
|
|
11335
11492
|
},
|
|
11336
11493
|
skinnedMesh: (mesh, model, palette, _material, glass) => {
|
|
@@ -11366,7 +11523,7 @@ export class WebGPURenderer implements RendererApi {
|
|
|
11366
11523
|
for (let index = 0; index < geometry.vertexBuffers.length; index++) {
|
|
11367
11524
|
pass.setVertexBuffer(index, geometry.vertexBuffers[index] as GPUBuffer);
|
|
11368
11525
|
}
|
|
11369
|
-
pass.setIndexBuffer(geometry.indexBuffer,
|
|
11526
|
+
pass.setIndexBuffer(geometry.indexBuffer, geometry.indexFormat);
|
|
11370
11527
|
pass.drawIndexed(geometry.indexCount);
|
|
11371
11528
|
},
|
|
11372
11529
|
};
|
|
@@ -13865,6 +14022,10 @@ export class WebGPURenderer implements RendererApi {
|
|
|
13865
14022
|
/* Uncorrected, for the reason the shaft's own copy of this line carries: the shader does its
|
|
13866
14023
|
own `* 0.5 + 0.5`, and correcting the matrix as well doubles it. */
|
|
13867
14024
|
f.set(env?.lightViewProj ?? this.mediumIdentity, at('uLightViewProj'));
|
|
14025
|
+
f.set(
|
|
14026
|
+
(env === null ? this.mediumIdentity : this.movingLightFor(env)) as Float32Array,
|
|
14027
|
+
at('uMovingLightViewProj'),
|
|
14028
|
+
);
|
|
13868
14029
|
ints[at('uPeeledShadowEnabled')] = this.peelView === null || !this.peelFilled ? 0 : 1;
|
|
13869
14030
|
device.queue.writeBuffer(this.mediumUniforms, 0, this.mediumStaging);
|
|
13870
14031
|
|
|
@@ -14389,6 +14550,8 @@ export class WebGPURenderer implements RendererApi {
|
|
|
14389
14550
|
true,
|
|
14390
14551
|
animation !== null,
|
|
14391
14552
|
);
|
|
14553
|
+
/* Still compiling where draws skip: the probe stands in for this surface until it lands. */
|
|
14554
|
+
if (pipeline === null) return;
|
|
14392
14555
|
/* A static list's surface halves go into its own pool, beside its draws. */
|
|
14393
14556
|
const command =
|
|
14394
14557
|
this.staticRecording === null ? surface.take() : takeRecorded(this.staticRecording.surface);
|
|
@@ -14409,6 +14572,7 @@ export class WebGPURenderer implements RendererApi {
|
|
|
14409
14572
|
if (instanceBuffer !== null) command.vertexBuffers[index++] = instanceBuffer;
|
|
14410
14573
|
command.vertexCount = index;
|
|
14411
14574
|
command.indexBuffer = mesh.indexBuffer;
|
|
14575
|
+
command.indexFormat = mesh.indexFormat;
|
|
14412
14576
|
command.indexed = true;
|
|
14413
14577
|
command.count = mesh.indexCount;
|
|
14414
14578
|
command.instances = instances;
|
|
@@ -14421,6 +14585,78 @@ export class WebGPURenderer implements RendererApi {
|
|
|
14421
14585
|
* light alone and its colour alone into the blur's targets and test for the depth its frame half
|
|
14422
14586
|
* wrote.
|
|
14423
14587
|
*/
|
|
14588
|
+
/**
|
|
14589
|
+
* Whether a split skin draw's two kept halves have pipelines, starting the compile of either that
|
|
14590
|
+
* has not: a skin drawn without them would lose its diffuse light for the frames they take, so a
|
|
14591
|
+
* split skin draws all three halves or none. See `PipelineCache.lit`.
|
|
14592
|
+
*/
|
|
14593
|
+
private skinHalvesReady(
|
|
14594
|
+
frameKey: string,
|
|
14595
|
+
base: string,
|
|
14596
|
+
skinned: boolean,
|
|
14597
|
+
morphed: boolean,
|
|
14598
|
+
layer: number,
|
|
14599
|
+
eight: boolean,
|
|
14600
|
+
clothed: boolean,
|
|
14601
|
+
): boolean {
|
|
14602
|
+
let ready = true;
|
|
14603
|
+
for (const half of SKIN_KEPT_HALVES) {
|
|
14604
|
+
const pipeline = this.skinHalfPipeline(
|
|
14605
|
+
half,
|
|
14606
|
+
frameKey,
|
|
14607
|
+
base,
|
|
14608
|
+
skinned,
|
|
14609
|
+
morphed,
|
|
14610
|
+
layer,
|
|
14611
|
+
eight,
|
|
14612
|
+
clothed,
|
|
14613
|
+
);
|
|
14614
|
+
if (pipeline === null) ready = false;
|
|
14615
|
+
}
|
|
14616
|
+
return ready;
|
|
14617
|
+
}
|
|
14618
|
+
|
|
14619
|
+
/** One kept half's pipeline, or none where it is still compiling: see `PipelineCache.lit`. */
|
|
14620
|
+
private skinHalfPipeline(
|
|
14621
|
+
half: (typeof SKIN_KEPT_HALVES)[number],
|
|
14622
|
+
frameKey: string,
|
|
14623
|
+
base: string,
|
|
14624
|
+
skinned: boolean,
|
|
14625
|
+
morphed: boolean,
|
|
14626
|
+
layer: number,
|
|
14627
|
+
eight: boolean,
|
|
14628
|
+
clothed: boolean,
|
|
14629
|
+
): GPURenderPipeline | null {
|
|
14630
|
+
const pipelines = this.skinPipelines;
|
|
14631
|
+
const present = this.meshPresent.get(base);
|
|
14632
|
+
if (pipelines === null || present === undefined) return null;
|
|
14633
|
+
const key = `${frameKey}|${half === 'diffuse' ? 'sd' : 'sa'}`;
|
|
14634
|
+
return (
|
|
14635
|
+
pipelines.peek(key) ??
|
|
14636
|
+
flatPipeline(
|
|
14637
|
+
pipelines,
|
|
14638
|
+
this.surface.device,
|
|
14639
|
+
this.flatLayoutFor(skinned, morphed),
|
|
14640
|
+
this.variant,
|
|
14641
|
+
key,
|
|
14642
|
+
present,
|
|
14643
|
+
false,
|
|
14644
|
+
skinned,
|
|
14645
|
+
morphed,
|
|
14646
|
+
true,
|
|
14647
|
+
layer,
|
|
14648
|
+
false,
|
|
14649
|
+
'none',
|
|
14650
|
+
this.materialDoubleSided,
|
|
14651
|
+
false,
|
|
14652
|
+
eight,
|
|
14653
|
+
clothed,
|
|
14654
|
+
'skin',
|
|
14655
|
+
half,
|
|
14656
|
+
)
|
|
14657
|
+
);
|
|
14658
|
+
}
|
|
14659
|
+
|
|
14424
14660
|
private keepSkinDiffuse(
|
|
14425
14661
|
mesh: GpuMesh,
|
|
14426
14662
|
frameKey: string,
|
|
@@ -14446,30 +14682,18 @@ export class WebGPURenderer implements RendererApi {
|
|
|
14446
14682
|
const bindGroup = this.flatBindGroupFor(skinned, morphed, deltas);
|
|
14447
14683
|
/* The light alone, which the blur spreads, then the colour alone, which it is multiplied by. */
|
|
14448
14684
|
for (const half of SKIN_KEPT_HALVES) {
|
|
14449
|
-
const
|
|
14450
|
-
|
|
14451
|
-
|
|
14452
|
-
|
|
14453
|
-
|
|
14454
|
-
|
|
14455
|
-
|
|
14456
|
-
|
|
14457
|
-
|
|
14458
|
-
|
|
14459
|
-
|
|
14460
|
-
|
|
14461
|
-
morphed,
|
|
14462
|
-
true,
|
|
14463
|
-
layer,
|
|
14464
|
-
false,
|
|
14465
|
-
'none',
|
|
14466
|
-
this.materialDoubleSided,
|
|
14467
|
-
false,
|
|
14468
|
-
eight,
|
|
14469
|
-
clothed,
|
|
14470
|
-
'skin',
|
|
14471
|
-
half,
|
|
14472
|
-
);
|
|
14685
|
+
const pipeline = this.skinHalfPipeline(
|
|
14686
|
+
half,
|
|
14687
|
+
frameKey,
|
|
14688
|
+
base,
|
|
14689
|
+
skinned,
|
|
14690
|
+
morphed,
|
|
14691
|
+
layer,
|
|
14692
|
+
eight,
|
|
14693
|
+
clothed,
|
|
14694
|
+
);
|
|
14695
|
+
/* Both landed before the draw was let through: see `skinHalvesReady`. */
|
|
14696
|
+
if (pipeline === null) return;
|
|
14473
14697
|
const command = half === 'diffuse' ? skin.take() : skin.takeAlbedo();
|
|
14474
14698
|
command.pipeline = pipeline;
|
|
14475
14699
|
command.bindGroup = bindGroup;
|
|
@@ -14483,6 +14707,7 @@ export class WebGPURenderer implements RendererApi {
|
|
|
14483
14707
|
}
|
|
14484
14708
|
command.vertexCount = mesh.vertexBuffers.length;
|
|
14485
14709
|
command.indexBuffer = mesh.indexBuffer;
|
|
14710
|
+
command.indexFormat = mesh.indexFormat;
|
|
14486
14711
|
command.indexed = true;
|
|
14487
14712
|
command.count = mesh.indexCount;
|
|
14488
14713
|
command.instances = 1;
|
|
@@ -14936,6 +15161,7 @@ export class WebGPURenderer implements RendererApi {
|
|
|
14936
15161
|
command.offsetCount = 0;
|
|
14937
15162
|
command.vertexCount = 0;
|
|
14938
15163
|
command.indexBuffer = null;
|
|
15164
|
+
command.indexFormat = 'uint32';
|
|
14939
15165
|
command.indexed = false;
|
|
14940
15166
|
command.instances = 1;
|
|
14941
15167
|
command.indirect = null;
|
|
@@ -14995,7 +15221,7 @@ export class WebGPURenderer implements RendererApi {
|
|
|
14995
15221
|
if (buffer != null) pass.setVertexBuffer(i, buffer);
|
|
14996
15222
|
}
|
|
14997
15223
|
if (command.indexed && command.indexBuffer !== null) {
|
|
14998
|
-
pass.setIndexBuffer(command.indexBuffer,
|
|
15224
|
+
pass.setIndexBuffer(command.indexBuffer, command.indexFormat);
|
|
14999
15225
|
if (command.indirect !== null) pass.drawIndexedIndirect(command.indirect, 0);
|
|
15000
15226
|
else pass.drawIndexed(command.count, command.instances);
|
|
15001
15227
|
} else {
|