@driftengine/core 4.8.7 → 4.10.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 +123 -11
- package/README.md +43 -38
- package/dist/index.d.ts +8 -1
- package/dist/index.js +11 -3
- 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/atmosphere.d.ts +13 -0
- package/dist/render/atmosphere.js +9 -1
- package/dist/render/backend/api.d.ts +19 -4
- package/dist/render/backend/createRenderer.d.ts +6 -0
- package/dist/render/backend/createRenderer.js +4 -1
- 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 +180 -4
- package/dist/render/backend/webgl2/renderer.js +550 -40
- 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 +19 -4
- package/dist/render/backend/webgpu/buffers.js +18 -11
- 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/device.d.ts +7 -1
- package/dist/render/backend/webgpu/device.js +31 -3
- package/dist/render/backend/webgpu/drawCommand.d.ts +18 -4
- package/dist/render/backend/webgpu/drawCommand.js +10 -3
- package/dist/render/backend/webgpu/flatPass.d.ts +100 -42
- package/dist/render/backend/webgpu/flatPass.js +191 -43
- package/dist/render/backend/webgpu/instanced.d.ts +14 -1
- package/dist/render/backend/webgpu/instanced.js +24 -1
- package/dist/render/backend/webgpu/materialStore.d.ts +101 -0
- package/dist/render/backend/webgpu/materialStore.js +265 -0
- package/dist/render/backend/webgpu/pipelineCache.d.ts +6 -0
- package/dist/render/backend/webgpu/pipelineCache.js +7 -0
- package/dist/render/backend/webgpu/postPass.d.ts +51 -9
- package/dist/render/backend/webgpu/postPass.js +16 -2
- package/dist/render/backend/webgpu/reflectionSurfacePass.d.ts +30 -0
- package/dist/render/backend/webgpu/reflectionSurfacePass.js +100 -0
- package/dist/render/backend/webgpu/renderer.d.ts +283 -37
- package/dist/render/backend/webgpu/renderer.js +1363 -202
- 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 +241 -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/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/displayRange.d.ts +31 -0
- package/dist/render/displayRange.js +47 -0
- package/dist/render/filmicCurve.d.ts +74 -0
- package/dist/render/filmicCurve.js +203 -0
- package/dist/render/fog.d.ts +4 -1
- package/dist/render/fog.js +12 -2
- package/dist/render/frame/resources.d.ts +2 -2
- package/dist/render/frame/resources.js +6 -0
- package/dist/render/frameReflections.d.ts +40 -0
- package/dist/render/frameReflections.js +48 -0
- package/dist/render/glCompressed.js +83 -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/lightmap.d.ts +1 -1
- package/dist/render/mesh.d.ts +5 -0
- package/dist/render/mesh.js +6 -0
- package/dist/render/pass.d.ts +49 -0
- package/dist/render/pointLightSelection.d.ts +4 -4
- package/dist/render/reflectionSurfaceTargets.d.ts +28 -0
- package/dist/render/reflectionSurfaceTargets.js +99 -0
- package/dist/render/renderQuality.d.ts +39 -8
- package/dist/render/renderQuality.js +4 -0
- package/dist/render/sceneTarget.d.ts +5 -0
- package/dist/render/sceneTarget.js +24 -1
- package/dist/render/screenSpaceReflection.d.ts +7 -1
- package/dist/render/screenSpaceReflection.js +5 -0
- package/dist/render/shaders/arcane.d.ts +1 -1
- package/dist/render/shaders/bolt.d.ts +1 -1
- package/dist/render/shaders/boneAnimation.d.ts +19 -0
- package/dist/render/shaders/boneAnimation.js +63 -0
- package/dist/render/shaders/caustics.d.ts +1 -1
- package/dist/render/shaders/depth.d.ts +7 -0
- package/dist/render/shaders/depth.js +35 -10
- package/dist/render/shaders/film.d.ts +1 -1
- package/dist/render/shaders/filmLook.js +2 -1
- package/dist/render/shaders/fire.d.ts +1 -1
- package/dist/render/shaders/flat/glassTint.d.ts +1 -1
- package/dist/render/shaders/flat/glassTint.js +2 -0
- package/dist/render/shaders/flat/index.d.ts +16 -0
- package/dist/render/shaders/flat/index.js +33 -5
- package/dist/render/shaders/flat/main.d.ts +1 -1
- package/dist/render/shaders/flat/main.js +43 -5
- package/dist/render/shaders/flat/models.js +1 -1
- package/dist/render/shaders/flat/overlay.d.ts +16 -0
- package/dist/render/shaders/flat/overlay.js +117 -0
- package/dist/render/shaders/flat/pointShadow.js +3 -3
- package/dist/render/shaders/flat/preamble.js +38 -24
- package/dist/render/shaders/flat/reflectionSurface.d.ts +21 -0
- package/dist/render/shaders/flat/reflectionSurface.js +61 -0
- package/dist/render/shaders/fog.d.ts +1 -1
- package/dist/render/shaders/fog.js +9 -2
- package/dist/render/shaders/fringe.d.ts +29 -0
- package/dist/render/shaders/fringe.js +55 -0
- package/dist/render/shaders/generated/arcane.wgsl.d.ts +1 -1
- package/dist/render/shaders/generated/arcane.wgsl.js +1 -1
- package/dist/render/shaders/generated/bolt.wgsl.d.ts +1 -1
- package/dist/render/shaders/generated/bolt.wgsl.js +1 -1
- package/dist/render/shaders/generated/caustics.wgsl.d.ts +1 -1
- package/dist/render/shaders/generated/caustics.wgsl.js +1 -1
- package/dist/render/shaders/generated/depth.wgsl.d.ts +93 -0
- package/dist/render/shaders/generated/depth.wgsl.js +93 -0
- package/dist/render/shaders/generated/film.wgsl.d.ts +1 -1
- package/dist/render/shaders/generated/film.wgsl.js +1 -1
- package/dist/render/shaders/generated/fire.wgsl.d.ts +1 -1
- package/dist/render/shaders/generated/fire.wgsl.js +1 -1
- package/dist/render/shaders/generated/flat.wgsl.d.ts +3254 -2920
- package/dist/render/shaders/generated/flat.wgsl.js +3292 -2957
- package/dist/render/shaders/generated/line.wgsl.d.ts +1 -1
- package/dist/render/shaders/generated/line.wgsl.js +1 -1
- package/dist/render/shaders/generated/particle.wgsl.d.ts +4 -4
- package/dist/render/shaders/generated/particle.wgsl.js +4 -4
- package/dist/render/shaders/generated/rush.wgsl.d.ts +56 -26
- package/dist/render/shaders/generated/rush.wgsl.js +56 -26
- package/dist/render/shaders/generated/scatter.wgsl.d.ts +1 -1
- package/dist/render/shaders/generated/scatter.wgsl.js +1 -1
- package/dist/render/shaders/generated/smoke.wgsl.d.ts +1 -1
- package/dist/render/shaders/generated/smoke.wgsl.js +1 -1
- package/dist/render/shaders/generated/ssrResolve.wgsl.d.ts +29 -0
- package/dist/render/shaders/generated/ssrResolve.wgsl.js +29 -0
- package/dist/render/shaders/generated/ssrTrace.wgsl.d.ts +22 -2
- package/dist/render/shaders/generated/ssrTrace.wgsl.js +22 -2
- package/dist/render/shaders/generated/water.wgsl.d.ts +1 -1
- package/dist/render/shaders/generated/water.wgsl.js +1 -1
- package/dist/render/shaders/gpudriven/fog.wgsl.d.ts +2 -2
- package/dist/render/shaders/gpudriven/fog.wgsl.js +11 -3
- package/dist/render/shaders/line.d.ts +1 -1
- package/dist/render/shaders/outputTransform.d.ts +7 -0
- package/dist/render/shaders/outputTransform.js +28 -14
- package/dist/render/shaders/particle.d.ts +3 -3
- package/dist/render/shaders/rush.js +54 -11
- package/dist/render/shaders/scatter.d.ts +1 -1
- package/dist/render/shaders/smoke.d.ts +1 -1
- package/dist/render/shaders/ssrResolve.d.ts +17 -0
- package/dist/render/shaders/ssrResolve.js +51 -0
- package/dist/render/shaders/ssrTrace.js +26 -0
- package/dist/render/shaders/vertexChannel.d.ts +7 -0
- package/dist/render/shaders/vertexChannel.js +26 -0
- package/dist/render/shaders/water.d.ts +1 -1
- package/dist/render/ssrPass.d.ts +16 -0
- package/dist/render/ssrPass.js +106 -1
- package/dist/render/staticDraws.d.ts +47 -0
- package/dist/render/staticDraws.js +43 -0
- package/dist/render/surfaceOverlay.d.ts +132 -0
- package/dist/render/surfaceOverlay.js +85 -0
- package/dist/render/surfaceTexture.d.ts +57 -7
- package/dist/render/surfaceTexture.js +125 -17
- package/dist/render/temporalAa.d.ts +14 -0
- package/dist/render/temporalAa.js +20 -0
- package/dist/render/vertexDefaults.d.ts +17 -0
- package/dist/render/vertexDefaults.js +24 -0
- package/package.json +6 -6
- package/src/index.ts +24 -2
- package/src/render/ambientHarmonics.ts +1 -1
- package/src/render/areaLights.ts +4 -4
- package/src/render/atmosphere.ts +22 -1
- package/src/render/backend/api.ts +22 -3
- package/src/render/backend/createRenderer.ts +18 -1
- 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 +672 -37
- 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 +42 -16
- package/src/render/backend/webgpu/compressedUpload.ts +59 -9
- package/src/render/backend/webgpu/depthPass.ts +51 -10
- package/src/render/backend/webgpu/device.ts +42 -3
- package/src/render/backend/webgpu/drawCommand.ts +22 -4
- package/src/render/backend/webgpu/flatPass.ts +250 -40
- package/src/render/backend/webgpu/instanced.ts +32 -1
- package/src/render/backend/webgpu/materialStore.ts +276 -0
- package/src/render/backend/webgpu/pipelineCache.ts +7 -0
- package/src/render/backend/webgpu/postPass.ts +18 -0
- package/src/render/backend/webgpu/reflectionSurfacePass.ts +114 -0
- package/src/render/backend/webgpu/renderer.ts +1655 -230
- 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 +363 -0
- package/src/render/backend/webgpu/surfaceTexturePass.ts +29 -3
- package/src/render/backend/webgpu/uniformRing.ts +10 -1
- package/src/render/bloomChain.ts +3 -3
- package/src/render/boneAnimation.ts +223 -0
- package/src/render/compressedSource.ts +121 -29
- package/src/render/displayRange.ts +61 -0
- package/src/render/filmicCurve.ts +229 -0
- package/src/render/fog.ts +19 -3
- package/src/render/frame/resources.ts +6 -0
- package/src/render/frameReflections.ts +72 -0
- package/src/render/glCompressed.ts +83 -0
- package/src/render/instances.ts +27 -0
- package/src/render/lightBudget.ts +11 -0
- package/src/render/lightmap.ts +1 -1
- package/src/render/mesh.ts +6 -0
- package/src/render/pass.ts +53 -1
- package/src/render/pointLightSelection.ts +4 -4
- package/src/render/reflectionSurfaceTargets.ts +105 -0
- package/src/render/renderQuality.ts +44 -8
- package/src/render/sceneTarget.ts +30 -2
- package/src/render/screenSpaceReflection.ts +7 -1
- package/src/render/shaders/boneAnimation.ts +63 -0
- package/src/render/shaders/depth.ts +45 -10
- package/src/render/shaders/filmLook.ts +2 -1
- package/src/render/shaders/flat/glassTint.ts +5 -1
- package/src/render/shaders/flat/index.ts +49 -5
- package/src/render/shaders/flat/main.ts +43 -5
- package/src/render/shaders/flat/models.ts +1 -1
- package/src/render/shaders/flat/overlay.ts +117 -0
- package/src/render/shaders/flat/pointShadow.ts +3 -3
- package/src/render/shaders/flat/preamble.ts +38 -24
- package/src/render/shaders/flat/reflectionSurface.ts +61 -0
- package/src/render/shaders/fog.ts +9 -2
- package/src/render/shaders/fringe.ts +59 -0
- package/src/render/shaders/generated/arcane.wgsl.ts +1 -1
- package/src/render/shaders/generated/bolt.wgsl.ts +1 -1
- package/src/render/shaders/generated/caustics.wgsl.ts +1 -1
- package/src/render/shaders/generated/depth.wgsl.ts +95 -0
- package/src/render/shaders/generated/film.wgsl.ts +1 -1
- package/src/render/shaders/generated/fire.wgsl.ts +1 -1
- package/src/render/shaders/generated/flat.wgsl.ts +3292 -2957
- package/src/render/shaders/generated/line.wgsl.ts +1 -1
- package/src/render/shaders/generated/particle.wgsl.ts +4 -4
- package/src/render/shaders/generated/rush.wgsl.ts +56 -26
- package/src/render/shaders/generated/scatter.wgsl.ts +1 -1
- package/src/render/shaders/generated/smoke.wgsl.ts +1 -1
- package/src/render/shaders/generated/ssrResolve.wgsl.ts +30 -0
- package/src/render/shaders/generated/ssrTrace.wgsl.ts +22 -2
- package/src/render/shaders/generated/water.wgsl.ts +1 -1
- package/src/render/shaders/gpudriven/fog.wgsl.ts +11 -3
- package/src/render/shaders/outputTransform.ts +30 -14
- package/src/render/shaders/rush.ts +54 -11
- package/src/render/shaders/ssrResolve.ts +52 -0
- package/src/render/shaders/ssrTrace.ts +26 -0
- package/src/render/shaders/vertexChannel.ts +27 -0
- package/src/render/ssrPass.ts +138 -1
- package/src/render/staticDraws.ts +95 -0
- package/src/render/surfaceOverlay.ts +195 -0
- package/src/render/surfaceTexture.ts +161 -27
- package/src/render/temporalAa.ts +20 -0
- package/src/render/vertexDefaults.ts +28 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The frame's materials' reflection maps on WebGL2: two half-float textures on the scene's own
|
|
3
|
+
* framebuffer, beside its colour, written by the opaque lit draws as they are drawn. What the two
|
|
4
|
+
* hold is `shaders/flat/reflectionSurface.ts`'s to say; this is where they live on this backend.
|
|
5
|
+
*
|
|
6
|
+
* **Written in the frame's own pass, where WebGPU replays the draws in a second one.** A WebGL2
|
|
7
|
+
* program writing an output its framebuffer has no buffer enabled for loses that output and nothing
|
|
8
|
+
* else, so the maps are enabled around an opaque lit draw (`on`, `off`) and stay disabled for every
|
|
9
|
+
* other: the sky, glass, text and particles write no material, and a draw into a mirror, a probe or
|
|
10
|
+
* a capture is into another framebuffer, whose draw buffers this never touches.
|
|
11
|
+
*
|
|
12
|
+
* **Detached once the trace has read them** (`detach`), because the resolve then draws into the
|
|
13
|
+
* scene's framebuffer while sampling both, and a texture sampled while attached to the framebuffer
|
|
14
|
+
* being drawn is a feedback loop whether or not its buffer is enabled. `begin` attaches them again.
|
|
15
|
+
*/
|
|
16
|
+
const ZERO = new Float32Array(4);
|
|
17
|
+
|
|
18
|
+
export class ReflectionSurfaceTargets {
|
|
19
|
+
private probe: WebGLTexture | null = null;
|
|
20
|
+
private tint: WebGLTexture | null = null;
|
|
21
|
+
private width = 0;
|
|
22
|
+
private height = 0;
|
|
23
|
+
private readonly all: number[];
|
|
24
|
+
private readonly colourAlone: number[];
|
|
25
|
+
|
|
26
|
+
constructor(private readonly gl: WebGL2RenderingContext) {
|
|
27
|
+
this.all = [gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1, gl.COLOR_ATTACHMENT2];
|
|
28
|
+
this.colourAlone = [gl.COLOR_ATTACHMENT0];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** The environment as the frame shows it, and the roughness in alpha. */
|
|
32
|
+
get probeTexture(): WebGLTexture | null {
|
|
33
|
+
return this.probe;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** What a found reflection is multiplied by. */
|
|
37
|
+
get tintTexture(): WebGLTexture | null {
|
|
38
|
+
return this.tint;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* At the frame's start, with the scene's framebuffer bound: both at its size, attached, cleared to
|
|
43
|
+
* nothing reflected, and left disabled.
|
|
44
|
+
*/
|
|
45
|
+
begin(width: number, height: number): void {
|
|
46
|
+
const { gl } = this;
|
|
47
|
+
if (this.probe === null || this.width !== width || this.height !== height) {
|
|
48
|
+
this.release();
|
|
49
|
+
this.probe = this.make(width, height);
|
|
50
|
+
this.tint = this.make(width, height);
|
|
51
|
+
this.width = width;
|
|
52
|
+
this.height = height;
|
|
53
|
+
}
|
|
54
|
+
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT1, gl.TEXTURE_2D, this.probe, 0);
|
|
55
|
+
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT2, gl.TEXTURE_2D, this.tint, 0);
|
|
56
|
+
gl.drawBuffers(this.all);
|
|
57
|
+
gl.clearBufferfv(gl.COLOR, 1, ZERO);
|
|
58
|
+
gl.clearBufferfv(gl.COLOR, 2, ZERO);
|
|
59
|
+
gl.drawBuffers(this.colourAlone);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Around an opaque lit draw into the frame: its two extra outputs land. */
|
|
63
|
+
on(): void {
|
|
64
|
+
this.gl.drawBuffers(this.all);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** And after it: only the colour does. */
|
|
68
|
+
off(): void {
|
|
69
|
+
this.gl.drawBuffers(this.colourAlone);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** With the scene's framebuffer bound, after the trace has read them: see the header. */
|
|
73
|
+
detach(): void {
|
|
74
|
+
const { gl } = this;
|
|
75
|
+
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT1, gl.TEXTURE_2D, null, 0);
|
|
76
|
+
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT2, gl.TEXTURE_2D, null, 0);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
dispose(): void {
|
|
80
|
+
this.release();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
private make(width: number, height: number): WebGLTexture {
|
|
84
|
+
const { gl } = this;
|
|
85
|
+
const texture = gl.createTexture();
|
|
86
|
+
if (texture === null) throw new Error('ReflectionSurfaceTargets: createTexture failed');
|
|
87
|
+
/* Unit 0, chosen rather than inherited, for the reason `SsrPass` gives. */
|
|
88
|
+
gl.activeTexture(gl.TEXTURE0);
|
|
89
|
+
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
90
|
+
gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RGBA16F, width, height);
|
|
91
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
92
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
93
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
94
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
95
|
+
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
96
|
+
return texture;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
private release(): void {
|
|
100
|
+
if (this.probe !== null) this.gl.deleteTexture(this.probe);
|
|
101
|
+
if (this.tint !== null) this.gl.deleteTexture(this.tint);
|
|
102
|
+
this.probe = null;
|
|
103
|
+
this.tint = null;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/** Construction-time GPU quality controls shared by every renderer resource. */
|
|
2
2
|
|
|
3
|
+
import type { FrameReflections } from './frameReflections.ts';
|
|
3
4
|
import { MAX_AREA_LIGHTS } from './areaLights.ts';
|
|
4
5
|
import { MAX_GLOBAL_MEDIUM_STEPS } from './globalMedium.ts';
|
|
5
6
|
import { MAX_POINT_LIGHTS } from './lightBudget.ts';
|
|
@@ -26,8 +27,14 @@ import { PREFILTER_SAMPLE_COUNTS } from './prefilterEnvMap.ts';
|
|
|
26
27
|
* red where `srgb` clips each channel and turns its core pink and wide. It is the curve a ported
|
|
27
28
|
* game's own resolve applied — for a port that has to match one — and it has none of ACES's toe or
|
|
28
29
|
* desaturation. See `HIGHLIGHT_SHOULDER_GLSL` for the arithmetic.
|
|
30
|
+
*
|
|
31
|
+
* `filmic` is a film curve shaped by five numbers — a slope, a toe, a shoulder and how far black
|
|
32
|
+
* and white clip — that holds a mid grey of 0.18 at 0.18 where `aces` gives about 0.11, so a look
|
|
33
|
+
* graded against such a curve is matched by its numbers (`setFilmicCurve`) rather than by a lookup
|
|
34
|
+
* table. Applied by the composite alone, so it needs `screenEffects` and `hdrScene`; without them
|
|
35
|
+
* every pass grades with `aces` and the renderer says so once. See `filmicCurve.ts`.
|
|
29
36
|
*/
|
|
30
|
-
export type OutputTransform = 'none' | 'srgb' | 'aces' | 'shoulder';
|
|
37
|
+
export type OutputTransform = 'none' | 'srgb' | 'aces' | 'shoulder' | 'filmic';
|
|
31
38
|
|
|
32
39
|
/**
|
|
33
40
|
* The three settings whose accepted values are a closed set, written as one.
|
|
@@ -355,6 +362,18 @@ export interface RenderQuality {
|
|
|
355
362
|
* eight-bit and this buys only the consistent grading.
|
|
356
363
|
*/
|
|
357
364
|
readonly hdrScene: boolean;
|
|
365
|
+
/**
|
|
366
|
+
* Ask for a high dynamic range display: a canvas whose highlights run past paper white to as
|
|
367
|
+
* far as the display allows, where it reports one. Off by default.
|
|
368
|
+
*
|
|
369
|
+
* **Asked for, not assumed.** It needs WebGPU, a display reporting a high dynamic range, and a
|
|
370
|
+
* composite that holds the light to give it (`screenEffects` and `hdrScene`); where any of those
|
|
371
|
+
* is missing the frame goes out as it always did and the renderer says which in
|
|
372
|
+
* `displayRangeReason`. `displayRange` is the answer a game reads to choose a look graded for the
|
|
373
|
+
* output it got. `setDisplayLuminance` sets how far above paper white the highlights may reach.
|
|
374
|
+
* WebGL2 has no extended-range canvas to draw into, so there it is always the standard range.
|
|
375
|
+
*/
|
|
376
|
+
readonly highDynamicRange: boolean;
|
|
358
377
|
/** Camera-depth water tint and scattering across every visible pass. */
|
|
359
378
|
readonly underwaterAtmosphere: boolean;
|
|
360
379
|
/** Procedural noise octaves evaluated by plume shaders. */
|
|
@@ -522,14 +541,14 @@ export interface RenderQuality {
|
|
|
522
541
|
*/
|
|
523
542
|
readonly sceneSamples: number;
|
|
524
543
|
/**
|
|
525
|
-
*
|
|
544
|
+
* Motion blur, 0 to 1. Off by default.
|
|
526
545
|
*
|
|
527
|
-
*
|
|
528
|
-
*
|
|
529
|
-
*
|
|
530
|
-
*
|
|
531
|
-
* needs only the previous view-projection,
|
|
532
|
-
*
|
|
546
|
+
* By the camera's motion everywhere, and **by each drawn object's own motion where a
|
|
547
|
+
* reconstruction draws one** (DriftTR, WebGPU): a mover's pixels smear along its path while a
|
|
548
|
+
* still stage stays sharp. Elsewhere a velocity buffer would be every mesh writing its motion into
|
|
549
|
+
* a second target — a structural change to a forward renderer — so those frames blur by the
|
|
550
|
+
* camera alone, which needs only the previous view-projection, and say so once when a draw names
|
|
551
|
+
* where it was. `setCameraMotionBlur` is the per-frame dial and the longest smear.
|
|
533
552
|
*
|
|
534
553
|
* Runs inside the composite pass, so it costs a depth sample and eight taps on the pixels
|
|
535
554
|
* that are moving and nothing on a still frame. Needs `screenEffects`, since without the
|
|
@@ -580,6 +599,18 @@ export interface RenderQuality {
|
|
|
580
599
|
* Needs `screenEffects`, since the resolve composites over the finished scene.
|
|
581
600
|
*/
|
|
582
601
|
readonly orderIndependent: boolean;
|
|
602
|
+
/**
|
|
603
|
+
* Every opaque lit surface reflects the frame by its own material: a ray marched against the
|
|
604
|
+
* frame's depth swaps the probes' share of each pixel for what it finds, at the pixel's own
|
|
605
|
+
* roughness and reflectance, and a surface past `maxRoughness` keeps the probes alone. Off by
|
|
606
|
+
* default; `true` for the defaults, or the numbers. See `frameReflections.ts`.
|
|
607
|
+
*
|
|
608
|
+
* Needs `screenEffects` and `hdrScene`, since the swap is made in scene light, and a frame of one
|
|
609
|
+
* sample; it says once where it cannot be drawn. What it costs on WebGPU is every opaque lit draw
|
|
610
|
+
* a second time without its lamps, into two half-float targets, and a march per reflective pixel;
|
|
611
|
+
* on WebGL2 the same two targets, written beside the colour by the opaque lit draws themselves.
|
|
612
|
+
*/
|
|
613
|
+
readonly screenSpaceReflections: boolean | FrameReflections;
|
|
583
614
|
/**
|
|
584
615
|
* Depth of field: how wide the blur may reach, as a fraction of the frame's height. Off by
|
|
585
616
|
* default.
|
|
@@ -964,9 +995,11 @@ export const DEFAULT_RENDER_QUALITY: Readonly<RenderQuality> = Object.freeze({
|
|
|
964
995
|
sceneSamples: 1,
|
|
965
996
|
planarReflections: false,
|
|
966
997
|
hdrScene: false,
|
|
998
|
+
highDynamicRange: false,
|
|
967
999
|
cameraMotionBlur: 0,
|
|
968
1000
|
temporalAa: false,
|
|
969
1001
|
orderIndependent: false,
|
|
1002
|
+
screenSpaceReflections: false,
|
|
970
1003
|
depthOfField: 0,
|
|
971
1004
|
reconstruction: 0,
|
|
972
1005
|
indirectLight: false,
|
|
@@ -1126,12 +1159,15 @@ export function resolveRenderQuality(options: RenderQualityOptions = {}): Readon
|
|
|
1126
1159
|
),
|
|
1127
1160
|
planarReflections: options.planarReflections ?? DEFAULT_RENDER_QUALITY.planarReflections,
|
|
1128
1161
|
hdrScene: options.hdrScene ?? DEFAULT_RENDER_QUALITY.hdrScene,
|
|
1162
|
+
highDynamicRange: options.highDynamicRange ?? DEFAULT_RENDER_QUALITY.highDynamicRange,
|
|
1129
1163
|
cameraMotionBlur: Math.min(
|
|
1130
1164
|
1,
|
|
1131
1165
|
Math.max(0, options.cameraMotionBlur ?? DEFAULT_RENDER_QUALITY.cameraMotionBlur),
|
|
1132
1166
|
),
|
|
1133
1167
|
temporalAa: options.temporalAa ?? DEFAULT_RENDER_QUALITY.temporalAa,
|
|
1134
1168
|
orderIndependent: options.orderIndependent ?? DEFAULT_RENDER_QUALITY.orderIndependent,
|
|
1169
|
+
screenSpaceReflections:
|
|
1170
|
+
options.screenSpaceReflections ?? DEFAULT_RENDER_QUALITY.screenSpaceReflections,
|
|
1135
1171
|
/* Off, or a ratio at least 1.3 and at most 2 — never a number between zero and the range. */
|
|
1136
1172
|
reconstruction: resolveReconstruction(options.reconstruction),
|
|
1137
1173
|
indirectLight: options.indirectLight ?? DEFAULT_RENDER_QUALITY.indirectLight,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { glSceneDepthFormat } from './depthConvention.ts';
|
|
2
2
|
import { clampGrain, clampVignette, grainSeed } from './shaders/filmLook.ts';
|
|
3
|
+
import { FRINGE_FLOATS, resolveFringe } from './shaders/fringe.ts';
|
|
3
4
|
import { AmbientOcclusionPass } from './ambientOcclusionPass.ts';
|
|
4
5
|
import { ExposurePass } from './exposurePass.ts';
|
|
5
6
|
import { clampAutoExposure } from './shaders/exposure.ts';
|
|
@@ -99,6 +100,8 @@ export class SceneTarget {
|
|
|
99
100
|
private gradeStrength = 0;
|
|
100
101
|
/** The lens and the print, held like the grade. See `filmLook.ts`. */
|
|
101
102
|
private vignette = 0;
|
|
103
|
+
/** The lens's colour fringe: red's and green's pull and where it begins. See `fringe.ts`. */
|
|
104
|
+
private readonly fringe = new Float32Array(FRINGE_FLOATS);
|
|
102
105
|
private grain = 0;
|
|
103
106
|
private grainSeed = 0;
|
|
104
107
|
/** Eye adaptation: how far, and this frame's time step. See `Renderer.setAutoExposure`. */
|
|
@@ -702,6 +705,11 @@ export class SceneTarget {
|
|
|
702
705
|
this.vignette = clampVignette(strength);
|
|
703
706
|
}
|
|
704
707
|
|
|
708
|
+
/** The lens's colour fringe, held until changed. See `Renderer.setChromaticAberration`. */
|
|
709
|
+
setChromaticAberration(intensity: number, start: number): void {
|
|
710
|
+
resolveFringe(intensity, start, this.fringe);
|
|
711
|
+
}
|
|
712
|
+
|
|
705
713
|
/** The print's grain and this frame's seed, held until changed. See `Renderer.setFilmGrain`. */
|
|
706
714
|
setFilmGrain(strength: number, seed: number): void {
|
|
707
715
|
this.grain = clampGrain(strength);
|
|
@@ -769,8 +777,15 @@ export class SceneTarget {
|
|
|
769
777
|
resolve(
|
|
770
778
|
strength: number,
|
|
771
779
|
reachUv: number,
|
|
772
|
-
/*
|
|
773
|
-
|
|
780
|
+
/*
|
|
781
|
+
* The grade, applied here because this is the last pass. See RUSH_FRAG's own note. `film` is
|
|
782
|
+
* the `filmic` curve's eight constants (`resolveFilmicCurve`), read only under transform 4.
|
|
783
|
+
*/
|
|
784
|
+
grade: {
|
|
785
|
+
readonly transform: number;
|
|
786
|
+
readonly exposure: number;
|
|
787
|
+
readonly film?: Float32Array;
|
|
788
|
+
} = {
|
|
774
789
|
transform: 0,
|
|
775
790
|
exposure: 1,
|
|
776
791
|
},
|
|
@@ -1012,6 +1027,12 @@ export class SceneTarget {
|
|
|
1012
1027
|
gl.uniform1f(this.uniforms['uReach'] ?? null, reachUv);
|
|
1013
1028
|
gl.uniform1i(this.uniforms['uOutputTransform'] ?? null, grade.transform);
|
|
1014
1029
|
gl.uniform1f(this.uniforms['uOutputExposure'] ?? null, grade.exposure);
|
|
1030
|
+
if (grade.film !== undefined) {
|
|
1031
|
+
gl.uniform4fv(this.uniforms['uFilmA'] ?? null, grade.film, 0, 4);
|
|
1032
|
+
gl.uniform4fv(this.uniforms['uFilmB'] ?? null, grade.film, 4, 4);
|
|
1033
|
+
}
|
|
1034
|
+
/* A standard range always here: see `Renderer.displayRange`. */
|
|
1035
|
+
gl.uniform1f(this.uniforms['uDisplayHeadroom'] ?? null, 1);
|
|
1015
1036
|
|
|
1016
1037
|
/*
|
|
1017
1038
|
* Depth on its own unit, and the reprojection with it. Bound every frame rather than
|
|
@@ -1113,6 +1134,12 @@ export class SceneTarget {
|
|
|
1113
1134
|
this.uniforms['uLocalExposure'] ?? null,
|
|
1114
1135
|
localGrid === null ? 0 : this.localExposure,
|
|
1115
1136
|
);
|
|
1137
|
+
/* Each object's own motion is WebGPU's under a reconstruction; here the scene stands in on
|
|
1138
|
+
unit 7 and the flag says not to read it, so the camera's motion alone blurs. */
|
|
1139
|
+
gl.activeTexture(gl.TEXTURE7);
|
|
1140
|
+
gl.bindTexture(gl.TEXTURE_2D, scene);
|
|
1141
|
+
gl.uniform1i(this.uniforms['uMotion'] ?? null, 7);
|
|
1142
|
+
gl.uniform1f(this.uniforms['uObjectMotion'] ?? null, 0);
|
|
1116
1143
|
gl.activeTexture(gl.TEXTURE0);
|
|
1117
1144
|
|
|
1118
1145
|
/* No unit and no texture: a flat colour, not a sample. Uploaded unconditionally — two
|
|
@@ -1122,6 +1149,7 @@ export class SceneTarget {
|
|
|
1122
1149
|
gl.uniform3fv(this.uniforms['uVeilColor'] ?? null, veilColor);
|
|
1123
1150
|
gl.uniform1f(this.uniforms['uVeilAlpha'] ?? null, veilAlpha);
|
|
1124
1151
|
gl.uniform1f(this.uniforms['uVignette'] ?? null, this.vignette);
|
|
1152
|
+
gl.uniform3fv(this.uniforms['uFringe'] ?? null, this.fringe);
|
|
1125
1153
|
gl.uniform2f(this.uniforms['uGrain'] ?? null, this.grain, this.grainSeed);
|
|
1126
1154
|
|
|
1127
1155
|
gl.bindVertexArray(this.vao);
|
|
@@ -27,6 +27,11 @@ import type { DecalBox } from './decalProjector.ts';
|
|
|
27
27
|
* which is the same price the temporal row declined for a velocity buffer. A caller declares a
|
|
28
28
|
* `ReflectiveSurface` instead: a box, and a facing rule for which surfaces inside it reflect. It is
|
|
29
29
|
* the shape `DecalProjector` already has, for the same reason.
|
|
30
|
+
*
|
|
31
|
+
* **Or every surface by its own material**, where the renderer was built with
|
|
32
|
+
* `screenSpaceReflections`: the lit stage leaves two maps of what it reflected — not a G-buffer, the
|
|
33
|
+
* environment's share and its tint, which is all a swap needs — and the same trace runs in a
|
|
34
|
+
* material mode over every pixel. See `frameReflections.ts`.
|
|
30
35
|
*/
|
|
31
36
|
|
|
32
37
|
/**
|
|
@@ -365,7 +370,8 @@ export interface ReflectiveSurfaceOptions extends DecalBox {
|
|
|
365
370
|
* box. Each pixel then returns `F0 · A + B` of what its ray finds, the split-sum environment BRDF
|
|
366
371
|
* at its own view and `roughness` — Karis's fit, the one the lit stage reflects its environment
|
|
367
372
|
* by — so a floor returns more toward the horizon than underfoot, and the share follows the
|
|
368
|
-
* camera as
|
|
373
|
+
* camera as a physically based renderer weighs its reflections. **False by default**, the one
|
|
374
|
+
* share as before.
|
|
369
375
|
*
|
|
370
376
|
* **What it gives up**: the pass has no material buffer, so the roughness and F0 are the box's,
|
|
371
377
|
* not each pixel's, and nothing occludes the reflection where the lit stage's ambient occlusion
|
|
@@ -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
|
|
|
@@ -88,7 +88,8 @@ export function grainWeight(luma: number): number {
|
|
|
88
88
|
|
|
89
89
|
/** Both backends' words when there is no composite to apply the look in. */
|
|
90
90
|
export const FILM_LOOK_WITHOUT_COMPOSITE =
|
|
91
|
-
'[driftengine] setVignette and
|
|
91
|
+
'[driftengine] setVignette, setFilmGrain and setChromaticAberration need `screenEffects`: ' +
|
|
92
|
+
'without a composite every ' +
|
|
92
93
|
'pass is the last thing to touch the frame, so there is no one place to apply a lens or a ' +
|
|
93
94
|
'print. The look was not applied.';
|
|
94
95
|
|
|
@@ -34,7 +34,9 @@ export type LitSwitch =
|
|
|
34
34
|
| 'LIGHT_FIXTURES'
|
|
35
35
|
| 'SURFACE_EFFECTS'
|
|
36
36
|
| 'DRIFT_LIGHT'
|
|
37
|
-
| 'PHYSICAL_SPECULAR'
|
|
37
|
+
| 'PHYSICAL_SPECULAR'
|
|
38
|
+
| 'SURFACE_OVERLAY'
|
|
39
|
+
| 'REFLECTION_MAPS';
|
|
38
40
|
|
|
39
41
|
/** Every switch off: what a renderer starts from before its profile and its content say otherwise. */
|
|
40
42
|
export function noLitSwitches(): Record<LitSwitch, boolean> {
|
|
@@ -45,6 +47,8 @@ export function noLitSwitches(): Record<LitSwitch, boolean> {
|
|
|
45
47
|
SURFACE_EFFECTS: false,
|
|
46
48
|
DRIFT_LIGHT: false,
|
|
47
49
|
PHYSICAL_SPECULAR: false,
|
|
50
|
+
SURFACE_OVERLAY: false,
|
|
51
|
+
REFLECTION_MAPS: false,
|
|
48
52
|
};
|
|
49
53
|
}
|
|
50
54
|
|
|
@@ -19,7 +19,10 @@ import { AREA_LIGHT_GLSL } from './areaLight.ts';
|
|
|
19
19
|
import { NORMAL_MAP_GLSL } from './normalMap.ts';
|
|
20
20
|
import { DRIFT_LIGHT_GLSL } from './driftLight.ts';
|
|
21
21
|
import { SURFACE_EFFECTS_GLSL } from './surfaceEffects.ts';
|
|
22
|
-
import {
|
|
22
|
+
import { overlayGlsl } from './overlay.ts';
|
|
23
|
+
import { reflectionSurfaceGlsl } from './reflectionSurface.ts';
|
|
24
|
+
import { CHANNEL_BEND, LIT_CHANNEL_ATTRIBUTE } from '../vertexChannel.ts';
|
|
25
|
+
import { BONE_ANIMATION_GLSL } from '../boneAnimation.ts';
|
|
23
26
|
import { FULL_LIGHT_BUDGET, type LightBudget } from '../../uniformVectorBudget.ts';
|
|
24
27
|
|
|
25
28
|
/**
|
|
@@ -54,10 +57,16 @@ layout(location = 10) in vec4 aTangent;
|
|
|
54
57
|
${SKINNING_GLSL}
|
|
55
58
|
#endif
|
|
56
59
|
|
|
57
|
-
uniform mat4 uViewProj;
|
|
60
|
+
uniform mat4 uViewProj; // wgsl:view
|
|
58
61
|
/** 1 when the mesh carries a tangent frame. See vHasTangents. */
|
|
59
62
|
uniform int uHasTangents;
|
|
60
|
-
uniform mat4 uLightViewProj;
|
|
63
|
+
uniform mat4 uLightViewProj; // wgsl:view
|
|
64
|
+
/**
|
|
65
|
+
* The scene's clock, what \`setAnimationTime\` set: what a bone animation's instances read
|
|
66
|
+
* their moment from. In the view block, before the wind, so every variant's view block is the
|
|
67
|
+
* plain one's or a prefix of it — the instanced variant declares no wind and keeps this.
|
|
68
|
+
*/
|
|
69
|
+
uniform float uSceneTime; // wgsl:view
|
|
61
70
|
/**
|
|
62
71
|
* How often the surface texture repeats across this mesh's UV range, per axis.
|
|
63
72
|
*
|
|
@@ -120,6 +129,9 @@ layout(location = 15) in vec4 aInstanceTint;
|
|
|
120
129
|
* opacity of one. See lightmap.ts.
|
|
121
130
|
*/
|
|
122
131
|
const bool LIGHTMAP_REGIONS = false; // wgsl:override
|
|
132
|
+
#if ANIMATED
|
|
133
|
+
${BONE_ANIMATION_GLSL}
|
|
134
|
+
#endif
|
|
123
135
|
#else
|
|
124
136
|
uniform mat4 uModel;
|
|
125
137
|
/**
|
|
@@ -145,7 +157,7 @@ uniform vec3 uTint;
|
|
|
145
157
|
* agreeing about where the shared uniforms sit: the instanced variant drops these five along with
|
|
146
158
|
* the two above it, and a dropped field moves nothing. flatPass.ts asserts exactly that.
|
|
147
159
|
*/
|
|
148
|
-
${
|
|
160
|
+
${LIT_CHANNEL_ATTRIBUTE}
|
|
149
161
|
${CHANNEL_BEND}
|
|
150
162
|
#endif
|
|
151
163
|
|
|
@@ -243,6 +255,10 @@ void main() {
|
|
|
243
255
|
vec3 localNormal = aNormal;
|
|
244
256
|
vec3 localTangent = aTangent.xyz;
|
|
245
257
|
#endif
|
|
258
|
+
#if ANIMATED
|
|
259
|
+
/* The clip's turn and place, in the mesh's own space, before the instance places it. */
|
|
260
|
+
local = vec4(boneAnimate(local.xyz, localNormal, localTangent), 1.0);
|
|
261
|
+
#endif
|
|
246
262
|
#if INSTANCED
|
|
247
263
|
mat4 model = mat4(aInstanceModel0, aInstanceModel1, aInstanceModel2, aInstanceModel3);
|
|
248
264
|
/*
|
|
@@ -377,6 +393,12 @@ export interface FlatVertexOptions {
|
|
|
377
393
|
* Excludes `skinned`: the joint attributes and the instance matrix want the same locations.
|
|
378
394
|
*/
|
|
379
395
|
readonly instanced: boolean;
|
|
396
|
+
/**
|
|
397
|
+
* Whether an instanced variant follows a bone animation: \`shaders/boneAnimation.ts\`. A
|
|
398
|
+
* variant rather than a pipeline constant, because it declares three textures the other
|
|
399
|
+
* instanced pipelines would otherwise have to bind stand-ins for. Instanced only.
|
|
400
|
+
*/
|
|
401
|
+
readonly animated?: boolean;
|
|
380
402
|
}
|
|
381
403
|
|
|
382
404
|
/**
|
|
@@ -399,9 +421,17 @@ export function flatVert(options: FlatVertexOptions): string {
|
|
|
399
421
|
'so every instance of the batch would wear one expression between them.',
|
|
400
422
|
);
|
|
401
423
|
}
|
|
424
|
+
if (options.animated === true && !options.instanced) {
|
|
425
|
+
throw new Error('flatVert: a bone animation is played by an instanced variant alone.');
|
|
426
|
+
}
|
|
402
427
|
return resolveConditionals(
|
|
403
428
|
FLAT_VERT_SOURCE,
|
|
404
|
-
{
|
|
429
|
+
{
|
|
430
|
+
SKINNED: options.skinned,
|
|
431
|
+
MORPHED: options.morphed,
|
|
432
|
+
INSTANCED: options.instanced,
|
|
433
|
+
ANIMATED: options.animated === true,
|
|
434
|
+
},
|
|
405
435
|
'flatVert',
|
|
406
436
|
);
|
|
407
437
|
}
|
|
@@ -468,6 +498,16 @@ export interface FlatShaderOptions {
|
|
|
468
498
|
* when absent. See `modelsGlsl`.
|
|
469
499
|
*/
|
|
470
500
|
readonly physicalSpecular?: boolean;
|
|
501
|
+
/**
|
|
502
|
+
* Whether it carries a draw's surface overlay, `uOverlay` and all (`setSurfaceOverlay`). True
|
|
503
|
+
* when absent. See `overlayGlsl`.
|
|
504
|
+
*/
|
|
505
|
+
readonly surfaceOverlay?: boolean;
|
|
506
|
+
/**
|
|
507
|
+
* Whether the frame's own draws write the reflection maps beside their colour: WebGL2's way to
|
|
508
|
+
* the frame's materials' reflections. True when absent. See `reflectionSurfaceGlsl`.
|
|
509
|
+
*/
|
|
510
|
+
readonly reflectionMaps?: boolean;
|
|
471
511
|
/**
|
|
472
512
|
* How many point lights this build declares room for. `MAX_POINT_LIGHTS` when absent.
|
|
473
513
|
*
|
|
@@ -613,6 +653,10 @@ export function flatFrag(options: FlatShaderOptions): string {
|
|
|
613
653
|
SURFACE_EFFECTS_GLSL,
|
|
614
654
|
/* Depth zero and after the tangent frame and the lobes it calls; see models.ts. */
|
|
615
655
|
modelsGlsl(options.physicalSpecular ?? true),
|
|
656
|
+
/* After the models, so its switch takes the next id; depth zero, as main calls it. */
|
|
657
|
+
overlayGlsl(options.surfaceOverlay ?? true),
|
|
658
|
+
/* After the overlay, so its switch takes the next id. See reflectionSurface.ts. */
|
|
659
|
+
reflectionSurfaceGlsl(options.reflectionMaps ?? true),
|
|
616
660
|
/* After the models, whose answer to a rectangle it asks for. See areaLight.ts. */
|
|
617
661
|
AREA_LIGHT_GLSL,
|
|
618
662
|
MAIN_GLSL,
|