@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
|
@@ -133,6 +133,10 @@ export declare class WebGPURenderer implements RendererApi {
|
|
|
133
133
|
* flight at the time, so a consumer that builds more meshes later can wait again.
|
|
134
134
|
*/
|
|
135
135
|
ready(): Promise<void>;
|
|
136
|
+
/** Every distinct cache a lit draw reaches: the frame's, the canvas's, the late pass's, skin's. */
|
|
137
|
+
private pipelineCaches;
|
|
138
|
+
/** Whether a lit draw whose pipeline is not built is left out while it compiles. */
|
|
139
|
+
private skipCompiling;
|
|
136
140
|
private presentedFrameCount;
|
|
137
141
|
/**
|
|
138
142
|
* The joint palettes this frame has set, one slot each. The WebGL2 field of this name is a
|
|
@@ -1179,6 +1183,11 @@ export declare class WebGPURenderer implements RendererApi {
|
|
|
1179
1183
|
private modelMap;
|
|
1180
1184
|
/** The material's shading model, which picks the lit pipeline: null the standard. */
|
|
1181
1185
|
private materialModel;
|
|
1186
|
+
/** `uWorldUv`, the material's projection packed by `packSurfaceProjection`. */
|
|
1187
|
+
private readonly projection;
|
|
1188
|
+
/** `uLayers`, the material's layers packed by `packSurfaceLayers`. */
|
|
1189
|
+
private readonly layerFloats;
|
|
1190
|
+
private warnedLayersModelMap;
|
|
1182
1191
|
/** Its numbers, `uModelParams`, packed by `packModel`. */
|
|
1183
1192
|
private readonly modelParams;
|
|
1184
1193
|
/**
|
|
@@ -1398,6 +1407,8 @@ export declare class WebGPURenderer implements RendererApi {
|
|
|
1398
1407
|
* this one is called per crossfading region per frame and a closure per call is an allocation.
|
|
1399
1408
|
*/
|
|
1400
1409
|
setDitherFade(amount: number): void;
|
|
1410
|
+
/** Whether the draws that follow spend their own opacity on that screen door. See `renderer.ts`. */
|
|
1411
|
+
setDitherOpacity(on: boolean): void;
|
|
1401
1412
|
/**
|
|
1402
1413
|
* How strong the microscopic relief on the surfaces drawn next is, and how coarse.
|
|
1403
1414
|
*
|
|
@@ -2013,6 +2024,22 @@ export declare class WebGPURenderer implements RendererApi {
|
|
|
2013
2024
|
* the texel-for-texel comparison that settled it.
|
|
2014
2025
|
*/
|
|
2015
2026
|
private readonly correctedLightViewProj;
|
|
2027
|
+
/**
|
|
2028
|
+
* What a receiver projects through to read the sun's static layers: the environment's
|
|
2029
|
+
* `lightViewProj`, taken at `bindMeshPass` as WebGL2 takes it there.
|
|
2030
|
+
*
|
|
2031
|
+
* **It was the last shadow pass's matrix**, which is the environment's wherever both layers are
|
|
2032
|
+
* drawn with one and the moving layer's wherever they are not: the static layer was then read
|
|
2033
|
+
* through the moving layer's tight square, and a distant pillar lost its shadow on WebGPU and kept
|
|
2034
|
+
* it on WebGL2, measured on demo/dev/sunLayers.html?moving=tight.
|
|
2035
|
+
*/
|
|
2036
|
+
private readonly receiverLightViewProj;
|
|
2037
|
+
/**
|
|
2038
|
+
* The matrix the sun's dynamic shadow pass was last drawn with, uncorrected as the lit stage
|
|
2039
|
+
* projects with, and whether one has been. See `movingLightFor`.
|
|
2040
|
+
*/
|
|
2041
|
+
private readonly movingLightViewProj;
|
|
2042
|
+
private movingLightKnown;
|
|
2016
2043
|
/**
|
|
2017
2044
|
* The same matrix *uncorrected*, which is what the flat shader must project with.
|
|
2018
2045
|
*
|
|
@@ -2061,6 +2088,19 @@ export declare class WebGPURenderer implements RendererApi {
|
|
|
2061
2088
|
* the lit pass on every surface whether they find anything or not.
|
|
2062
2089
|
*/
|
|
2063
2090
|
private noteGlassCaster;
|
|
2091
|
+
/**
|
|
2092
|
+
* A material's layers where they can be drawn: none asked, or a model's map in the mask's place,
|
|
2093
|
+
* said once, leave one layer.
|
|
2094
|
+
*/
|
|
2095
|
+
private layersOf;
|
|
2096
|
+
/**
|
|
2097
|
+
* What the sun's moving layer is read through: the matrix its shadow pass was last drawn with,
|
|
2098
|
+
* where the lit pipelines carry one (`MOVING_SUN`); the environment's otherwise, which every caller
|
|
2099
|
+
* drawing both layers with one matrix hands it anyway.
|
|
2100
|
+
*/
|
|
2101
|
+
private movingLightFor;
|
|
2102
|
+
/** The moving layer's own matrix on, the first time a frame draws that layer with one. */
|
|
2103
|
+
private enableMovingSun;
|
|
2064
2104
|
/** One of the lit stage's switches on, in every cache a lit pipeline can come from. */
|
|
2065
2105
|
private enableLit;
|
|
2066
2106
|
/** One resolution every glass caster is read through, so recording one allocates nothing. */
|
|
@@ -3202,6 +3242,14 @@ export declare class WebGPURenderer implements RendererApi {
|
|
|
3202
3242
|
* light alone and its colour alone into the blur's targets and test for the depth its frame half
|
|
3203
3243
|
* wrote.
|
|
3204
3244
|
*/
|
|
3245
|
+
/**
|
|
3246
|
+
* Whether a split skin draw's two kept halves have pipelines, starting the compile of either that
|
|
3247
|
+
* has not: a skin drawn without them would lose its diffuse light for the frames they take, so a
|
|
3248
|
+
* split skin draws all three halves or none. See `PipelineCache.lit`.
|
|
3249
|
+
*/
|
|
3250
|
+
private skinHalvesReady;
|
|
3251
|
+
/** One kept half's pipeline, or none where it is still compiling: see `PipelineCache.lit`. */
|
|
3252
|
+
private skinHalfPipeline;
|
|
3205
3253
|
private keepSkinDiffuse;
|
|
3206
3254
|
/**
|
|
3207
3255
|
* Spread the frame's skin and add it back: once, at the first blended draw or before the frame's
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { vertexPackingOf } from '../../vertexPacking.js';
|
|
2
|
+
import { markPacking, markPackingOfKey, packingKey } from './vertexFormats.js';
|
|
1
3
|
import { mat4 } from 'gl-matrix';
|
|
2
4
|
import { probeFaceRange } from '../../reflectionProbe.js';
|
|
3
5
|
import { TEMPORAL_FLICKER, TEMPORAL_HISTORY_BLEND, TemporalHistory, flickerRule, jitterOffset, jitterProjection, } from '../../temporalAa.js';
|
|
@@ -60,6 +62,9 @@ import { gpuCompressedFormats } from './compressedUpload.js';
|
|
|
60
62
|
import { GpuClothBinding, GpuClothParticles, clothStandIn } from './clothTextures.js';
|
|
61
63
|
import { MODEL_PARAM_FLOATS, eyeAxisInWorld, packModel, skinProfileDistance, } from '../../surfaceModel.js';
|
|
62
64
|
import { OVERLAY_FLOATS, overlayLays, packSurfaceOverlay, } from '../../surfaceOverlay.js';
|
|
65
|
+
import { PROJECTION_FLOATS, packSurfaceProjection } from '../../surfaceProjection.js';
|
|
66
|
+
import { orthographicDepthSpan } from '../../lightMatrix.js';
|
|
67
|
+
import { LAYER_FLOATS, packSurfaceLayers } from '../../surfaceLayers.js';
|
|
63
68
|
import { frameReflectionsRefused, resolveFrameReflections, } from '../../frameReflections.js';
|
|
64
69
|
import { REFLECTION_SURFACE_FORMAT, ReflectionSurfacePass } from './reflectionSurfacePass.js';
|
|
65
70
|
import { validateClothBinding } from '../../clothBindingData.js';
|
|
@@ -857,7 +862,21 @@ export class WebGPURenderer {
|
|
|
857
862
|
* flight at the time, so a consumer that builds more meshes later can wait again.
|
|
858
863
|
*/
|
|
859
864
|
async ready() {
|
|
860
|
-
await Promise.all(this.
|
|
865
|
+
await Promise.all(this.pipelineCaches().map((cache) => cache.ready()));
|
|
866
|
+
}
|
|
867
|
+
/** Every distinct cache a lit draw reaches: the frame's, the canvas's, the late pass's, skin's. */
|
|
868
|
+
pipelineCaches() {
|
|
869
|
+
const caches = [...this.pipelineTargets];
|
|
870
|
+
for (const cache of [this.latePipelines, this.skinPipelines]) {
|
|
871
|
+
if (cache !== null && !caches.includes(cache))
|
|
872
|
+
caches.push(cache);
|
|
873
|
+
}
|
|
874
|
+
return caches;
|
|
875
|
+
}
|
|
876
|
+
/** Whether a lit draw whose pipeline is not built is left out while it compiles. */
|
|
877
|
+
skipCompiling(skips) {
|
|
878
|
+
for (const cache of this.pipelineCaches())
|
|
879
|
+
cache.skipsCompiling = skips;
|
|
861
880
|
}
|
|
862
881
|
presentedFrameCount = 0;
|
|
863
882
|
/**
|
|
@@ -2177,6 +2196,7 @@ export class WebGPURenderer {
|
|
|
2177
2196
|
}
|
|
2178
2197
|
filmCommand.vertexCount = geometry.vertexBuffers.length;
|
|
2179
2198
|
filmCommand.indexBuffer = geometry.indexBuffer;
|
|
2199
|
+
filmCommand.indexFormat = geometry.indexFormat;
|
|
2180
2200
|
filmCommand.indexed = true;
|
|
2181
2201
|
filmCommand.count = geometry.indexCount;
|
|
2182
2202
|
}
|
|
@@ -2189,7 +2209,7 @@ export class WebGPURenderer {
|
|
|
2189
2209
|
for (let index = 0; index < geometry.vertexBuffers.length; index++) {
|
|
2190
2210
|
pass.setVertexBuffer(index, geometry.vertexBuffers[index]);
|
|
2191
2211
|
}
|
|
2192
|
-
pass.setIndexBuffer(geometry.indexBuffer,
|
|
2212
|
+
pass.setIndexBuffer(geometry.indexBuffer, geometry.indexFormat);
|
|
2193
2213
|
pass.drawIndexed(geometry.indexCount);
|
|
2194
2214
|
}
|
|
2195
2215
|
}
|
|
@@ -2223,6 +2243,11 @@ export class WebGPURenderer {
|
|
|
2223
2243
|
modelMap = null;
|
|
2224
2244
|
/** The material's shading model, which picks the lit pipeline: null the standard. */
|
|
2225
2245
|
materialModel = null;
|
|
2246
|
+
/** `uWorldUv`, the material's projection packed by `packSurfaceProjection`. */
|
|
2247
|
+
projection = new Float32Array(PROJECTION_FLOATS);
|
|
2248
|
+
/** `uLayers`, the material's layers packed by `packSurfaceLayers`. */
|
|
2249
|
+
layerFloats = new Float32Array(LAYER_FLOATS);
|
|
2250
|
+
warnedLayersModelMap = false;
|
|
2226
2251
|
/** Its numbers, `uModelParams`, packed by `packModel`. */
|
|
2227
2252
|
modelParams = new Float32Array(MODEL_PARAM_FLOATS);
|
|
2228
2253
|
/**
|
|
@@ -2623,7 +2648,10 @@ export class WebGPURenderer {
|
|
|
2623
2648
|
const normal = (material?.normal ?? null);
|
|
2624
2649
|
const orm = (material?.orm ?? null);
|
|
2625
2650
|
const emissiveMap = (material?.emissive ?? null);
|
|
2626
|
-
const
|
|
2651
|
+
const ownModelMap = (material?.modelMap ?? null);
|
|
2652
|
+
/* A layered material's mask goes where a model's map would: see `SurfaceMaterial.layers`. */
|
|
2653
|
+
const layers = this.layersOf(material);
|
|
2654
|
+
const modelMap = ownModelMap ?? (layers?.mask ?? null);
|
|
2627
2655
|
this.materialModel = material?.model ?? null;
|
|
2628
2656
|
const reflectivity = material?.reflectivity;
|
|
2629
2657
|
const environmentGain = material?.environmentGain;
|
|
@@ -2634,7 +2662,7 @@ export class WebGPURenderer {
|
|
|
2634
2662
|
this.writeEnvironmentDials();
|
|
2635
2663
|
/* What the blur spreads this skin by: the last material to name a profile says. */
|
|
2636
2664
|
const model = material?.model;
|
|
2637
|
-
warnUnpagedLightmap(model,
|
|
2665
|
+
warnUnpagedLightmap(model, ownModelMap);
|
|
2638
2666
|
if (model?.kind === 'skin' && this.skinScatter !== null) {
|
|
2639
2667
|
this.skinScatter.setProfile(model.profile, skinProfileDistance(model, 0), skinProfileDistance(model, 1), skinProfileDistance(model, 2));
|
|
2640
2668
|
}
|
|
@@ -2682,10 +2710,23 @@ export class WebGPURenderer {
|
|
|
2682
2710
|
f[emissive + 1] = asked?.[1] ?? 1;
|
|
2683
2711
|
f[emissive + 2] = asked?.[2] ?? 1;
|
|
2684
2712
|
/* The model's numbers and whether its map is bound. See `packModel`. */
|
|
2685
|
-
packModel(material?.model ?? null,
|
|
2713
|
+
packModel(material?.model ?? null, ownModelMap !== null, this.modelParams, material?.physicalSpecular === true);
|
|
2686
2714
|
/* The first physical highlight asked for is when the lit pipelines start carrying one. */
|
|
2687
2715
|
if (material?.physicalSpecular === true)
|
|
2688
2716
|
this.enableLit('PHYSICAL_SPECULAR');
|
|
2717
|
+
/* Maps placed by the world: the first material that asks is when lit pipelines carry it. */
|
|
2718
|
+
packSurfaceProjection(material?.projection, this.projection);
|
|
2719
|
+
f.set(this.projection, this.materialField('uWorldUv'));
|
|
2720
|
+
/* How much light from behind it lets through, in the glass tint's spare lane. */
|
|
2721
|
+
f[this.materialField('uGlassTint') + 3] =
|
|
2722
|
+
Math.min(Math.max(material?.diffuseTransmission ?? 0, 0), 1) || 0;
|
|
2723
|
+
if (this.projection[0] > 0)
|
|
2724
|
+
this.enableLit('WORLD_UVS');
|
|
2725
|
+
/* And its layers, the first time a material blends any: layered.ts. */
|
|
2726
|
+
packSurfaceLayers(layers, this.layerFloats);
|
|
2727
|
+
f.set(this.layerFloats, this.materialField('uLayers'));
|
|
2728
|
+
if (layers !== null)
|
|
2729
|
+
this.enableLit('LAYERED');
|
|
2689
2730
|
f.set(this.modelParams, this.materialField('uModelParams'));
|
|
2690
2731
|
});
|
|
2691
2732
|
/*
|
|
@@ -2873,6 +2914,14 @@ export class WebGPURenderer {
|
|
|
2873
2914
|
this.perFrameFloats[this.materialField('uWriteMode') + 1] = Math.min(1, Math.max(-1, amount));
|
|
2874
2915
|
this.materials.dirty();
|
|
2875
2916
|
}
|
|
2917
|
+
/** Whether the draws that follow spend their own opacity on that screen door. See `renderer.ts`. */
|
|
2918
|
+
setDitherOpacity(on) {
|
|
2919
|
+
if (this.surface.lost)
|
|
2920
|
+
return;
|
|
2921
|
+
/* The third lane of `uWriteMode`, beside the fade. */
|
|
2922
|
+
this.perFrameFloats[this.materialField('uWriteMode') + 2] = on ? 1 : 0;
|
|
2923
|
+
this.materials.dirty();
|
|
2924
|
+
}
|
|
2876
2925
|
/**
|
|
2877
2926
|
* How strong the microscopic relief on the surfaces drawn next is, and how coarse.
|
|
2878
2927
|
*
|
|
@@ -4154,6 +4203,7 @@ export class WebGPURenderer {
|
|
|
4154
4203
|
const sunShadow = env === undefined ? 0 : clamp(options.sunShadow ?? 0, 0, 1);
|
|
4155
4204
|
ring.writeFloat(fragmentSlot, at('uSunShadow'), sunShadow);
|
|
4156
4205
|
ring.writeFloats(fragmentSlot, at('uLightViewProj'), env === undefined ? NO_LIGHT_MATRIX : env.lightViewProj);
|
|
4206
|
+
ring.writeFloats(fragmentSlot, at('uMovingLightViewProj'), env === undefined ? NO_LIGHT_MATRIX : this.movingLightFor(env));
|
|
4157
4207
|
ring.writeFloat(fragmentSlot, at('uShadowMapSize'), this.quality.directionalShadowMapSize);
|
|
4158
4208
|
/* Sampled only where a pass filled it — see `peelFilled` for why existing is not enough. */
|
|
4159
4209
|
ring.writeInt(fragmentSlot, at('uPeeledShadowEnabled'), this.peelFilled ? 1 : 0);
|
|
@@ -4182,6 +4232,7 @@ export class WebGPURenderer {
|
|
|
4182
4232
|
}
|
|
4183
4233
|
volumeCommand.vertexCount = mesh.vertexBuffers.length;
|
|
4184
4234
|
volumeCommand.indexBuffer = mesh.indexBuffer;
|
|
4235
|
+
volumeCommand.indexFormat = mesh.indexFormat;
|
|
4185
4236
|
volumeCommand.indexed = true;
|
|
4186
4237
|
volumeCommand.count = mesh.indexCount;
|
|
4187
4238
|
}
|
|
@@ -4191,7 +4242,7 @@ export class WebGPURenderer {
|
|
|
4191
4242
|
for (let index = 0; index < mesh.vertexBuffers.length; index++) {
|
|
4192
4243
|
pass.setVertexBuffer(index, mesh.vertexBuffers[index]);
|
|
4193
4244
|
}
|
|
4194
|
-
pass.setIndexBuffer(mesh.indexBuffer,
|
|
4245
|
+
pass.setIndexBuffer(mesh.indexBuffer, mesh.indexFormat);
|
|
4195
4246
|
pass.drawIndexed(mesh.indexCount);
|
|
4196
4247
|
}
|
|
4197
4248
|
}
|
|
@@ -4907,6 +4958,22 @@ export class WebGPURenderer {
|
|
|
4907
4958
|
* the texel-for-texel comparison that settled it.
|
|
4908
4959
|
*/
|
|
4909
4960
|
correctedLightViewProj = new Float32Array(16);
|
|
4961
|
+
/**
|
|
4962
|
+
* What a receiver projects through to read the sun's static layers: the environment's
|
|
4963
|
+
* `lightViewProj`, taken at `bindMeshPass` as WebGL2 takes it there.
|
|
4964
|
+
*
|
|
4965
|
+
* **It was the last shadow pass's matrix**, which is the environment's wherever both layers are
|
|
4966
|
+
* drawn with one and the moving layer's wherever they are not: the static layer was then read
|
|
4967
|
+
* through the moving layer's tight square, and a distant pillar lost its shadow on WebGPU and kept
|
|
4968
|
+
* it on WebGL2, measured on demo/dev/sunLayers.html?moving=tight.
|
|
4969
|
+
*/
|
|
4970
|
+
receiverLightViewProj = new Float32Array(16);
|
|
4971
|
+
/**
|
|
4972
|
+
* The matrix the sun's dynamic shadow pass was last drawn with, uncorrected as the lit stage
|
|
4973
|
+
* projects with, and whether one has been. See `movingLightFor`.
|
|
4974
|
+
*/
|
|
4975
|
+
movingLightViewProj = new Float32Array(16);
|
|
4976
|
+
movingLightKnown = false;
|
|
4910
4977
|
/**
|
|
4911
4978
|
* The same matrix *uncorrected*, which is what the flat shader must project with.
|
|
4912
4979
|
*
|
|
@@ -5003,6 +5070,44 @@ export class WebGPURenderer {
|
|
|
5003
5070
|
this.glassSeen = true;
|
|
5004
5071
|
this.enableLit('GLASS_SHADOWS');
|
|
5005
5072
|
}
|
|
5073
|
+
/**
|
|
5074
|
+
* A material's layers where they can be drawn: none asked, or a model's map in the mask's place,
|
|
5075
|
+
* said once, leave one layer.
|
|
5076
|
+
*/
|
|
5077
|
+
layersOf(material) {
|
|
5078
|
+
const layers = material?.layers ?? null;
|
|
5079
|
+
if (layers === null || layers.repeats.length === 0)
|
|
5080
|
+
return null;
|
|
5081
|
+
if ((material?.modelMap ?? null) === null)
|
|
5082
|
+
return layers;
|
|
5083
|
+
if (!this.warnedLayersModelMap) {
|
|
5084
|
+
this.warnedLayersModelMap = true;
|
|
5085
|
+
console.warn("WebGPU: a material's layers are drawn as one: its mask is read where a model's map goes, " +
|
|
5086
|
+
'and this material carries a `modelMap` too.');
|
|
5087
|
+
}
|
|
5088
|
+
return null;
|
|
5089
|
+
}
|
|
5090
|
+
/**
|
|
5091
|
+
* What the sun's moving layer is read through: the matrix its shadow pass was last drawn with,
|
|
5092
|
+
* where the lit pipelines carry one (`MOVING_SUN`); the environment's otherwise, which every caller
|
|
5093
|
+
* drawing both layers with one matrix hands it anyway.
|
|
5094
|
+
*/
|
|
5095
|
+
movingLightFor(env) {
|
|
5096
|
+
return this.movingLightKnown && this.pipelines.litSwitches.MOVING_SUN
|
|
5097
|
+
? this.movingLightViewProj
|
|
5098
|
+
: env.lightViewProj;
|
|
5099
|
+
}
|
|
5100
|
+
/** The moving layer's own matrix on, the first time a frame draws that layer with one. */
|
|
5101
|
+
enableMovingSun(env) {
|
|
5102
|
+
if (this.pipelines.litSwitches.MOVING_SUN || !this.movingLightKnown)
|
|
5103
|
+
return;
|
|
5104
|
+
for (let k = 0; k < 16; k++) {
|
|
5105
|
+
if (this.movingLightViewProj[k] !== env.lightViewProj[k]) {
|
|
5106
|
+
this.enableLit('MOVING_SUN');
|
|
5107
|
+
return;
|
|
5108
|
+
}
|
|
5109
|
+
}
|
|
5110
|
+
}
|
|
5006
5111
|
/** One of the lit stage's switches on, in every cache a lit pipeline can come from. */
|
|
5007
5112
|
enableLit(feature) {
|
|
5008
5113
|
if (this.pipelines.litSwitches[feature])
|
|
@@ -5056,7 +5161,7 @@ export class WebGPURenderer {
|
|
|
5056
5161
|
for (let index = 0; index < geometry.vertexBuffers.length; index++) {
|
|
5057
5162
|
pass.setVertexBuffer(index, geometry.vertexBuffers[index]);
|
|
5058
5163
|
}
|
|
5059
|
-
pass.setIndexBuffer(geometry.indexBuffer,
|
|
5164
|
+
pass.setIndexBuffer(geometry.indexBuffer, geometry.indexFormat);
|
|
5060
5165
|
pass.drawIndexed(geometry.indexCount);
|
|
5061
5166
|
},
|
|
5062
5167
|
/**
|
|
@@ -5129,7 +5234,7 @@ export class WebGPURenderer {
|
|
|
5129
5234
|
pass.setVertexBuffer(index, geometry.vertexBuffers[index]);
|
|
5130
5235
|
}
|
|
5131
5236
|
pass.setVertexBuffer(index, gpuBatch.buffer);
|
|
5132
|
-
pass.setIndexBuffer(geometry.indexBuffer,
|
|
5237
|
+
pass.setIndexBuffer(geometry.indexBuffer, geometry.indexFormat);
|
|
5133
5238
|
pass.drawIndexed(geometry.indexCount, count);
|
|
5134
5239
|
},
|
|
5135
5240
|
skinnedMesh: (mesh, model, palette, material, cloth) => {
|
|
@@ -5172,7 +5277,7 @@ export class WebGPURenderer {
|
|
|
5172
5277
|
for (let index = 0; index < geometry.vertexBuffers.length; index++) {
|
|
5173
5278
|
pass.setVertexBuffer(index, geometry.vertexBuffers[index]);
|
|
5174
5279
|
}
|
|
5175
|
-
pass.setIndexBuffer(geometry.indexBuffer,
|
|
5280
|
+
pass.setIndexBuffer(geometry.indexBuffer, geometry.indexFormat);
|
|
5176
5281
|
pass.drawIndexed(geometry.indexCount);
|
|
5177
5282
|
},
|
|
5178
5283
|
/**
|
|
@@ -5543,6 +5648,8 @@ export class WebGPURenderer {
|
|
|
5543
5648
|
this.overlayPipelines === this.pipelines
|
|
5544
5649
|
? [this.pipelines]
|
|
5545
5650
|
: [this.pipelines, this.overlayPipelines];
|
|
5651
|
+
/* A lit draw first needed inside a frame waits for its compile or is left out while it runs. */
|
|
5652
|
+
this.skipCompiling(quality.pipelineCompile === 'skip');
|
|
5546
5653
|
this.variant = flatVariant({
|
|
5547
5654
|
directionalShadows: quality.directionalShadows,
|
|
5548
5655
|
/* No `bakeReflectionProbe` here; see the field. */
|
|
@@ -6410,6 +6517,8 @@ export class WebGPURenderer {
|
|
|
6410
6517
|
present['layers'] = key.includes(':layers');
|
|
6411
6518
|
/* Nor is a dynamic mesh's split, which moves positions and normals into buffers of their own. */
|
|
6412
6519
|
present['dynamic'] = key.includes(':dynamic');
|
|
6520
|
+
/* Nor how each attribute travels, which moves every field after a packed one. */
|
|
6521
|
+
markPackingOfKey(present, key);
|
|
6413
6522
|
return present;
|
|
6414
6523
|
}
|
|
6415
6524
|
/**
|
|
@@ -6713,6 +6822,13 @@ export class WebGPURenderer {
|
|
|
6713
6822
|
present['dynamic'] = true;
|
|
6714
6823
|
key += ':dynamic';
|
|
6715
6824
|
}
|
|
6825
|
+
/*
|
|
6826
|
+
* And how each attribute travels (`vertexPacking.ts`): a field read as sixteen bits rather than
|
|
6827
|
+
* thirty-two, or not interleaved at all, moves every field after it, so the key says so.
|
|
6828
|
+
*/
|
|
6829
|
+
const packing = vertexPackingOf(data, dynamic);
|
|
6830
|
+
markPacking(present, packing);
|
|
6831
|
+
key += packingKey(packing);
|
|
6716
6832
|
const fullKey = `${this.variant}|${key}`;
|
|
6717
6833
|
/*
|
|
6718
6834
|
* **For every target this mesh can land on, which is two when the overlay is its own.**
|
|
@@ -6920,6 +7036,8 @@ export class WebGPURenderer {
|
|
|
6920
7036
|
bindMeshPass(camera, env) {
|
|
6921
7037
|
if (this.surface.lost)
|
|
6922
7038
|
return;
|
|
7039
|
+
/* The matrix every receiver projects through: the environment's, as WebGL2's. See the field. */
|
|
7040
|
+
this.receiverLightViewProj.set(env.lightViewProj);
|
|
6923
7041
|
/* Rectangles past the fixed arm's are the froxel table's, and without it nobody shades them. */
|
|
6924
7042
|
if (!this.warnedAreaOverflow &&
|
|
6925
7043
|
!this.quality.clusteredLights &&
|
|
@@ -7034,6 +7152,12 @@ export class WebGPURenderer {
|
|
|
7034
7152
|
this.surfaceFog = FOG_RECEDE;
|
|
7035
7153
|
/* Every material switch off — albedo, ORM map, emissive map, two-sided — as WebGL2 resets them. */
|
|
7036
7154
|
i.fill(0, at('uMaterialFlags'), at('uMaterialFlags') + 4);
|
|
7155
|
+
/* And no projection: maps follow the mesh's coordinates until a material asks otherwise. */
|
|
7156
|
+
f.fill(0, at('uWorldUv'), at('uWorldUv') + 4);
|
|
7157
|
+
/* Nor light through from behind. See `SurfaceMaterial.diffuseTransmission`. */
|
|
7158
|
+
f[at('uGlassTint') + 3] = 0;
|
|
7159
|
+
/* Nor layers: one layer until a material asks for more. */
|
|
7160
|
+
f.fill(0, at('uLayers'), at('uLayers') + LAYER_FLOATS);
|
|
7037
7161
|
f[at('uCutout')] = 0;
|
|
7038
7162
|
f[at('uCutout') + 1] = 0;
|
|
7039
7163
|
this.cutoutResolveStaged = 'hard';
|
|
@@ -7106,6 +7230,7 @@ export class WebGPURenderer {
|
|
|
7106
7230
|
/* No weighting and no dither until a pass or a crossfade asks. See `setDitherFade`. */
|
|
7107
7231
|
f[at('uWriteMode')] = 0;
|
|
7108
7232
|
f[at('uWriteMode') + 1] = 0;
|
|
7233
|
+
f[at('uWriteMode') + 2] = 0;
|
|
7109
7234
|
/* 1, not 0: a multiplier's identity is one. See `setEnvironmentGain`. */
|
|
7110
7235
|
f[at('uEnvironmentDials') + 2] = 1;
|
|
7111
7236
|
/* No overlay until a draw sets one. See `setSurfaceOverlay`. */
|
|
@@ -7386,6 +7511,11 @@ export class WebGPURenderer {
|
|
|
7386
7511
|
f[at('uShadowStrength')] = env.shadowStrength;
|
|
7387
7512
|
f[at('uShadowMapSize')] = this.quality.directionalShadowMapSize;
|
|
7388
7513
|
f[at('uShadowDepthSpan')] = env.shadowDepthSpan;
|
|
7514
|
+
/* The moving layer's own matrix and span, where the lit stage reads one: `movingLightFor`. */
|
|
7515
|
+
this.enableMovingSun(env);
|
|
7516
|
+
const moving = this.movingLightFor(env);
|
|
7517
|
+
f.set(moving, at('uMovingLightViewProj'));
|
|
7518
|
+
f[at('uMovingShadowDepthSpan')] = orthographicDepthSpan(moving);
|
|
7389
7519
|
f[at('uShadowMaxDistance')] = this.quality.directionalShadowMaxDistance;
|
|
7390
7520
|
f[at('uShadowMaxSlope')] = this.quality.directionalShadowMaxSlope;
|
|
7391
7521
|
/* Sampled only where a pass filled it — see `peelFilled` for why existing is not enough. */
|
|
@@ -7569,7 +7699,7 @@ export class WebGPURenderer {
|
|
|
7569
7699
|
/** A view block: the camera, the light's matrix and the frame's wind, into `ring` at `slot`. */
|
|
7570
7700
|
writeView(ring, slot, viewProj) {
|
|
7571
7701
|
ring.writeFloats(slot, FLAT_VIEW_FIELDS.uViewProj.offset, viewProj);
|
|
7572
|
-
ring.writeFloats(slot, FLAT_VIEW_FIELDS.uLightViewProj.offset, this.
|
|
7702
|
+
ring.writeFloats(slot, FLAT_VIEW_FIELDS.uLightViewProj.offset, this.receiverLightViewProj);
|
|
7573
7703
|
/* The scene's clock, which a bone animation's instances read their moment from. */
|
|
7574
7704
|
ring.writeFloat(slot, FLAT_VIEW_FIELDS.uSceneTime.offset, this.animationTime);
|
|
7575
7705
|
const d = this.frameWind;
|
|
@@ -7939,14 +8069,20 @@ export class WebGPURenderer {
|
|
|
7939
8069
|
* thrown error in the middle of one.
|
|
7940
8070
|
*/
|
|
7941
8071
|
const pipelines = blend ? this.blendedPipelines(lands) : this.targetPipelines();
|
|
7942
|
-
let pipeline = pipelines.peek(key);
|
|
7943
|
-
if (pipeline ===
|
|
8072
|
+
let pipeline = pipelines.peek(key) ?? null;
|
|
8073
|
+
if (pipeline === null) {
|
|
7944
8074
|
const present = this.meshPresent.get(base);
|
|
7945
8075
|
if (present === undefined) {
|
|
7946
8076
|
throw new Error(`WebGPU: no pipeline for ${key}; createMesh builds it`);
|
|
7947
8077
|
}
|
|
7948
8078
|
pipeline = flatPipeline(pipelines, this.surface.device, this.flatLayoutFor(skinned, morphed), this.variant, key, present, adds ? 'additive' : blend, skinned, morphed, depthWrite, layer, false, this.oitMode, this.materialDoubleSided, coverage, eight, clothed, modelKind, splits ? 'scene' : 'whole');
|
|
7949
8079
|
}
|
|
8080
|
+
/* A split skin draws its three halves or none of them. */
|
|
8081
|
+
if (pipeline !== null &&
|
|
8082
|
+
splits &&
|
|
8083
|
+
!this.skinHalvesReady(key, base, skinned, morphed, layer, eight, clothed)) {
|
|
8084
|
+
pipeline = null;
|
|
8085
|
+
}
|
|
7950
8086
|
/*
|
|
7951
8087
|
* Guards the draw call only, not the restore below.
|
|
7952
8088
|
*
|
|
@@ -7963,8 +8099,9 @@ export class WebGPURenderer {
|
|
|
7963
8099
|
* close to the 256-slot budget before the gateway, the play controls, the waveform, the
|
|
7964
8100
|
* label handles and the sparkles are even counted.
|
|
7965
8101
|
*/
|
|
7966
|
-
|
|
7967
|
-
|
|
8102
|
+
/* A draw whose pipeline is still compiling is left out, its state restored all the same. */
|
|
8103
|
+
const material = pipeline === null ? null : this.materialSlotForDraw();
|
|
8104
|
+
if (pipeline !== null && material !== null) {
|
|
7968
8105
|
/*
|
|
7969
8106
|
* Record rather than issue. Every per-draw value is already in `slot` and `material` —
|
|
7970
8107
|
* the uniform rings are the state arena this design would otherwise have had to build —
|
|
@@ -7986,6 +8123,7 @@ export class WebGPURenderer {
|
|
|
7986
8123
|
}
|
|
7987
8124
|
command.vertexCount = mesh.vertexBuffers.length;
|
|
7988
8125
|
command.indexBuffer = mesh.indexBuffer;
|
|
8126
|
+
command.indexFormat = mesh.indexFormat;
|
|
7989
8127
|
command.indexed = true;
|
|
7990
8128
|
command.count = mesh.indexCount;
|
|
7991
8129
|
}
|
|
@@ -8003,7 +8141,7 @@ export class WebGPURenderer {
|
|
|
8003
8141
|
for (let index = 0; index < mesh.vertexBuffers.length; index++) {
|
|
8004
8142
|
pass.setVertexBuffer(index, mesh.vertexBuffers[index]);
|
|
8005
8143
|
}
|
|
8006
|
-
pass.setIndexBuffer(mesh.indexBuffer,
|
|
8144
|
+
pass.setIndexBuffer(mesh.indexBuffer, mesh.indexFormat);
|
|
8007
8145
|
pass.drawIndexed(mesh.indexCount);
|
|
8008
8146
|
}
|
|
8009
8147
|
if (splits) {
|
|
@@ -8378,16 +8516,17 @@ export class WebGPURenderer {
|
|
|
8378
8516
|
`${this.materialDoubleSided ? '|2s' : ''}${coverage ? '|a2c' : ''}` +
|
|
8379
8517
|
`${modelKind === null ? '' : `|m:${modelKind}`}`;
|
|
8380
8518
|
const pipelines = blend ? this.blendedPipelines(lands) : this.targetPipelines();
|
|
8381
|
-
let pipeline = pipelines.peek(key);
|
|
8382
|
-
if (pipeline ===
|
|
8519
|
+
let pipeline = pipelines.peek(key) ?? null;
|
|
8520
|
+
if (pipeline === null) {
|
|
8383
8521
|
const present = this.meshPresent.get(base);
|
|
8384
8522
|
if (present === undefined) {
|
|
8385
8523
|
throw new Error(`WebGPU: no mesh attributes recorded for ${base}; createMesh records them`);
|
|
8386
8524
|
}
|
|
8387
8525
|
pipeline = flatPipeline(pipelines, this.surface.device, animation === null ? this.flatLayoutFor(false, false) : this.animatedBindGroupLayout, this.variant, key, present, adds ? 'additive' : blend, false, false, depthWrite, layer, true, 'none', this.materialDoubleSided, coverage, false, false, modelKind, 'whole', false, animation !== null);
|
|
8388
8526
|
}
|
|
8389
|
-
|
|
8390
|
-
|
|
8527
|
+
/* A batch whose pipeline is still compiling is left out, as a mesh is. */
|
|
8528
|
+
const material = pipeline === null ? null : this.materialSlotForDraw();
|
|
8529
|
+
if (pipeline !== null && material !== null) {
|
|
8391
8530
|
const command = blend
|
|
8392
8531
|
? this.recordBlended(0, lands)
|
|
8393
8532
|
: this.recordDraw(0, this.currentTarget());
|
|
@@ -8409,6 +8548,7 @@ export class WebGPURenderer {
|
|
|
8409
8548
|
command.vertexBuffers[index] = instanceBuffer;
|
|
8410
8549
|
command.vertexCount = mesh.vertexBuffers.length + 1;
|
|
8411
8550
|
command.indexBuffer = mesh.indexBuffer;
|
|
8551
|
+
command.indexFormat = mesh.indexFormat;
|
|
8412
8552
|
command.indexed = true;
|
|
8413
8553
|
command.count = mesh.indexCount;
|
|
8414
8554
|
command.instances = count;
|
|
@@ -8427,7 +8567,7 @@ export class WebGPURenderer {
|
|
|
8427
8567
|
pass.setVertexBuffer(index, mesh.vertexBuffers[index]);
|
|
8428
8568
|
}
|
|
8429
8569
|
pass.setVertexBuffer(index, instanceBuffer);
|
|
8430
|
-
pass.setIndexBuffer(mesh.indexBuffer,
|
|
8570
|
+
pass.setIndexBuffer(mesh.indexBuffer, mesh.indexFormat);
|
|
8431
8571
|
if (cut === null)
|
|
8432
8572
|
pass.drawIndexed(mesh.indexCount, count);
|
|
8433
8573
|
else
|
|
@@ -8628,6 +8768,11 @@ export class WebGPURenderer {
|
|
|
8628
8768
|
if (view === null)
|
|
8629
8769
|
return false;
|
|
8630
8770
|
this.lightViewProj.set(lightViewProj);
|
|
8771
|
+
/* The moving layer is read through the matrix it is drawn with: see `movingLightFor`. */
|
|
8772
|
+
if (dynamic) {
|
|
8773
|
+
this.movingLightViewProj.set(lightViewProj);
|
|
8774
|
+
this.movingLightKnown = true;
|
|
8775
|
+
}
|
|
8631
8776
|
this.reopenViews();
|
|
8632
8777
|
mat4.multiply(this.correctedLightViewProj, SHADOW_CLIP_CORRECTION, lightViewProj);
|
|
8633
8778
|
this.shadowLayerIsPeel = peel;
|
|
@@ -8912,11 +9057,14 @@ export class WebGPURenderer {
|
|
|
8912
9057
|
this.lateViewBlock.slot = list.viewOffset(0);
|
|
8913
9058
|
this.materials.dirty();
|
|
8914
9059
|
this.staticRecording = recording;
|
|
9060
|
+
/* A recorded list keeps what it recorded, so every draw of it waits for its pipeline. */
|
|
9061
|
+
this.skipCompiling(false);
|
|
8915
9062
|
try {
|
|
8916
9063
|
this.sceneCasterMaterial = undefined;
|
|
8917
9064
|
replayStaticDraws(list, this.sceneCasterSink);
|
|
8918
9065
|
}
|
|
8919
9066
|
finally {
|
|
9067
|
+
this.skipCompiling(this.quality.pipelineCompile === 'skip');
|
|
8920
9068
|
this.staticRecording = null;
|
|
8921
9069
|
this.perDraw = perDraw;
|
|
8922
9070
|
this.passRing = passRing;
|
|
@@ -9186,7 +9334,7 @@ export class WebGPURenderer {
|
|
|
9186
9334
|
for (let index = 0; index < geometry.vertexBuffers.length; index++) {
|
|
9187
9335
|
pass.setVertexBuffer(index, geometry.vertexBuffers[index]);
|
|
9188
9336
|
}
|
|
9189
|
-
pass.setIndexBuffer(geometry.indexBuffer,
|
|
9337
|
+
pass.setIndexBuffer(geometry.indexBuffer, geometry.indexFormat);
|
|
9190
9338
|
pass.drawIndexed(geometry.indexCount);
|
|
9191
9339
|
},
|
|
9192
9340
|
instanced: (batch, data, material, glass) => {
|
|
@@ -9220,7 +9368,7 @@ export class WebGPURenderer {
|
|
|
9220
9368
|
pass.setVertexBuffer(index, geometry.vertexBuffers[index]);
|
|
9221
9369
|
}
|
|
9222
9370
|
pass.setVertexBuffer(index, gpuBatch.buffer);
|
|
9223
|
-
pass.setIndexBuffer(geometry.indexBuffer,
|
|
9371
|
+
pass.setIndexBuffer(geometry.indexBuffer, geometry.indexFormat);
|
|
9224
9372
|
pass.drawIndexed(geometry.indexCount, count);
|
|
9225
9373
|
},
|
|
9226
9374
|
skinnedMesh: (mesh, model, palette, _material, glass) => {
|
|
@@ -9248,7 +9396,7 @@ export class WebGPURenderer {
|
|
|
9248
9396
|
for (let index = 0; index < geometry.vertexBuffers.length; index++) {
|
|
9249
9397
|
pass.setVertexBuffer(index, geometry.vertexBuffers[index]);
|
|
9250
9398
|
}
|
|
9251
|
-
pass.setIndexBuffer(geometry.indexBuffer,
|
|
9399
|
+
pass.setIndexBuffer(geometry.indexBuffer, geometry.indexFormat);
|
|
9252
9400
|
pass.drawIndexed(geometry.indexCount);
|
|
9253
9401
|
},
|
|
9254
9402
|
};
|
|
@@ -11377,6 +11525,7 @@ export class WebGPURenderer {
|
|
|
11377
11525
|
/* Uncorrected, for the reason the shaft's own copy of this line carries: the shader does its
|
|
11378
11526
|
own `* 0.5 + 0.5`, and correcting the matrix as well doubles it. */
|
|
11379
11527
|
f.set(env?.lightViewProj ?? this.mediumIdentity, at('uLightViewProj'));
|
|
11528
|
+
f.set((env === null ? this.mediumIdentity : this.movingLightFor(env)), at('uMovingLightViewProj'));
|
|
11380
11529
|
ints[at('uPeeledShadowEnabled')] = this.peelView === null || !this.peelFilled ? 0 : 1;
|
|
11381
11530
|
device.queue.writeBuffer(this.mediumUniforms, 0, this.mediumStaging);
|
|
11382
11531
|
const g = this.mediumUpsampleFloats;
|
|
@@ -11778,6 +11927,9 @@ export class WebGPURenderer {
|
|
|
11778
11927
|
const key = `${frameKey}|rs`;
|
|
11779
11928
|
const pipeline = this.pipelines.peek(key) ??
|
|
11780
11929
|
flatPipeline(this.pipelines, this.surface.device, animation === null ? this.flatLayoutFor(skinned, morphed) : this.animatedBindGroupLayout, this.variant, key, present, false, skinned, morphed, true, layer, instanceBuffer !== null, 'none', this.materialDoubleSided, false, eight, clothed, modelKind, 'whole', true, animation !== null);
|
|
11930
|
+
/* Still compiling where draws skip: the probe stands in for this surface until it lands. */
|
|
11931
|
+
if (pipeline === null)
|
|
11932
|
+
return;
|
|
11781
11933
|
/* A static list's surface halves go into its own pool, beside its draws. */
|
|
11782
11934
|
const command = this.staticRecording === null ? surface.take() : takeRecorded(this.staticRecording.surface);
|
|
11783
11935
|
command.pipeline = pipeline;
|
|
@@ -11798,6 +11950,7 @@ export class WebGPURenderer {
|
|
|
11798
11950
|
command.vertexBuffers[index++] = instanceBuffer;
|
|
11799
11951
|
command.vertexCount = index;
|
|
11800
11952
|
command.indexBuffer = mesh.indexBuffer;
|
|
11953
|
+
command.indexFormat = mesh.indexFormat;
|
|
11801
11954
|
command.indexed = true;
|
|
11802
11955
|
command.count = mesh.indexCount;
|
|
11803
11956
|
command.instances = instances;
|
|
@@ -11809,6 +11962,30 @@ export class WebGPURenderer {
|
|
|
11809
11962
|
* light alone and its colour alone into the blur's targets and test for the depth its frame half
|
|
11810
11963
|
* wrote.
|
|
11811
11964
|
*/
|
|
11965
|
+
/**
|
|
11966
|
+
* Whether a split skin draw's two kept halves have pipelines, starting the compile of either that
|
|
11967
|
+
* has not: a skin drawn without them would lose its diffuse light for the frames they take, so a
|
|
11968
|
+
* split skin draws all three halves or none. See `PipelineCache.lit`.
|
|
11969
|
+
*/
|
|
11970
|
+
skinHalvesReady(frameKey, base, skinned, morphed, layer, eight, clothed) {
|
|
11971
|
+
let ready = true;
|
|
11972
|
+
for (const half of SKIN_KEPT_HALVES) {
|
|
11973
|
+
const pipeline = this.skinHalfPipeline(half, frameKey, base, skinned, morphed, layer, eight, clothed);
|
|
11974
|
+
if (pipeline === null)
|
|
11975
|
+
ready = false;
|
|
11976
|
+
}
|
|
11977
|
+
return ready;
|
|
11978
|
+
}
|
|
11979
|
+
/** One kept half's pipeline, or none where it is still compiling: see `PipelineCache.lit`. */
|
|
11980
|
+
skinHalfPipeline(half, frameKey, base, skinned, morphed, layer, eight, clothed) {
|
|
11981
|
+
const pipelines = this.skinPipelines;
|
|
11982
|
+
const present = this.meshPresent.get(base);
|
|
11983
|
+
if (pipelines === null || present === undefined)
|
|
11984
|
+
return null;
|
|
11985
|
+
const key = `${frameKey}|${half === 'diffuse' ? 'sd' : 'sa'}`;
|
|
11986
|
+
return (pipelines.peek(key) ??
|
|
11987
|
+
flatPipeline(pipelines, this.surface.device, this.flatLayoutFor(skinned, morphed), this.variant, key, present, false, skinned, morphed, true, layer, false, 'none', this.materialDoubleSided, false, eight, clothed, 'skin', half));
|
|
11988
|
+
}
|
|
11812
11989
|
keepSkinDiffuse(mesh, frameKey, base, skinned, morphed, deltas, layer, eight, clothed, slot, material) {
|
|
11813
11990
|
/* A skin's halves are not bundled: a static list holding one replays draw by draw. */
|
|
11814
11991
|
if (this.staticRecording !== null) {
|
|
@@ -11823,9 +12000,10 @@ export class WebGPURenderer {
|
|
|
11823
12000
|
const bindGroup = this.flatBindGroupFor(skinned, morphed, deltas);
|
|
11824
12001
|
/* The light alone, which the blur spreads, then the colour alone, which it is multiplied by. */
|
|
11825
12002
|
for (const half of SKIN_KEPT_HALVES) {
|
|
11826
|
-
const
|
|
11827
|
-
|
|
11828
|
-
|
|
12003
|
+
const pipeline = this.skinHalfPipeline(half, frameKey, base, skinned, morphed, layer, eight, clothed);
|
|
12004
|
+
/* Both landed before the draw was let through: see `skinHalvesReady`. */
|
|
12005
|
+
if (pipeline === null)
|
|
12006
|
+
return;
|
|
11829
12007
|
const command = half === 'diffuse' ? skin.take() : skin.takeAlbedo();
|
|
11830
12008
|
command.pipeline = pipeline;
|
|
11831
12009
|
command.bindGroup = bindGroup;
|
|
@@ -11839,6 +12017,7 @@ export class WebGPURenderer {
|
|
|
11839
12017
|
}
|
|
11840
12018
|
command.vertexCount = mesh.vertexBuffers.length;
|
|
11841
12019
|
command.indexBuffer = mesh.indexBuffer;
|
|
12020
|
+
command.indexFormat = mesh.indexFormat;
|
|
11842
12021
|
command.indexed = true;
|
|
11843
12022
|
command.count = mesh.indexCount;
|
|
11844
12023
|
command.instances = 1;
|
|
@@ -12277,6 +12456,7 @@ export class WebGPURenderer {
|
|
|
12277
12456
|
command.offsetCount = 0;
|
|
12278
12457
|
command.vertexCount = 0;
|
|
12279
12458
|
command.indexBuffer = null;
|
|
12459
|
+
command.indexFormat = 'uint32';
|
|
12280
12460
|
command.indexed = false;
|
|
12281
12461
|
command.instances = 1;
|
|
12282
12462
|
command.indirect = null;
|
|
@@ -12344,7 +12524,7 @@ export class WebGPURenderer {
|
|
|
12344
12524
|
pass.setVertexBuffer(i, buffer);
|
|
12345
12525
|
}
|
|
12346
12526
|
if (command.indexed && command.indexBuffer !== null) {
|
|
12347
|
-
pass.setIndexBuffer(command.indexBuffer,
|
|
12527
|
+
pass.setIndexBuffer(command.indexBuffer, command.indexFormat);
|
|
12348
12528
|
if (command.indirect !== null)
|
|
12349
12529
|
pass.drawIndexedIndirect(command.indirect, 0);
|
|
12350
12530
|
else
|