@driftengine/core 4.13.4 → 4.13.5
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 +36 -0
- package/README.md +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/render/anisotropicLobe.d.ts +5 -0
- package/dist/render/anisotropicLobe.js +13 -0
- package/dist/render/atmosphere.d.ts +79 -1
- package/dist/render/atmosphere.js +66 -19
- package/dist/render/backend/webgl2/renderer.d.ts +34 -2
- package/dist/render/backend/webgl2/renderer.js +44 -12
- package/dist/render/backend/webgpu/boltPass.d.ts +1 -1
- package/dist/render/backend/webgpu/causticsPass.d.ts +1 -1
- package/dist/render/backend/webgpu/filmPass.d.ts +1 -1
- package/dist/render/backend/webgpu/gpuDrivenPass.js +20 -3
- package/dist/render/backend/webgpu/linePass.d.ts +1 -1
- package/dist/render/backend/webgpu/mediumFields.d.ts +17 -0
- package/dist/render/backend/webgpu/mediumFields.js +74 -0
- package/dist/render/backend/webgpu/plumePass.d.ts +3 -3
- package/dist/render/backend/webgpu/postPass.d.ts +7 -2
- package/dist/render/backend/webgpu/renderer.d.ts +13 -3
- package/dist/render/backend/webgpu/renderer.js +86 -150
- package/dist/render/backend/webgpu/scatterPass.d.ts +1 -1
- package/dist/render/backend/webgpu/waterPass.d.ts +1 -1
- package/dist/render/environmentMixing.d.ts +18 -0
- package/dist/render/environmentMixing.js +40 -0
- package/dist/render/fog.d.ts +43 -1
- package/dist/render/fog.js +87 -22
- package/dist/render/globalMedium.d.ts +112 -10
- package/dist/render/globalMedium.js +96 -1
- package/dist/render/globalMediumPass.d.ts +7 -3
- package/dist/render/globalMediumPass.js +22 -1
- package/dist/render/hairLobes.d.ts +5 -3
- package/dist/render/hairLobes.js +11 -7
- package/dist/render/lightBudget.d.ts +12 -0
- package/dist/render/lightBudget.js +24 -0
- package/dist/render/sceneTarget.d.ts +5 -3
- package/dist/render/sceneTarget.js +14 -8
- package/dist/render/shaders/arcane.d.ts +1 -1
- package/dist/render/shaders/bolt.d.ts +1 -1
- package/dist/render/shaders/caustics.d.ts +1 -1
- package/dist/render/shaders/film.d.ts +1 -1
- package/dist/render/shaders/film.js +4 -1
- package/dist/render/shaders/fire.d.ts +1 -1
- package/dist/render/shaders/flat/anisotropic.d.ts +8 -1
- package/dist/render/shaders/flat/anisotropic.js +25 -3
- package/dist/render/shaders/flat/hair.js +31 -7
- package/dist/render/shaders/flat/main.d.ts +1 -1
- package/dist/render/shaders/flat/main.js +20 -1
- package/dist/render/shaders/flat/models.js +1 -1
- package/dist/render/shaders/flat/preamble.js +7 -0
- package/dist/render/shaders/fog.d.ts +4 -4
- package/dist/render/shaders/fog.js +81 -32
- package/dist/render/shaders/generated/arcane.wgsl.d.ts +29 -39
- package/dist/render/shaders/generated/arcane.wgsl.js +29 -39
- package/dist/render/shaders/generated/bolt.wgsl.d.ts +26 -36
- package/dist/render/shaders/generated/bolt.wgsl.js +26 -36
- package/dist/render/shaders/generated/caustics.wgsl.d.ts +25 -35
- package/dist/render/shaders/generated/caustics.wgsl.js +25 -35
- package/dist/render/shaders/generated/film.wgsl.d.ts +28 -38
- package/dist/render/shaders/generated/film.wgsl.js +28 -38
- package/dist/render/shaders/generated/fire.wgsl.d.ts +28 -38
- package/dist/render/shaders/generated/fire.wgsl.js +28 -38
- package/dist/render/shaders/generated/flat.wgsl.d.ts +1466 -1546
- package/dist/render/shaders/generated/flat.wgsl.js +1489 -1569
- package/dist/render/shaders/generated/globalMedium.wgsl.d.ts +98 -12
- package/dist/render/shaders/generated/globalMedium.wgsl.js +98 -12
- package/dist/render/shaders/generated/line.wgsl.d.ts +25 -35
- package/dist/render/shaders/generated/line.wgsl.js +25 -35
- package/dist/render/shaders/generated/particle.wgsl.d.ts +100 -140
- package/dist/render/shaders/generated/particle.wgsl.js +100 -140
- package/dist/render/shaders/generated/rush.wgsl.d.ts +20 -10
- package/dist/render/shaders/generated/rush.wgsl.js +20 -10
- package/dist/render/shaders/generated/scatter.wgsl.d.ts +25 -35
- package/dist/render/shaders/generated/scatter.wgsl.js +25 -35
- package/dist/render/shaders/generated/smoke.wgsl.d.ts +28 -38
- package/dist/render/shaders/generated/smoke.wgsl.js +28 -38
- package/dist/render/shaders/generated/water.wgsl.d.ts +29 -39
- package/dist/render/shaders/generated/water.wgsl.js +29 -39
- package/dist/render/shaders/globalMedium.js +114 -10
- package/dist/render/shaders/gpudriven/blendRaster.wgsl.js +2 -1
- package/dist/render/shaders/gpudriven/fog.wgsl.d.ts +10 -4
- package/dist/render/shaders/gpudriven/fog.wgsl.js +77 -19
- package/dist/render/shaders/gpudriven/frameBlock.wgsl.d.ts +1 -1
- package/dist/render/shaders/gpudriven/frameBlock.wgsl.js +12 -1
- package/dist/render/shaders/gpudriven/shade.wgsl.js +3 -1
- package/dist/render/shaders/line.d.ts +1 -1
- package/dist/render/shaders/line.js +4 -2
- package/dist/render/shaders/localExposure.d.ts +42 -1
- package/dist/render/shaders/localExposure.js +73 -6
- package/dist/render/shaders/particle.d.ts +3 -3
- package/dist/render/shaders/particle.js +10 -6
- package/dist/render/shaders/scatter.d.ts +1 -1
- package/dist/render/shaders/scatter.js +4 -2
- package/dist/render/shaders/smoke.d.ts +1 -1
- package/dist/render/shaders/water.d.ts +1 -1
- package/dist/render/shaders/water.js +2 -1
- package/dist/render/surfaceModel.d.ts +23 -4
- package/dist/render/surfaceModel.js +12 -2
- package/package.json +6 -6
- package/src/index.ts +12 -2
- package/src/render/anisotropicLobe.ts +20 -0
- package/src/render/atmosphere.ts +153 -20
- package/src/render/backend/webgl2/renderer.ts +63 -13
- package/src/render/backend/webgpu/gpuDrivenPass.ts +20 -3
- package/src/render/backend/webgpu/mediumFields.ts +87 -0
- package/src/render/backend/webgpu/renderer.ts +109 -157
- package/src/render/environmentMixing.ts +48 -0
- package/src/render/fog.ts +125 -25
- package/src/render/globalMedium.ts +214 -11
- package/src/render/globalMediumPass.ts +29 -4
- package/src/render/hairLobes.ts +35 -4
- package/src/render/lightBudget.ts +32 -0
- package/src/render/sceneTarget.ts +15 -11
- package/src/render/shaders/film.ts +4 -1
- package/src/render/shaders/flat/anisotropic.ts +25 -3
- package/src/render/shaders/flat/hair.ts +31 -7
- package/src/render/shaders/flat/main.ts +20 -1
- package/src/render/shaders/flat/models.ts +1 -1
- package/src/render/shaders/flat/preamble.ts +7 -0
- package/src/render/shaders/fog.ts +81 -32
- package/src/render/shaders/generated/arcane.wgsl.ts +29 -39
- package/src/render/shaders/generated/bolt.wgsl.ts +26 -36
- package/src/render/shaders/generated/caustics.wgsl.ts +25 -35
- package/src/render/shaders/generated/film.wgsl.ts +28 -38
- package/src/render/shaders/generated/fire.wgsl.ts +28 -38
- package/src/render/shaders/generated/flat.wgsl.ts +1489 -1569
- package/src/render/shaders/generated/globalMedium.wgsl.ts +98 -12
- package/src/render/shaders/generated/line.wgsl.ts +25 -35
- package/src/render/shaders/generated/particle.wgsl.ts +100 -140
- package/src/render/shaders/generated/rush.wgsl.ts +20 -10
- package/src/render/shaders/generated/scatter.wgsl.ts +25 -35
- package/src/render/shaders/generated/smoke.wgsl.ts +28 -38
- package/src/render/shaders/generated/water.wgsl.ts +29 -39
- package/src/render/shaders/globalMedium.ts +114 -10
- package/src/render/shaders/gpudriven/blendRaster.wgsl.ts +2 -1
- package/src/render/shaders/gpudriven/fog.wgsl.ts +78 -19
- package/src/render/shaders/gpudriven/frameBlock.wgsl.ts +12 -1
- package/src/render/shaders/gpudriven/shade.wgsl.ts +3 -1
- package/src/render/shaders/line.ts +4 -2
- package/src/render/shaders/localExposure.ts +115 -6
- package/src/render/shaders/particle.ts +10 -6
- package/src/render/shaders/scatter.ts +4 -2
- package/src/render/shaders/water.ts +2 -1
- package/src/render/surfaceModel.ts +41 -6
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/** A field's byte offset in the block, or -1 where the shader compiled it out. */
|
|
2
|
+
function placed(fields, name) {
|
|
3
|
+
return fields[name]?.offset ?? -1;
|
|
4
|
+
}
|
|
5
|
+
/** Into a block staged as floats, indexed in four-byte words. */
|
|
6
|
+
export function writeMediumFields(fields, f, m) {
|
|
7
|
+
let at = placed(fields, 'uFogColor');
|
|
8
|
+
if (at >= 0)
|
|
9
|
+
f.set(m.fogColor, at / 4);
|
|
10
|
+
at = placed(fields, 'uFogMedium');
|
|
11
|
+
if (at >= 0) {
|
|
12
|
+
f[at / 4] = m.fogDensity;
|
|
13
|
+
f[at / 4 + 1] = m.fogHeightFalloff;
|
|
14
|
+
f[at / 4 + 2] = m.fogEyeY;
|
|
15
|
+
f[at / 4 + 3] = m.underwaterFogDensity;
|
|
16
|
+
}
|
|
17
|
+
at = placed(fields, 'uFogRange');
|
|
18
|
+
if (at >= 0) {
|
|
19
|
+
f[at / 4] = m.fogNear;
|
|
20
|
+
f[at / 4 + 1] = m.fogFar;
|
|
21
|
+
f[at / 4 + 2] = m.fogMode;
|
|
22
|
+
f[at / 4 + 3] = 0;
|
|
23
|
+
}
|
|
24
|
+
at = placed(fields, 'uUnderwaterColor');
|
|
25
|
+
if (at >= 0)
|
|
26
|
+
f.set(m.underwaterColor, at / 4);
|
|
27
|
+
at = placed(fields, 'uUnderwaterFactor');
|
|
28
|
+
if (at >= 0)
|
|
29
|
+
f[at / 4] = m.underwaterFactor;
|
|
30
|
+
at = placed(fields, 'uFogLayer2');
|
|
31
|
+
if (at >= 0)
|
|
32
|
+
f.set(m.fogLayer2, at / 4);
|
|
33
|
+
at = placed(fields, 'uFogGlow');
|
|
34
|
+
if (at >= 0)
|
|
35
|
+
f.set(m.fogGlow, at / 4);
|
|
36
|
+
at = placed(fields, 'uFogGlowDir');
|
|
37
|
+
if (at >= 0)
|
|
38
|
+
f.set(m.fogGlowDir, at / 4);
|
|
39
|
+
}
|
|
40
|
+
/** Into one slot of a ring, at the fields' byte offsets. */
|
|
41
|
+
export function writeMediumSlot(ring, slot, fields, m) {
|
|
42
|
+
let at = placed(fields, 'uFogColor');
|
|
43
|
+
if (at >= 0)
|
|
44
|
+
ring.writeFloats(slot, at, m.fogColor);
|
|
45
|
+
at = placed(fields, 'uFogMedium');
|
|
46
|
+
if (at >= 0) {
|
|
47
|
+
ring.writeFloat(slot, at, m.fogDensity);
|
|
48
|
+
ring.writeFloat(slot, at + 4, m.fogHeightFalloff);
|
|
49
|
+
ring.writeFloat(slot, at + 8, m.fogEyeY);
|
|
50
|
+
ring.writeFloat(slot, at + 12, m.underwaterFogDensity);
|
|
51
|
+
}
|
|
52
|
+
at = placed(fields, 'uFogRange');
|
|
53
|
+
if (at >= 0) {
|
|
54
|
+
ring.writeFloat(slot, at, m.fogNear);
|
|
55
|
+
ring.writeFloat(slot, at + 4, m.fogFar);
|
|
56
|
+
ring.writeFloat(slot, at + 8, m.fogMode);
|
|
57
|
+
ring.writeFloat(slot, at + 12, 0);
|
|
58
|
+
}
|
|
59
|
+
at = placed(fields, 'uUnderwaterColor');
|
|
60
|
+
if (at >= 0)
|
|
61
|
+
ring.writeFloats(slot, at, m.underwaterColor);
|
|
62
|
+
at = placed(fields, 'uUnderwaterFactor');
|
|
63
|
+
if (at >= 0)
|
|
64
|
+
ring.writeFloat(slot, at, m.underwaterFactor);
|
|
65
|
+
at = placed(fields, 'uFogLayer2');
|
|
66
|
+
if (at >= 0)
|
|
67
|
+
ring.writeFloats(slot, at, m.fogLayer2);
|
|
68
|
+
at = placed(fields, 'uFogGlow');
|
|
69
|
+
if (at >= 0)
|
|
70
|
+
ring.writeFloats(slot, at, m.fogGlow);
|
|
71
|
+
at = placed(fields, 'uFogGlowDir');
|
|
72
|
+
if (at >= 0)
|
|
73
|
+
ring.writeFloats(slot, at, m.fogGlowDir);
|
|
74
|
+
}
|
|
@@ -15,9 +15,9 @@ export declare const PLUME_VERT_SIZE: 112;
|
|
|
15
15
|
export declare const PLUME_FRAG_FIELDS: UniformFields;
|
|
16
16
|
export declare const PLUME_FRAG_SIZE: number;
|
|
17
17
|
/** Each material's own block, so a change to one and not the others is caught rather than assumed. */
|
|
18
|
-
export declare const FIRE_FRAG_SIZE:
|
|
19
|
-
export declare const SMOKE_FRAG_SIZE:
|
|
20
|
-
export declare const ARCANE_FRAG_SIZE:
|
|
18
|
+
export declare const FIRE_FRAG_SIZE: 176;
|
|
19
|
+
export declare const SMOKE_FRAG_SIZE: 176;
|
|
20
|
+
export declare const ARCANE_FRAG_SIZE: 192;
|
|
21
21
|
export declare function plumeVertexLayouts(): GPUVertexBufferLayout[];
|
|
22
22
|
/** Plume geometry on the device, behind the surface's opaque handle. */
|
|
23
23
|
export interface GpuPlumes {
|
|
@@ -26,7 +26,7 @@ import type { PipelineCache } from './pipelineCache.ts';
|
|
|
26
26
|
* float target the generated shaders can sample as an ordinary texture.
|
|
27
27
|
*/
|
|
28
28
|
export declare const RUSH_FRAG_FIELDS: UniformFields;
|
|
29
|
-
export declare const RUSH_FRAG_SIZE:
|
|
29
|
+
export declare const RUSH_FRAG_SIZE: 320;
|
|
30
30
|
declare const RUSH_UNIFORMS: 1;
|
|
31
31
|
declare const RUSH_TEXTURES: {
|
|
32
32
|
readonly uScene: {
|
|
@@ -75,7 +75,7 @@ export declare const AO_FRAG_SIZE: 96;
|
|
|
75
75
|
export declare const AO_BLUR_FIELDS: UniformFields;
|
|
76
76
|
export declare const AO_BLUR_SIZE: 48;
|
|
77
77
|
export declare const MEDIUM_FRAG_FIELDS: UniformFields;
|
|
78
|
-
export declare const MEDIUM_FRAG_SIZE:
|
|
78
|
+
export declare const MEDIUM_FRAG_SIZE: 2400;
|
|
79
79
|
export declare const MEDIUM_UPSAMPLE_FIELDS: UniformFields;
|
|
80
80
|
export declare const MEDIUM_UPSAMPLE_SIZE: 48;
|
|
81
81
|
export declare const BLOOM_PREFILTER_FIELDS: UniformFields;
|
|
@@ -369,6 +369,11 @@ export declare const MEDIUM_TEXTURES: {
|
|
|
369
369
|
readonly sampler: 35;
|
|
370
370
|
readonly type: "sampler2DArray";
|
|
371
371
|
};
|
|
372
|
+
readonly uPointShadows: {
|
|
373
|
+
readonly texture: 36;
|
|
374
|
+
readonly sampler: 37;
|
|
375
|
+
readonly type: "sampler2DArray";
|
|
376
|
+
};
|
|
372
377
|
};
|
|
373
378
|
export declare const MEDIUM_UPSAMPLE_UNIFORMS: 1;
|
|
374
379
|
export declare const MEDIUM_UPSAMPLE_TEXTURES: {
|
|
@@ -35,6 +35,7 @@ import type { SurfaceMaterial, SurfaceTextureOptions } from '../../surfaceTextur
|
|
|
35
35
|
import type { RenderBackend } from '../api.ts';
|
|
36
36
|
import { type DisplayRange } from '../../displayRange.ts';
|
|
37
37
|
import { type FilmicCurve } from '../../filmicCurve.ts';
|
|
38
|
+
import type { LocalExposureOptions } from '../../shaders/localExposure.ts';
|
|
38
39
|
import { type ColourGradeLut } from '../../colourGrade.ts';
|
|
39
40
|
import type { CausticSheet } from '../../causticsRenderer.ts';
|
|
40
41
|
import { type GpuCaustics } from './causticsPass.ts';
|
|
@@ -45,6 +46,7 @@ import type { DeviceParticles, ParticleInstances } from '../../particlePool.ts';
|
|
|
45
46
|
import type { PlumeOptions, PlumePlacement } from '../../plumeRenderer.ts';
|
|
46
47
|
import type { InstanceData } from '../../instancedMesh.ts';
|
|
47
48
|
import { type RenderQuality } from '../../renderQuality.ts';
|
|
49
|
+
import type { GlobalMediumSettings } from '../../globalMedium.ts';
|
|
48
50
|
import type { MeshData } from '../../mesh.ts';
|
|
49
51
|
import type { ShadowCasters } from '../../shadowCasters.ts';
|
|
50
52
|
import { type GpuMesh } from './buffers.ts';
|
|
@@ -724,6 +726,9 @@ export declare class WebGPURenderer implements RendererApi {
|
|
|
724
726
|
private readonly mediumInvProjection;
|
|
725
727
|
/** This frame's medium. Off until a caller says otherwise. See `setGlobalMedium`. */
|
|
726
728
|
private mediumOptions;
|
|
729
|
+
/** The lamps the medium is lit by, and the lit stage's lamps they come from, refilled a frame. */
|
|
730
|
+
private readonly mediumLamps;
|
|
731
|
+
private readonly mediumLights;
|
|
727
732
|
/**
|
|
728
733
|
* The temporal resolve: its block, its ping-pong pair, and the jitter state.
|
|
729
734
|
*
|
|
@@ -1412,6 +1417,10 @@ export declare class WebGPURenderer implements RendererApi {
|
|
|
1412
1417
|
setSurfaceReflectivity(amount: number): void;
|
|
1413
1418
|
/** How bright the environment the surfaces drawn next reflect is. See `renderer.ts`. */
|
|
1414
1419
|
setEnvironmentGain(gain: number): void;
|
|
1420
|
+
/** The environment brought to the light where a surface stands. See `renderer.ts`. */
|
|
1421
|
+
setEnvironmentMixing(weight: number, roughnessLow?: number, roughnessHigh?: number): void;
|
|
1422
|
+
/** `uEnvironmentMixing` as it stands; none until a draw asks. See `setEnvironmentMixing`. */
|
|
1423
|
+
private readonly environmentMixing;
|
|
1415
1424
|
/**
|
|
1416
1425
|
* The reflectivity and environment gain the setters gave the pass, and the ones the material
|
|
1417
1426
|
* set now states, or null where it states none (`SurfaceMaterial.reflectivity`). A draw wears the
|
|
@@ -3980,8 +3989,9 @@ export declare class WebGPURenderer implements RendererApi {
|
|
|
3980
3989
|
/** Eye adaptation: how far, this frame's time step, and the pass once asked for. */
|
|
3981
3990
|
private autoExposure;
|
|
3982
3991
|
private autoExposureDt;
|
|
3983
|
-
/**
|
|
3992
|
+
/** Whether regions move, and how, as `resolveLocalExposure` packs it. See `setLocalExposure`. */
|
|
3984
3993
|
private localExposure;
|
|
3994
|
+
private readonly localExposureShape;
|
|
3985
3995
|
private exposurePass;
|
|
3986
3996
|
/**
|
|
3987
3997
|
* How strongly the lens darkens the frame's corners, held until changed: 0 is none, 0.5 is about
|
|
@@ -4039,7 +4049,7 @@ export declare class WebGPURenderer implements RendererApi {
|
|
|
4039
4049
|
* version is that `density` is extinction per metre, 0 is a real off that allocates nothing and
|
|
4040
4050
|
* draws nothing, and the three optional arguments are held until changed.
|
|
4041
4051
|
*/
|
|
4042
|
-
setGlobalMedium(density: number, albedo?: number, anisotropy?: number, maxDistance?: number): void;
|
|
4052
|
+
setGlobalMedium(density: number | GlobalMediumSettings, albedo?: number | Vec3, anisotropy?: number, maxDistance?: number): void;
|
|
4043
4053
|
/** How much speed blur the frame should resolve with, 0 to 1. */
|
|
4044
4054
|
setSpeedRush(strength: number): void;
|
|
4045
4055
|
/**
|
|
@@ -4083,7 +4093,7 @@ export declare class WebGPURenderer implements RendererApi {
|
|
|
4083
4093
|
* the same setter over the same state, sharing eye adaptation's pass, which is built the first
|
|
4084
4094
|
* time either is asked for.
|
|
4085
4095
|
*/
|
|
4086
|
-
setLocalExposure(
|
|
4096
|
+
setLocalExposure(setting: number | LocalExposureOptions): void;
|
|
4087
4097
|
/** The exposure pass, built once; the composite's group holds placeholders until it exists. */
|
|
4088
4098
|
private ensureExposurePass;
|
|
4089
4099
|
/**
|
|
@@ -24,7 +24,9 @@ import { Camera } from '../../camera.js';
|
|
|
24
24
|
import { PickableSet } from '../../pickable.js';
|
|
25
25
|
import { GpuTimestamps } from './gpuTimestamps.js';
|
|
26
26
|
import { isWeakGpuFamily } from '../../gpuCapability.js';
|
|
27
|
-
import {
|
|
27
|
+
import { writeMediumFields, writeMediumSlot } from './mediumFields.js';
|
|
28
|
+
import { noEnvironmentMixing, resolveEnvironmentMixing } from '../../environmentMixing.js';
|
|
29
|
+
import { createResolvedAtmosphere, resolveAtmosphere, } from '../../atmosphere.js';
|
|
28
30
|
import { AMBIENT_SH_FLOATS, packAmbientSH } from '../../ambientHarmonics.js';
|
|
29
31
|
import { lightmapTexels, warnRegionsWithoutPage, warnUnpagedLightmap, withLightmapUvs, } from '../../lightmap.js';
|
|
30
32
|
import { BLOOM_FILTER_RADIUS_UV, BLOOM_LEVELS, bloomLevelSizes, bloomThresholdOf, bloomProfileWarning, defaultBloomResponse, resolveBloomResponse, } from '../../bloomChain.js';
|
|
@@ -88,7 +90,7 @@ import { DEFAULT_FILMIC_CURVE, FILMIC_CLAMPED, FILMIC_CONSTANTS, FILMIC_WITHOUT_
|
|
|
88
90
|
import { ExposurePass } from './exposurePass.js';
|
|
89
91
|
import { AO_STORE } from '../../shaders/ambientOcclusion.js';
|
|
90
92
|
import { clampAutoExposure } from '../../shaders/exposure.js';
|
|
91
|
-
import {
|
|
93
|
+
import { LOCAL_EXPOSURE_FLOATS, resolveLocalExposure } from '../../shaders/localExposure.js';
|
|
92
94
|
import { createDepthResolveLayout, createPostStageLayout, depthResolvePipeline, postPipeline, postPipelineTargets, sceneColorFormat, AO_BLUR_FIELDS, AO_BLUR_FRAG_WGSL, AO_BLUR_SIZE, AO_BLUR_TEXTURES, AO_BLUR_UNIFORMS, AO_FRAG_FIELDS, AO_FRAG_SIZE, AO_FRAG_WGSL, AO_TEXTURES, AO_UNIFORMS, BLOOM_DOWNSAMPLE_FIELDS, BLOOM_DOWNSAMPLE_FRAG_WGSL, BLOOM_PREFILTER_FIELDS, BLOOM_PREFILTER_FRAG_WGSL, BLOOM_STAGE_SIZE, BLOOM_TEXTURES, BLOOM_UNIFORMS, BLOOM_UPSAMPLE_FIELDS, TINTED_ADD_BLEND, BLOOM_UPSAMPLE_FRAG_WGSL, RESOLVED_DEPTH_FORMAT, RUSH_FRAG_FIELDS, RUSH_FRAG_SIZE, RUSH_FRAG_WGSL, RUSH_TEXTURES, RUSH_UNIFORMS, TAA_FRAG_FIELDS, TAA_FRAG_SIZE, TAA_TEXTURES, TAA_UNIFORMS, TEMPORAL_RESOLVE_FRAG_WGSL, MEDIUM_FRAG_FIELDS, MEDIUM_FRAG_SIZE, MEDIUM_FRAG_WGSL, MEDIUM_TEXTURES, MEDIUM_TRANSMIT_BLEND, MEDIUM_UNIFORMS, MEDIUM_UPSAMPLE_FIELDS, MEDIUM_UPSAMPLE_FRAG_WGSL, MEDIUM_UPSAMPLE_SIZE, MEDIUM_UPSAMPLE_TEXTURES, MEDIUM_UPSAMPLE_UNIFORMS, OIT_COMPOSITE_BLEND, OIT_RESOLVE_FRAG_WGSL, OIT_TEXTURES, DECAL_FRAG_FIELDS, DECAL_FRAG_SIZE, DECAL_MULTIPLY_BLEND, DECAL_PROJECT_FRAG_WGSL, DECAL_TEXTURES, DECAL_UNIFORMS, PREMULTIPLIED_OVER_BLEND, FRAME_REFLECTION_BLEND, REFLECTION_OVER_BLEND, SSR_FRAG_FIELDS, SSR_FRAG_SIZE, SSR_MATERIAL_FIELDS, SSR_MATERIAL_RESOLVE_FRAG_WGSL, SSR_MATERIAL_SIZE, SSR_MATERIAL_TEXTURES, SSR_MATERIAL_UNIFORMS, SSR_RESOLVE_FRAG_WGSL, SSR_RESOLVE_TEXTURES, SSR_TEXTURES, SSR_TRACE_FRAG_WGSL, SSR_UNIFORMS, createOitResolveLayout, createSsrResolveLayout, } from './postPass.js';
|
|
93
95
|
import { GRADE_PLACEHOLDER_SIZE, identityGradeLut, validateGradeLut, } from '../../colourGrade.js';
|
|
94
96
|
import { FILM_LOOK_WITHOUT_COMPOSITE, clampGrain, clampVignette, grainSeed, } from '../../shaders/filmLook.js';
|
|
@@ -102,9 +104,9 @@ import { buildPlumeGeometry } from '../../plumeGeometry.js';
|
|
|
102
104
|
import { facingCode } from '../../particleBatch.js';
|
|
103
105
|
import { PARTICLE_INDICES } from '../../shaders/particle.js';
|
|
104
106
|
import { createScatterDeform, resolveScatterDeform, } from '../../scatterDeform.js';
|
|
105
|
-
import { resolvePointLights } from '../../lightBudget.js';
|
|
107
|
+
import { createResolvedPointLights, resolvePointLights, } from '../../lightBudget.js';
|
|
106
108
|
import { resolveRenderQuality } from '../../renderQuality.js';
|
|
107
|
-
import { DEFAULT_GLOBAL_MEDIUM, mediumActive, mediumTargetSize,
|
|
109
|
+
import { DEFAULT_GLOBAL_MEDIUM, WEAK_GPU_MEDIUM_STEPS, createResolvedMediumLamps, mediumActive, mediumTargetSize, resolveGlobalMedium, resolveGlobalMediumSettings, resolveMediumLamps, } from '../../globalMedium.js';
|
|
108
110
|
import { castsDepth, glassOf } from '../../shadowCasters.js';
|
|
109
111
|
import { materialHasMaps, noteMapsWithoutUvs } from '../../mapsWithoutUvs.js';
|
|
110
112
|
import { VIEW_MODEL_DEPTH_SHARE, viewModelDepthRange } from '../../viewModel.js';
|
|
@@ -1532,7 +1534,10 @@ export class WebGPURenderer {
|
|
|
1532
1534
|
/** The inverse projection the composite linearises a depth with, built once per frame. */
|
|
1533
1535
|
mediumInvProjection = mat4.create();
|
|
1534
1536
|
/** This frame's medium. Off until a caller says otherwise. See `setGlobalMedium`. */
|
|
1535
|
-
mediumOptions = DEFAULT_GLOBAL_MEDIUM;
|
|
1537
|
+
mediumOptions = resolveGlobalMedium(DEFAULT_GLOBAL_MEDIUM);
|
|
1538
|
+
/** The lamps the medium is lit by, and the lit stage's lamps they come from, refilled a frame. */
|
|
1539
|
+
mediumLamps = createResolvedMediumLamps();
|
|
1540
|
+
mediumLights = createResolvedPointLights();
|
|
1536
1541
|
/**
|
|
1537
1542
|
* The temporal resolve: its block, its ping-pong pair, and the jitter state.
|
|
1538
1543
|
*
|
|
@@ -2194,16 +2199,7 @@ export class WebGPURenderer {
|
|
|
2194
2199
|
f[atF('uFilmRoughness')] = Math.min(1, Math.max(0, options.roughness ?? 0));
|
|
2195
2200
|
f[atF('uFilmRoughnessCycles')] = Math.max(0.01, options.roughnessCyclesPerMetre ?? 60);
|
|
2196
2201
|
const medium = resolveAtmosphere(env, this.atmosphereHeight(camera), this.quality.underwaterAtmosphere, this.medium);
|
|
2197
|
-
|
|
2198
|
-
f[atF('uFogDensity')] = medium.fogDensity;
|
|
2199
|
-
f[atF('uFogHeightFalloff')] = medium.fogHeightFalloff;
|
|
2200
|
-
f[atF('uFogEyeY')] = medium.fogEyeY;
|
|
2201
|
-
f.set(medium.underwaterColor, atF('uUnderwaterColor'));
|
|
2202
|
-
f[atF('uUnderwaterFogDensity')] = medium.underwaterFogDensity;
|
|
2203
|
-
f[atF('uUnderwaterFactor')] = medium.underwaterFactor;
|
|
2204
|
-
i[atF('uFogMode')] = medium.fogMode;
|
|
2205
|
-
f[atF('uFogNear')] = medium.fogNear;
|
|
2206
|
-
f[atF('uFogFar')] = medium.fogFar;
|
|
2202
|
+
writeMediumFields(FILM_FRAG_FIELDS, f, medium);
|
|
2207
2203
|
this.filmFrags.writeBlock(fragmentSlot, this.filmFragInts);
|
|
2208
2204
|
const filmPipe = filmPipeline(this.blendedPipelines(), this.surface.device, this.filmLayout, `film|${geometry.key ?? ''}`, this.presentOf(geometry));
|
|
2209
2205
|
/* The mirror is an attachment right now, so the group that does not hold it. */
|
|
@@ -2931,6 +2927,15 @@ export class WebGPURenderer {
|
|
|
2931
2927
|
this.passEnvironmentGain = Math.max(0, gain);
|
|
2932
2928
|
this.writeEnvironmentDials();
|
|
2933
2929
|
}
|
|
2930
|
+
/** The environment brought to the light where a surface stands. See `renderer.ts`. */
|
|
2931
|
+
setEnvironmentMixing(weight, roughnessLow = 0.1, roughnessHigh = 0.3) {
|
|
2932
|
+
resolveEnvironmentMixing(weight, roughnessLow, roughnessHigh, this.environmentMixing);
|
|
2933
|
+
this.material((f) => {
|
|
2934
|
+
f.set(this.environmentMixing, this.materialField('uEnvironmentMixing'));
|
|
2935
|
+
});
|
|
2936
|
+
}
|
|
2937
|
+
/** `uEnvironmentMixing` as it stands; none until a draw asks. See `setEnvironmentMixing`. */
|
|
2938
|
+
environmentMixing = noEnvironmentMixing(new Float32Array(4));
|
|
2934
2939
|
/**
|
|
2935
2940
|
* The reflectivity and environment gain the setters gave the pass, and the ones the material
|
|
2936
2941
|
* set now states, or null where it states none (`SurfaceMaterial.reflectivity`). A draw wears the
|
|
@@ -3716,16 +3721,7 @@ export class WebGPURenderer {
|
|
|
3716
3721
|
scatterInto(f, fields['uLightWeight'], lights.weights, 1);
|
|
3717
3722
|
}
|
|
3718
3723
|
const medium = resolveAtmosphere(env, camera.position[1] ?? 0, this.quality.underwaterAtmosphere, this.medium);
|
|
3719
|
-
|
|
3720
|
-
f[atF('uFogDensity')] = medium.fogDensity;
|
|
3721
|
-
f[atF('uFogHeightFalloff')] = medium.fogHeightFalloff;
|
|
3722
|
-
f[atF('uFogEyeY')] = medium.fogEyeY;
|
|
3723
|
-
f.set(medium.underwaterColor, atF('uUnderwaterColor'));
|
|
3724
|
-
f[atF('uUnderwaterFogDensity')] = medium.underwaterFogDensity;
|
|
3725
|
-
f[atF('uUnderwaterFactor')] = medium.underwaterFactor;
|
|
3726
|
-
i[atF('uFogMode')] = medium.fogMode;
|
|
3727
|
-
f[atF('uFogNear')] = medium.fogNear;
|
|
3728
|
-
f[atF('uFogFar')] = medium.fogFar;
|
|
3724
|
+
writeMediumFields(fields, f, medium);
|
|
3729
3725
|
/* Only the mote fragment declares this — spark and smoke stay unconditionally fogged and
|
|
3730
3726
|
have no such field. See ParticleBatchOptions.fog. */
|
|
3731
3727
|
if (has('uFogEnabled'))
|
|
@@ -3929,16 +3925,7 @@ export class WebGPURenderer {
|
|
|
3929
3925
|
frags.writeInt(fragmentSlot, atF('uClipEnabled'), this.reflectionPassActive ? 1 : 0);
|
|
3930
3926
|
frags.writeFloats(fragmentSlot, atF('uClipPlane'), this.reflection?.clipPlane ?? NO_CLIP_PLANE);
|
|
3931
3927
|
const medium = resolveAtmosphere(env, this.atmosphereHeight(camera), this.quality.underwaterAtmosphere, this.medium);
|
|
3932
|
-
frags
|
|
3933
|
-
frags.writeFloat(fragmentSlot, atF('uFogDensity'), medium.fogDensity);
|
|
3934
|
-
frags.writeFloat(fragmentSlot, atF('uFogHeightFalloff'), medium.fogHeightFalloff);
|
|
3935
|
-
frags.writeFloat(fragmentSlot, atF('uFogEyeY'), medium.fogEyeY);
|
|
3936
|
-
frags.writeFloats(fragmentSlot, atF('uUnderwaterColor'), medium.underwaterColor);
|
|
3937
|
-
frags.writeFloat(fragmentSlot, atF('uUnderwaterFogDensity'), medium.underwaterFogDensity);
|
|
3938
|
-
frags.writeFloat(fragmentSlot, atF('uUnderwaterFactor'), medium.underwaterFactor);
|
|
3939
|
-
frags.writeInt(fragmentSlot, atF('uFogMode'), medium.fogMode);
|
|
3940
|
-
frags.writeFloat(fragmentSlot, atF('uFogNear'), medium.fogNear);
|
|
3941
|
-
frags.writeFloat(fragmentSlot, atF('uFogFar'), medium.fogFar);
|
|
3928
|
+
writeMediumSlot(frags, fragmentSlot, PLUME_FRAG_FIELDS, medium);
|
|
3942
3929
|
frags.writeInt(fragmentSlot, atF('uOutputTransform'), this.passGrade());
|
|
3943
3930
|
frags.writeFloat(fragmentSlot, atF('uOutputExposure'), this.passGradeExposure());
|
|
3944
3931
|
/*
|
|
@@ -4079,16 +4066,7 @@ export class WebGPURenderer {
|
|
|
4079
4066
|
scatterInto(f, WATER_FRAG_FIELDS['uLightWeight'], lights.weights, 1);
|
|
4080
4067
|
scatterInto(f, WATER_FRAG_FIELDS['uLightCone'], lights.conesAndFalloffs, 4);
|
|
4081
4068
|
const medium = resolveAtmosphere(env, camera.position[1] ?? 0, this.quality.underwaterAtmosphere, this.medium);
|
|
4082
|
-
|
|
4083
|
-
f[atF('uFogDensity')] = medium.fogDensity;
|
|
4084
|
-
f[atF('uFogHeightFalloff')] = medium.fogHeightFalloff;
|
|
4085
|
-
f[atF('uFogEyeY')] = medium.fogEyeY;
|
|
4086
|
-
f.set(medium.underwaterColor, atF('uUnderwaterColor'));
|
|
4087
|
-
f[atF('uUnderwaterFogDensity')] = medium.underwaterFogDensity;
|
|
4088
|
-
f[atF('uUnderwaterFactor')] = medium.underwaterFactor;
|
|
4089
|
-
i[atF('uFogMode')] = medium.fogMode;
|
|
4090
|
-
f[atF('uFogNear')] = medium.fogNear;
|
|
4091
|
-
f[atF('uFogFar')] = medium.fogFar;
|
|
4069
|
+
writeMediumFields(WATER_FRAG_FIELDS, f, medium);
|
|
4092
4070
|
/* No reflection pass yet: the shader's own "off" path, not an improvised one. */
|
|
4093
4071
|
i[atF('uReflectionEnabled')] = mirror === null ? 0 : 1;
|
|
4094
4072
|
i[atF('uReflectionFilterTaps')] = water.reflectionFilterTaps;
|
|
@@ -4587,16 +4565,7 @@ export class WebGPURenderer {
|
|
|
4587
4565
|
f.set(camera.position, atF('uCameraPos'));
|
|
4588
4566
|
/* The medium, through the same resolver every other pass here binds from. */
|
|
4589
4567
|
const medium = resolveAtmosphere(env, camera.position[1] ?? 0, this.quality.underwaterAtmosphere, this.medium);
|
|
4590
|
-
|
|
4591
|
-
f[atF('uFogDensity')] = medium.fogDensity;
|
|
4592
|
-
f[atF('uFogHeightFalloff')] = medium.fogHeightFalloff;
|
|
4593
|
-
f[atF('uFogEyeY')] = medium.fogEyeY;
|
|
4594
|
-
f.set(medium.underwaterColor, atF('uUnderwaterColor'));
|
|
4595
|
-
f[atF('uUnderwaterFogDensity')] = medium.underwaterFogDensity;
|
|
4596
|
-
f[atF('uUnderwaterFactor')] = medium.underwaterFactor;
|
|
4597
|
-
i[atF('uFogMode')] = medium.fogMode;
|
|
4598
|
-
f[atF('uFogNear')] = medium.fogNear;
|
|
4599
|
-
f[atF('uFogFar')] = medium.fogFar;
|
|
4568
|
+
writeMediumFields(BOLT_FRAG_FIELDS, f, medium);
|
|
4600
4569
|
this.boltVerts.writeBlock(vertexSlot, this.boltVertBlock);
|
|
4601
4570
|
this.boltFrags.writeBlock(fragmentSlot, this.boltFragInts);
|
|
4602
4571
|
const boltPipe = boltPipeline(this.blendedPipelines(), this.surface.device, this.boltLayout);
|
|
@@ -4699,16 +4668,7 @@ export class WebGPURenderer {
|
|
|
4699
4668
|
this.lineFrags.writeFloat(fragmentSlot, atF('uOutputExposure'), this.passGradeExposure());
|
|
4700
4669
|
/* The medium, through the same resolver every other pass here binds from. */
|
|
4701
4670
|
const medium = resolveAtmosphere(env, camera.position[1] ?? 0, this.quality.underwaterAtmosphere, this.medium);
|
|
4702
|
-
this.lineFrags
|
|
4703
|
-
this.lineFrags.writeFloat(fragmentSlot, atF('uFogDensity'), medium.fogDensity);
|
|
4704
|
-
this.lineFrags.writeFloat(fragmentSlot, atF('uFogHeightFalloff'), medium.fogHeightFalloff);
|
|
4705
|
-
this.lineFrags.writeFloat(fragmentSlot, atF('uFogEyeY'), medium.fogEyeY);
|
|
4706
|
-
this.lineFrags.writeFloats(fragmentSlot, atF('uUnderwaterColor'), medium.underwaterColor);
|
|
4707
|
-
this.lineFrags.writeFloat(fragmentSlot, atF('uUnderwaterFogDensity'), medium.underwaterFogDensity);
|
|
4708
|
-
this.lineFrags.writeFloat(fragmentSlot, atF('uUnderwaterFactor'), medium.underwaterFactor);
|
|
4709
|
-
this.lineFrags.writeInt(fragmentSlot, atF('uFogMode'), medium.fogMode);
|
|
4710
|
-
this.lineFrags.writeFloat(fragmentSlot, atF('uFogNear'), medium.fogNear);
|
|
4711
|
-
this.lineFrags.writeFloat(fragmentSlot, atF('uFogFar'), medium.fogFar);
|
|
4671
|
+
writeMediumSlot(this.lineFrags, fragmentSlot, LINE_FRAG_FIELDS, medium);
|
|
4712
4672
|
const linePipe = linePipeline(this.blendedPipelines(), this.surface.device, this.lineLayout, additive);
|
|
4713
4673
|
/* Two uniform blocks and three vertex buffers, and no attachment among them. */
|
|
4714
4674
|
const lineCommand = this.recordBlended(0);
|
|
@@ -4855,39 +4815,11 @@ export class WebGPURenderer {
|
|
|
4855
4815
|
this.shadowDraws.writeFloats(slot, DEPTH_VERT_FIELDS.uWindSpatialPhase.offset, d.spatialPhase);
|
|
4856
4816
|
}
|
|
4857
4817
|
/** Refilled per frame rather than allocated; see `resolvePointLights`. */
|
|
4858
|
-
lights =
|
|
4859
|
-
count: 0,
|
|
4860
|
-
falloff: 0,
|
|
4861
|
-
positions: new Float32Array(0),
|
|
4862
|
-
colors: new Float32Array(0),
|
|
4863
|
-
radii: new Float32Array(0),
|
|
4864
|
-
sourceRadii: new Float32Array(0),
|
|
4865
|
-
weights: new Float32Array(0),
|
|
4866
|
-
directions: new Float32Array(0),
|
|
4867
|
-
coneCos: new Float32Array(0),
|
|
4868
|
-
iesProfiles: new Float32Array(0),
|
|
4869
|
-
iesAxes: new Float32Array(0),
|
|
4870
|
-
cookies: new Float32Array(0),
|
|
4871
|
-
heldSourceRadii: new Float32Array(MAX_POINT_LIGHTS),
|
|
4872
|
-
axesAndChannels: new Float32Array(MAX_POINT_LIGHTS * 4),
|
|
4873
|
-
conesAndFalloffs: new Float32Array(MAX_POINT_LIGHTS * 4),
|
|
4874
|
-
heldWeights: new Float32Array(MAX_POINT_LIGHTS),
|
|
4875
|
-
};
|
|
4818
|
+
lights = createResolvedPointLights();
|
|
4876
4819
|
/** The fixed arm's rectangles as `uAreaLightSize` holds them. See `packAreaSizesAndDoors`. */
|
|
4877
4820
|
areaSizesAndDoors = new Float32Array(MAX_AREA_LIGHTS * 4);
|
|
4878
4821
|
/** Refilled per frame rather than allocated; see `resolveAtmosphere`. */
|
|
4879
|
-
medium =
|
|
4880
|
-
fogColor: new Float32Array(3),
|
|
4881
|
-
underwaterColor: new Float32Array(3),
|
|
4882
|
-
fogDensity: 0,
|
|
4883
|
-
fogHeightFalloff: 0,
|
|
4884
|
-
fogEyeY: 0,
|
|
4885
|
-
fogMode: 0,
|
|
4886
|
-
fogNear: 0,
|
|
4887
|
-
fogFar: 1,
|
|
4888
|
-
underwaterFogDensity: 0,
|
|
4889
|
-
underwaterFactor: 0,
|
|
4890
|
-
};
|
|
4822
|
+
medium = createResolvedAtmosphere();
|
|
4891
4823
|
/* -- Overlays: panels and text ------------------------------------------------------ */
|
|
4892
4824
|
panelLayout;
|
|
4893
4825
|
panelCorners;
|
|
@@ -6313,6 +6245,7 @@ export class WebGPURenderer {
|
|
|
6313
6245
|
this.mediumLayout = createPostStageLayout(device, MEDIUM_UNIFORMS, MEDIUM_FRAG_SIZE, [
|
|
6314
6246
|
{ binding: MEDIUM_TEXTURES.uDepth, filterable: false },
|
|
6315
6247
|
{ binding: MEDIUM_TEXTURES.uSunShadows, filterable: false, dimension: '2d-array' },
|
|
6248
|
+
{ binding: MEDIUM_TEXTURES.uPointShadows, filterable: false, dimension: '2d-array' },
|
|
6316
6249
|
]);
|
|
6317
6250
|
this.mediumUniforms = device.createBuffer({
|
|
6318
6251
|
label: 'post.mediumUniforms',
|
|
@@ -7365,16 +7298,7 @@ export class WebGPURenderer {
|
|
|
7365
7298
|
* Found by a voxel scene that is the first in the tree to use `fogMode: 'linear'` on WebGPU.
|
|
7366
7299
|
*/
|
|
7367
7300
|
const meshMedium = resolveAtmosphere(env, this.atmosphereHeight(camera), this.quality.underwaterAtmosphere, this.medium);
|
|
7368
|
-
|
|
7369
|
-
f[at('uFogDensity')] = meshMedium.fogDensity;
|
|
7370
|
-
f[at('uFogHeightFalloff')] = meshMedium.fogHeightFalloff;
|
|
7371
|
-
f[at('uFogEyeY')] = meshMedium.fogEyeY;
|
|
7372
|
-
i[at('uFogMode')] = meshMedium.fogMode;
|
|
7373
|
-
f[at('uFogNear')] = meshMedium.fogNear;
|
|
7374
|
-
f[at('uFogFar')] = meshMedium.fogFar;
|
|
7375
|
-
f.set(meshMedium.underwaterColor, at('uUnderwaterColor'));
|
|
7376
|
-
f[at('uUnderwaterFogDensity')] = meshMedium.underwaterFogDensity;
|
|
7377
|
-
f[at('uUnderwaterFactor')] = meshMedium.underwaterFactor;
|
|
7301
|
+
writeMediumFields(this.fragment.fields, f, meshMedium);
|
|
7378
7302
|
/*
|
|
7379
7303
|
* The mirror's half-space, and only while the mirror is being drawn.
|
|
7380
7304
|
*
|
|
@@ -7419,6 +7343,8 @@ export class WebGPURenderer {
|
|
|
7419
7343
|
f[at('uWriteMode') + 2] = 0;
|
|
7420
7344
|
/* 1, not 0: a multiplier's identity is one. See `setEnvironmentGain`. */
|
|
7421
7345
|
f[at('uEnvironmentDials') + 2] = 1;
|
|
7346
|
+
/* And no mixing, which is stored less one. See `setEnvironmentMixing`. */
|
|
7347
|
+
f.set(noEnvironmentMixing(this.environmentMixing), at('uEnvironmentMixing'));
|
|
7422
7348
|
/* No overlay until a draw sets one. See `setSurfaceOverlay`. */
|
|
7423
7349
|
this.overlayFloats.fill(0);
|
|
7424
7350
|
f.fill(0, at('uOverlay'), at('uOverlay') + OVERLAY_FLOATS);
|
|
@@ -7662,16 +7588,7 @@ export class WebGPURenderer {
|
|
|
7662
7588
|
* drift `bindAtmosphere` was written to prevent.
|
|
7663
7589
|
*/
|
|
7664
7590
|
const medium = resolveAtmosphere(env, this.atmosphereHeight(camera), this.quality.underwaterAtmosphere, this.medium);
|
|
7665
|
-
|
|
7666
|
-
f[at('uFogDensity')] = medium.fogDensity;
|
|
7667
|
-
f[at('uFogHeightFalloff')] = medium.fogHeightFalloff;
|
|
7668
|
-
f[at('uFogEyeY')] = medium.fogEyeY;
|
|
7669
|
-
i[at('uFogMode')] = medium.fogMode;
|
|
7670
|
-
f[at('uFogNear')] = medium.fogNear;
|
|
7671
|
-
f[at('uFogFar')] = medium.fogFar;
|
|
7672
|
-
f.set(medium.underwaterColor, at('uUnderwaterColor'));
|
|
7673
|
-
f[at('uUnderwaterFogDensity')] = medium.underwaterFogDensity;
|
|
7674
|
-
f[at('uUnderwaterFactor')] = medium.underwaterFactor;
|
|
7591
|
+
writeMediumFields(this.fragment.fields, f, medium);
|
|
7675
7592
|
/*
|
|
7676
7593
|
* The shadow terms, matching what `renderer.ts` binds at default quality.
|
|
7677
7594
|
*
|
|
@@ -8976,16 +8893,7 @@ export class WebGPURenderer {
|
|
|
8976
8893
|
f.set(env.ambient, atF('uAmbient'));
|
|
8977
8894
|
f.set(camera.position, atF('uCameraPos'));
|
|
8978
8895
|
const medium = resolveAtmosphere(env, camera.position[1] ?? 0, this.quality.underwaterAtmosphere, this.medium);
|
|
8979
|
-
|
|
8980
|
-
f[atF('uFogDensity')] = medium.fogDensity;
|
|
8981
|
-
f[atF('uFogHeightFalloff')] = medium.fogHeightFalloff;
|
|
8982
|
-
f[atF('uFogEyeY')] = medium.fogEyeY;
|
|
8983
|
-
f.set(medium.underwaterColor, atF('uUnderwaterColor'));
|
|
8984
|
-
f[atF('uUnderwaterFogDensity')] = medium.underwaterFogDensity;
|
|
8985
|
-
f[atF('uUnderwaterFactor')] = medium.underwaterFactor;
|
|
8986
|
-
i[atF('uFogMode')] = medium.fogMode;
|
|
8987
|
-
f[atF('uFogNear')] = medium.fogNear;
|
|
8988
|
-
f[atF('uFogFar')] = medium.fogFar;
|
|
8896
|
+
writeMediumFields(SCATTER_FRAG_FIELDS, f, medium);
|
|
8989
8897
|
i[atF('uOutputTransform')] = this.passGrade();
|
|
8990
8898
|
f[atF('uOutputExposure')] = this.passGradeExposure();
|
|
8991
8899
|
const fragmentSlot = this.scatterFrags.allocate();
|
|
@@ -9799,6 +9707,8 @@ export class WebGPURenderer {
|
|
|
9799
9707
|
* resolve, which is what sampling a stand-in does.
|
|
9800
9708
|
*/
|
|
9801
9709
|
this.rebuildFlatBindGroup();
|
|
9710
|
+
/* The medium reads the same array: see `buildMediumBindGroup`. */
|
|
9711
|
+
this.mediumBindGroup = this.buildMediumBindGroup();
|
|
9802
9712
|
}
|
|
9803
9713
|
this.pointShadows.prepareStaticMaps(lights.length);
|
|
9804
9714
|
this.preparedPointLightCount = lights.length;
|
|
@@ -10041,6 +9951,8 @@ export class WebGPURenderer {
|
|
|
10041
9951
|
if (old !== null) {
|
|
10042
9952
|
this.retiredPointTexture = old;
|
|
10043
9953
|
this.rebuildFlatBindGroup();
|
|
9954
|
+
/* The medium reads the same array: see `buildMediumBindGroup`. */
|
|
9955
|
+
this.mediumBindGroup = this.buildMediumBindGroup();
|
|
10044
9956
|
}
|
|
10045
9957
|
}
|
|
10046
9958
|
}
|
|
@@ -10523,7 +10435,7 @@ export class WebGPURenderer {
|
|
|
10523
10435
|
* it. The held brightness is kept for either, since local exposure moves regions relative to it.
|
|
10524
10436
|
* See `setAutoExposure` and `setLocalExposure`.
|
|
10525
10437
|
*/
|
|
10526
|
-
const localising = this.localExposure
|
|
10438
|
+
const localising = this.localExposure;
|
|
10527
10439
|
const measuring = (this.autoExposure > 0 || localising) && this.exposurePass !== null;
|
|
10528
10440
|
const adapting = measuring && this.autoExposure > 0;
|
|
10529
10441
|
const shownScene = this.reconstructing ? this.reconShownView : this.sceneColorView;
|
|
@@ -10596,7 +10508,13 @@ export class WebGPURenderer {
|
|
|
10596
10508
|
f[at('uVignette')] = this.vignette;
|
|
10597
10509
|
f.set(this.fringe, at('uFringe'));
|
|
10598
10510
|
f[at('uAutoExposure')] = adapting ? this.autoExposure : 0;
|
|
10599
|
-
f[at('uLocalExposure')] = measuring && localising ?
|
|
10511
|
+
f[at('uLocalExposure')] = measuring && localising ? 1 : 0;
|
|
10512
|
+
const shapeAt = at('uLocalShape');
|
|
10513
|
+
const pivotAt = at('uLocalPivot');
|
|
10514
|
+
for (let k = 0; k < 4; k++) {
|
|
10515
|
+
f[shapeAt + k] = this.localExposureShape[k];
|
|
10516
|
+
f[pivotAt + k] = this.localExposureShape[4 + k];
|
|
10517
|
+
}
|
|
10600
10518
|
f[at('uGrain')] = this.grain;
|
|
10601
10519
|
f[at('uGrain') + 1] = this.grainSeed;
|
|
10602
10520
|
device.queue.writeBuffer(this.rushUniforms, 0, this.rushStaging);
|
|
@@ -11810,7 +11728,17 @@ export class WebGPURenderer {
|
|
|
11810
11728
|
f.set(env?.directionalColor ?? [0, 0, 0], at('uSunColor'));
|
|
11811
11729
|
f.set(env?.ambient ?? [0, 0, 0], at('uAmbient'));
|
|
11812
11730
|
f[at('uDensity')] = options.density;
|
|
11813
|
-
|
|
11731
|
+
const height = at('uHeight');
|
|
11732
|
+
f[height] = options.heightFalloff;
|
|
11733
|
+
f[height + 1] = options.baseY;
|
|
11734
|
+
const layer2 = at('uLayer2');
|
|
11735
|
+
f[layer2] = options.density2;
|
|
11736
|
+
f[layer2 + 1] = options.heightFalloff2;
|
|
11737
|
+
f[layer2 + 2] = options.baseY2;
|
|
11738
|
+
f.set(options.albedo, at('uAlbedo'));
|
|
11739
|
+
const scatter = at('uScatter');
|
|
11740
|
+
f[scatter] = options.sunScatter;
|
|
11741
|
+
f[scatter + 1] = options.skyScatter;
|
|
11814
11742
|
f[at('uAnisotropy')] = options.anisotropy;
|
|
11815
11743
|
f[at('uMaxDistance')] = options.maxDistance;
|
|
11816
11744
|
ints[at('uSteps')] = this.quality.globalMediumSteps;
|
|
@@ -11828,6 +11756,20 @@ export class WebGPURenderer {
|
|
|
11828
11756
|
f.set(env?.lightViewProj ?? this.mediumIdentity, at('uLightViewProj'));
|
|
11829
11757
|
f.set((env === null ? this.mediumIdentity : this.movingLightFor(env)), at('uMovingLightViewProj'));
|
|
11830
11758
|
ints[at('uPeeledShadowEnabled')] = this.peelView === null || !this.peelFilled ? 0 : 1;
|
|
11759
|
+
/* The lit stage's lamps and the shadows it resolved for them, this frame's. */
|
|
11760
|
+
const lamps = resolveMediumLamps(options, resolvePointLights(env, this.quality.pointLightFalloff, this.mediumLights), this.pointShadows === null ? null : this.resolvedPointShadows, env?.lightMediumScatter, this.mediumLamps);
|
|
11761
|
+
ints[at('uLampCount')] = lamps.count;
|
|
11762
|
+
ints[at('uLampFalloff')] = lamps.falloff;
|
|
11763
|
+
if (lamps.count > 0) {
|
|
11764
|
+
f.set(lamps.position, at('uLampPosition'));
|
|
11765
|
+
f.set(lamps.color, at('uLampColor'));
|
|
11766
|
+
f.set(lamps.aim, at('uLampAim'));
|
|
11767
|
+
f.set(lamps.cone, at('uLampCone'));
|
|
11768
|
+
f.set(lamps.shadow, at('uLampShadow'));
|
|
11769
|
+
f.set(lamps.shadowAt, at('uLampShadowAt'));
|
|
11770
|
+
f.set(lamps.live, at('uLampLive'));
|
|
11771
|
+
f.set(lamps.liveAt, at('uLampLiveAt'));
|
|
11772
|
+
}
|
|
11831
11773
|
device.queue.writeBuffer(this.mediumUniforms, 0, this.mediumStaging);
|
|
11832
11774
|
const g = this.mediumUpsampleFloats;
|
|
11833
11775
|
const upsampleAt = (name) => this.postField(MEDIUM_UPSAMPLE_FIELDS, name);
|
|
@@ -14236,8 +14178,9 @@ export class WebGPURenderer {
|
|
|
14236
14178
|
/** Eye adaptation: how far, this frame's time step, and the pass once asked for. */
|
|
14237
14179
|
autoExposure = 0;
|
|
14238
14180
|
autoExposureDt = 0;
|
|
14239
|
-
/**
|
|
14240
|
-
localExposure =
|
|
14181
|
+
/** Whether regions move, and how, as `resolveLocalExposure` packs it. See `setLocalExposure`. */
|
|
14182
|
+
localExposure = false;
|
|
14183
|
+
localExposureShape = new Float32Array(LOCAL_EXPOSURE_FLOATS);
|
|
14241
14184
|
exposurePass = null;
|
|
14242
14185
|
/**
|
|
14243
14186
|
* How strongly the lens darkens the frame's corners, held until changed: 0 is none, 0.5 is about
|
|
@@ -14387,12 +14330,7 @@ export class WebGPURenderer {
|
|
|
14387
14330
|
* draws nothing, and the three optional arguments are held until changed.
|
|
14388
14331
|
*/
|
|
14389
14332
|
setGlobalMedium(density, albedo, anisotropy, maxDistance) {
|
|
14390
|
-
this.mediumOptions =
|
|
14391
|
-
density: Number.isFinite(density) ? density : 0,
|
|
14392
|
-
albedo,
|
|
14393
|
-
anisotropy,
|
|
14394
|
-
maxDistance,
|
|
14395
|
-
});
|
|
14333
|
+
this.mediumOptions = resolveGlobalMediumSettings(density, albedo, anisotropy, maxDistance);
|
|
14396
14334
|
}
|
|
14397
14335
|
/** How much speed blur the frame should resolve with, 0 to 1. */
|
|
14398
14336
|
setSpeedRush(strength) {
|
|
@@ -14463,13 +14401,13 @@ export class WebGPURenderer {
|
|
|
14463
14401
|
* the same setter over the same state, sharing eye adaptation's pass, which is built the first
|
|
14464
14402
|
* time either is asked for.
|
|
14465
14403
|
*/
|
|
14466
|
-
setLocalExposure(
|
|
14404
|
+
setLocalExposure(setting) {
|
|
14467
14405
|
if (!this.hasComposite || !this.quality.hdrScene) {
|
|
14468
|
-
this.warnLookWithoutComposite(
|
|
14406
|
+
this.warnLookWithoutComposite(typeof setting === 'number' ? setting : 1);
|
|
14469
14407
|
return;
|
|
14470
14408
|
}
|
|
14471
|
-
this.localExposure =
|
|
14472
|
-
if (this.localExposure
|
|
14409
|
+
this.localExposure = resolveLocalExposure(setting, this.localExposureShape);
|
|
14410
|
+
if (this.localExposure)
|
|
14473
14411
|
this.ensureExposurePass();
|
|
14474
14412
|
}
|
|
14475
14413
|
/** The exposure pass, built once; the composite's group holds placeholders until it exists. */
|
|
@@ -14606,16 +14544,7 @@ export class WebGPURenderer {
|
|
|
14606
14544
|
f[atF('uWindDir') + 1] = inv === 0 ? 0 : windZ * inv;
|
|
14607
14545
|
f[atF('uWaveGain')] = sea.steepness;
|
|
14608
14546
|
const medium = resolveAtmosphere(env, this.atmosphereHeight(camera), this.quality.underwaterAtmosphere, this.medium);
|
|
14609
|
-
|
|
14610
|
-
f[atF('uFogDensity')] = medium.fogDensity;
|
|
14611
|
-
f[atF('uFogHeightFalloff')] = medium.fogHeightFalloff;
|
|
14612
|
-
f[atF('uFogEyeY')] = medium.fogEyeY;
|
|
14613
|
-
f.set(medium.underwaterColor, atF('uUnderwaterColor'));
|
|
14614
|
-
f[atF('uUnderwaterFogDensity')] = medium.underwaterFogDensity;
|
|
14615
|
-
f[atF('uUnderwaterFactor')] = medium.underwaterFactor;
|
|
14616
|
-
i[atF('uFogMode')] = medium.fogMode;
|
|
14617
|
-
f[atF('uFogNear')] = medium.fogNear;
|
|
14618
|
-
f[atF('uFogFar')] = medium.fogFar;
|
|
14547
|
+
writeMediumFields(CAUSTICS_FRAG_FIELDS, f, medium);
|
|
14619
14548
|
this.causticsVerts.writeBlock(vertexSlot, this.causticsVertBlock);
|
|
14620
14549
|
this.causticsFrags.writeBlock(fragmentSlot, this.causticsFragInts);
|
|
14621
14550
|
const causticsPipe = causticsPipeline(this.blendedPipelines(), this.surface.device, this.causticsLayout);
|
|
@@ -15556,6 +15485,13 @@ export class WebGPURenderer {
|
|
|
15556
15485
|
{ binding: MEDIUM_TEXTURES.uDepth.sampler, resource: this.postDepthSampler },
|
|
15557
15486
|
{ binding: MEDIUM_TEXTURES.uSunShadows.texture, resource: this.sunArrayView },
|
|
15558
15487
|
{ binding: MEDIUM_TEXTURES.uSunShadows.sampler, resource: this.volumeShadowSampler },
|
|
15488
|
+
/* The lamps' maps, the lit stage's own array, rebuilt here whenever that array is
|
|
15489
|
+
replaced; the white stand-in reads as nothing in the way, and no lamp reads it. */
|
|
15490
|
+
{
|
|
15491
|
+
binding: MEDIUM_TEXTURES.uPointShadows.texture,
|
|
15492
|
+
resource: this.pointShadowArray?.view ?? this.shadowBlankView,
|
|
15493
|
+
},
|
|
15494
|
+
{ binding: MEDIUM_TEXTURES.uPointShadows.sampler, resource: this.volumeShadowSampler },
|
|
15559
15495
|
],
|
|
15560
15496
|
});
|
|
15561
15497
|
}
|
|
@@ -21,7 +21,7 @@ export declare const SCATTER_DEPTH_SIZE: 240;
|
|
|
21
21
|
export declare const SCATTER_VERT_FIELDS: UniformFields;
|
|
22
22
|
export declare const SCATTER_VERT_SIZE: 240;
|
|
23
23
|
export declare const SCATTER_FRAG_FIELDS: UniformFields;
|
|
24
|
-
export declare const SCATTER_FRAG_SIZE:
|
|
24
|
+
export declare const SCATTER_FRAG_SIZE: 192;
|
|
25
25
|
export declare function scatterVertexLayouts(): GPUVertexBufferLayout[];
|
|
26
26
|
/** Geometry and placement on the device, behind the opaque handle the surface hands out. */
|
|
27
27
|
export interface GpuScatter {
|
|
@@ -11,7 +11,7 @@ import type { UniformFields } from './scatterPass.ts';
|
|
|
11
11
|
export declare const WATER_VERT_FIELDS: UniformFields;
|
|
12
12
|
export declare const WATER_VERT_SIZE: 208;
|
|
13
13
|
export declare const WATER_FRAG_FIELDS: UniformFields;
|
|
14
|
-
export declare const WATER_FRAG_SIZE:
|
|
14
|
+
export declare const WATER_FRAG_SIZE: 1568;
|
|
15
15
|
/** The two meshes and the numbers the grid decided, behind the surface's opaque handle. */
|
|
16
16
|
export interface GpuWater {
|
|
17
17
|
/** The ocean: near sheet and far skirt in one buffer. */
|