@driftengine/core 4.12.0 → 4.13.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 +66 -0
- package/README.md +18 -9
- package/dist/geometry/meshBuilder.d.ts +10 -0
- package/dist/geometry/meshBuilder.js +11 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +3 -2
- package/dist/math/color.d.ts +25 -0
- package/dist/math/color.js +37 -0
- package/dist/render/backend/webgl2/renderer.d.ts +17 -4
- package/dist/render/backend/webgl2/renderer.js +82 -47
- package/dist/render/backend/webgl2/skinScatter.d.ts +3 -1
- package/dist/render/backend/webgl2/skinScatter.js +5 -1
- 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/flockPass.d.ts +1 -1
- package/dist/render/backend/webgpu/giFieldPass.d.ts +3 -1
- package/dist/render/backend/webgpu/gpuDrivenPass.d.ts +10 -1
- package/dist/render/backend/webgpu/gpuDrivenPass.js +28 -11
- package/dist/render/backend/webgpu/panelPass.d.ts +1 -1
- package/dist/render/backend/webgpu/postPass.d.ts +2 -2
- package/dist/render/backend/webgpu/renderer.d.ts +19 -8
- package/dist/render/backend/webgpu/renderer.js +94 -38
- package/dist/render/backend/webgpu/scatterPass.d.ts +1 -1
- package/dist/render/backend/webgpu/skinScatterPass.d.ts +5 -1
- package/dist/render/backend/webgpu/skinScatterPass.js +9 -3
- package/dist/render/backend/webgpu/skyPass.d.ts +11 -1
- package/dist/render/backend/webgpu/waterPass.d.ts +1 -1
- package/dist/render/backend/webgpu/windStreakPass.d.ts +1 -1
- package/dist/render/causticsRenderer.d.ts +3 -1
- package/dist/render/causticsRenderer.js +5 -1
- package/dist/render/decalPass.d.ts +3 -1
- package/dist/render/decalPass.js +4 -1
- package/dist/render/flockRenderer.d.ts +1 -1
- package/dist/render/flockRenderer.js +4 -1
- package/dist/render/globalMediumPass.d.ts +3 -1
- package/dist/render/globalMediumPass.js +5 -1
- package/dist/render/gradeColor.d.ts +21 -0
- package/dist/render/gradeColor.js +64 -0
- package/dist/render/lightMatrix.d.ts +13 -0
- package/dist/render/lightMatrix.js +17 -0
- package/dist/render/passGrade.d.ts +13 -0
- package/dist/render/passGrade.js +47 -0
- package/dist/render/plumeRenderer.d.ts +1 -1
- package/dist/render/plumeRenderer.js +4 -1
- package/dist/render/renderQuality.d.ts +57 -18
- package/dist/render/renderQuality.js +3 -3
- package/dist/render/sceneTarget.d.ts +2 -0
- package/dist/render/sceneTarget.js +1 -0
- package/dist/render/sdfTextRenderer.d.ts +1 -1
- package/dist/render/sdfTextRenderer.js +1 -1
- package/dist/render/shaders/arcane.d.ts +1 -1
- package/dist/render/shaders/arcane.js +5 -1
- package/dist/render/shaders/bolt.d.ts +1 -1
- package/dist/render/shaders/bolt.js +4 -1
- package/dist/render/shaders/caustics.d.ts +1 -1
- package/dist/render/shaders/caustics.js +4 -1
- package/dist/render/shaders/decalProject.js +12 -2
- package/dist/render/shaders/film.d.ts +1 -1
- package/dist/render/shaders/film.js +22 -9
- package/dist/render/shaders/fire.d.ts +1 -1
- package/dist/render/shaders/fire.js +4 -1
- package/dist/render/shaders/flat/layerLooks.js +11 -19
- package/dist/render/shaders/flat/layered.js +33 -18
- package/dist/render/shaders/flock.d.ts +1 -1
- package/dist/render/shaders/flock.js +4 -1
- package/dist/render/shaders/generated/arcane.wgsl.d.ts +11 -1
- package/dist/render/shaders/generated/arcane.wgsl.js +11 -1
- package/dist/render/shaders/generated/bolt.wgsl.d.ts +12 -2
- package/dist/render/shaders/generated/bolt.wgsl.js +12 -2
- package/dist/render/shaders/generated/caustics.wgsl.d.ts +12 -2
- package/dist/render/shaders/generated/caustics.wgsl.js +12 -2
- package/dist/render/shaders/generated/decalProject.wgsl.d.ts +6 -1
- package/dist/render/shaders/generated/decalProject.wgsl.js +6 -1
- package/dist/render/shaders/generated/film.wgsl.d.ts +12 -2
- package/dist/render/shaders/generated/film.wgsl.js +12 -2
- package/dist/render/shaders/generated/fire.wgsl.d.ts +11 -1
- package/dist/render/shaders/generated/fire.wgsl.js +11 -1
- package/dist/render/shaders/generated/flat.wgsl.js +23 -23
- package/dist/render/shaders/generated/flock.wgsl.d.ts +12 -2
- package/dist/render/shaders/generated/flock.wgsl.js +12 -2
- package/dist/render/shaders/generated/globalMedium.wgsl.d.ts +12 -2
- package/dist/render/shaders/generated/globalMedium.wgsl.js +12 -2
- package/dist/render/shaders/generated/lightVolume.wgsl.d.ts +36 -16
- package/dist/render/shaders/generated/lightVolume.wgsl.js +39 -19
- package/dist/render/shaders/generated/panel.wgsl.d.ts +12 -2
- package/dist/render/shaders/generated/panel.wgsl.js +12 -2
- package/dist/render/shaders/generated/rush.wgsl.d.ts +31 -26
- package/dist/render/shaders/generated/rush.wgsl.js +31 -26
- package/dist/render/shaders/generated/scatter.wgsl.d.ts +12 -2
- package/dist/render/shaders/generated/scatter.wgsl.js +12 -2
- package/dist/render/shaders/generated/skinBlur.wgsl.d.ts +11 -1
- package/dist/render/shaders/generated/skinBlur.wgsl.js +11 -1
- package/dist/render/shaders/generated/sky.wgsl.d.ts +12 -2
- package/dist/render/shaders/generated/sky.wgsl.js +12 -2
- package/dist/render/shaders/generated/smoke.wgsl.d.ts +11 -1
- package/dist/render/shaders/generated/smoke.wgsl.js +11 -1
- package/dist/render/shaders/generated/text.wgsl.d.ts +11 -1
- package/dist/render/shaders/generated/text.wgsl.js +11 -1
- package/dist/render/shaders/generated/water.wgsl.d.ts +12 -2
- package/dist/render/shaders/generated/water.wgsl.js +12 -2
- package/dist/render/shaders/generated/windStreaks.wgsl.d.ts +12 -2
- package/dist/render/shaders/generated/windStreaks.wgsl.js +12 -2
- package/dist/render/shaders/globalMedium.js +14 -1
- package/dist/render/shaders/gpudriven/present.wgsl.d.ts +15 -6
- package/dist/render/shaders/gpudriven/present.wgsl.js +71 -8
- package/dist/render/shaders/lightVolume.js +4 -1
- package/dist/render/shaders/line.d.ts +1 -1
- package/dist/render/shaders/outputTransform.d.ts +8 -2
- package/dist/render/shaders/outputTransform.js +18 -11
- package/dist/render/shaders/panel.d.ts +1 -1
- package/dist/render/shaders/panel.js +5 -1
- package/dist/render/shaders/particle.d.ts +3 -3
- package/dist/render/shaders/rush.js +8 -0
- package/dist/render/shaders/scatter.d.ts +1 -1
- package/dist/render/shaders/scatter.js +4 -1
- package/dist/render/shaders/sdfText.d.ts +1 -1
- package/dist/render/shaders/skinBlur.js +5 -1
- package/dist/render/shaders/sky.d.ts +1 -1
- package/dist/render/shaders/sky.js +5 -1
- package/dist/render/shaders/smoke.d.ts +1 -1
- package/dist/render/shaders/smoke.js +4 -1
- package/dist/render/shaders/text.d.ts +1 -1
- package/dist/render/shaders/text.js +4 -1
- package/dist/render/shaders/water.d.ts +1 -1
- package/dist/render/shaders/water.js +12 -2
- package/dist/render/shaders/windStreaks.d.ts +1 -1
- package/dist/render/shaders/windStreaks.js +4 -1
- package/dist/render/surfaceLayerLooks.d.ts +16 -4
- package/dist/render/surfaceLayerLooks.js +33 -14
- package/dist/render/surfaceLayers.d.ts +2 -2
- package/dist/render/textRenderer.d.ts +3 -1
- package/dist/render/textRenderer.js +7 -1
- package/dist/render/vertexDefaults.d.ts +1 -1
- package/dist/render/vertexDefaults.js +1 -1
- package/dist/render/waterRenderer.d.ts +1 -1
- package/dist/render/waterRenderer.js +4 -1
- package/dist/render/windStreakRenderer.d.ts +3 -1
- package/dist/render/windStreakRenderer.js +5 -1
- package/package.json +6 -6
- package/src/geometry/meshBuilder.ts +21 -2
- package/src/index.ts +11 -2
- package/src/math/color.ts +39 -0
- package/src/render/backend/webgl2/renderer.ts +134 -44
- package/src/render/backend/webgl2/skinScatter.ts +5 -0
- package/src/render/backend/webgpu/giFieldPass.ts +3 -1
- package/src/render/backend/webgpu/gpuDrivenPass.ts +29 -13
- package/src/render/backend/webgpu/renderer.ts +104 -37
- package/src/render/backend/webgpu/skinScatterPass.ts +17 -1
- package/src/render/causticsRenderer.ts +5 -0
- package/src/render/decalPass.ts +3 -0
- package/src/render/flockRenderer.ts +5 -0
- package/src/render/globalMediumPass.ts +10 -1
- package/src/render/gradeColor.ts +90 -0
- package/src/render/lightMatrix.ts +32 -0
- package/src/render/passGrade.ts +58 -0
- package/src/render/plumeRenderer.ts +5 -0
- package/src/render/renderQuality.ts +60 -21
- package/src/render/sceneTarget.ts +3 -0
- package/src/render/sdfTextRenderer.ts +1 -1
- package/src/render/shaders/arcane.ts +5 -1
- package/src/render/shaders/bolt.ts +4 -1
- package/src/render/shaders/caustics.ts +4 -1
- package/src/render/shaders/decalProject.ts +12 -2
- package/src/render/shaders/film.ts +22 -9
- package/src/render/shaders/fire.ts +4 -1
- package/src/render/shaders/flat/layerLooks.ts +11 -19
- package/src/render/shaders/flat/layered.ts +33 -18
- package/src/render/shaders/flock.ts +4 -1
- package/src/render/shaders/generated/arcane.wgsl.ts +11 -1
- package/src/render/shaders/generated/bolt.wgsl.ts +12 -2
- package/src/render/shaders/generated/caustics.wgsl.ts +12 -2
- package/src/render/shaders/generated/decalProject.wgsl.ts +6 -1
- package/src/render/shaders/generated/film.wgsl.ts +12 -2
- package/src/render/shaders/generated/fire.wgsl.ts +11 -1
- package/src/render/shaders/generated/flat.wgsl.ts +23 -23
- package/src/render/shaders/generated/flock.wgsl.ts +12 -2
- package/src/render/shaders/generated/globalMedium.wgsl.ts +12 -2
- package/src/render/shaders/generated/lightVolume.wgsl.ts +39 -19
- package/src/render/shaders/generated/panel.wgsl.ts +12 -2
- package/src/render/shaders/generated/rush.wgsl.ts +31 -26
- package/src/render/shaders/generated/scatter.wgsl.ts +12 -2
- package/src/render/shaders/generated/skinBlur.wgsl.ts +11 -1
- package/src/render/shaders/generated/sky.wgsl.ts +12 -2
- package/src/render/shaders/generated/smoke.wgsl.ts +11 -1
- package/src/render/shaders/generated/text.wgsl.ts +11 -1
- package/src/render/shaders/generated/water.wgsl.ts +12 -2
- package/src/render/shaders/generated/windStreaks.wgsl.ts +12 -2
- package/src/render/shaders/globalMedium.ts +14 -1
- package/src/render/shaders/gpudriven/present.wgsl.ts +72 -8
- package/src/render/shaders/lightVolume.ts +4 -1
- package/src/render/shaders/outputTransform.ts +19 -11
- package/src/render/shaders/panel.ts +5 -1
- package/src/render/shaders/rush.ts +8 -0
- package/src/render/shaders/scatter.ts +4 -1
- package/src/render/shaders/skinBlur.ts +5 -1
- package/src/render/shaders/sky.ts +5 -1
- package/src/render/shaders/smoke.ts +4 -1
- package/src/render/shaders/text.ts +4 -1
- package/src/render/shaders/water.ts +12 -2
- package/src/render/shaders/windStreaks.ts +4 -1
- package/src/render/surfaceLayerLooks.ts +49 -18
- package/src/render/surfaceLayers.ts +2 -2
- package/src/render/textRenderer.ts +6 -0
- package/src/render/vertexDefaults.ts +1 -1
- package/src/render/waterRenderer.ts +5 -0
- package/src/render/windStreakRenderer.ts +5 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { glslFarDepth } from '../depthConvention.ts';
|
|
2
|
+
import { OUTPUT_TRANSFORM_GLSL } from './outputTransform.ts';
|
|
2
3
|
/**
|
|
3
4
|
* Procedural gradient sky drawn as a single attribute-less fullscreen triangle.
|
|
4
5
|
* Ray direction is reconstructed per-fragment from the inverse view-projection,
|
|
@@ -77,6 +78,7 @@ uniform vec3 uUnderwaterColor;
|
|
|
77
78
|
uniform float uUnderwaterFactor;
|
|
78
79
|
|
|
79
80
|
out vec4 outColor;
|
|
81
|
+
${OUTPUT_TRANSFORM_GLSL}
|
|
80
82
|
|
|
81
83
|
float hash21(vec2 p) {
|
|
82
84
|
return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453123);
|
|
@@ -273,6 +275,8 @@ void main() {
|
|
|
273
275
|
float waterLight = mix(0.62, 1.08, clamp(dir.y * 0.5 + 0.5, 0.0, 1.0));
|
|
274
276
|
col = mix(col, uUnderwaterColor * waterLight, uUnderwaterFactor);
|
|
275
277
|
|
|
276
|
-
|
|
278
|
+
/* Graded where nothing after this will grade it, as every pass is: its colours are the same
|
|
279
|
+
light as the fog the world fades into. 0 in a probe's face, whose cube stores radiance. */
|
|
280
|
+
outColor = vec4(applyOutputTransform(col), 1.0);
|
|
277
281
|
}
|
|
278
282
|
`;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { FOG_GLSL } from './fog.ts';
|
|
2
|
+
import { OUTPUT_TRANSFORM_GLSL } from './outputTransform.ts';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Smoke: a column that rises, expands and dissipates. Shares the plume
|
|
@@ -22,6 +23,7 @@ uniform vec4 uClipPlane;
|
|
|
22
23
|
uniform int uClipEnabled;
|
|
23
24
|
|
|
24
25
|
out vec4 outColor;
|
|
26
|
+
${OUTPUT_TRANSFORM_GLSL}
|
|
25
27
|
|
|
26
28
|
float hash21(vec2 p) {
|
|
27
29
|
return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453123);
|
|
@@ -84,6 +86,7 @@ void main() {
|
|
|
84
86
|
float fog = mediumFog(vDistance, vWorldPos.y);
|
|
85
87
|
col = mix(col, atmosphereColor, fog);
|
|
86
88
|
float alpha = clamp(density * 0.95, 0.0, 1.0) * emerge * dissipate * 0.13;
|
|
87
|
-
|
|
89
|
+
/* Graded where nothing after this will grade it, as every pass is. The alpha is coverage. */
|
|
90
|
+
outColor = vec4(applyOutputTransform(col), alpha * (1.0 - fog));
|
|
88
91
|
}
|
|
89
92
|
`;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { OUTPUT_TRANSFORM_GLSL } from './outputTransform.ts';
|
|
1
2
|
/**
|
|
2
3
|
* Screen-space 3D text.
|
|
3
4
|
*
|
|
@@ -147,6 +148,7 @@ uniform float uGlow;
|
|
|
147
148
|
uniform float uAlpha;
|
|
148
149
|
|
|
149
150
|
out vec4 fragColor;
|
|
151
|
+
${OUTPUT_TRANSFORM_GLSL}
|
|
150
152
|
|
|
151
153
|
void main() {
|
|
152
154
|
/*
|
|
@@ -161,5 +163,6 @@ void main() {
|
|
|
161
163
|
vec3 lit = uColor * lambert;
|
|
162
164
|
// The glow rides the arrival: brightest as a character lands, settling after.
|
|
163
165
|
vec3 emissive = uColor * uGlow * (0.45 + 0.55 * vChar);
|
|
164
|
-
|
|
166
|
+
/* Graded where nothing after this will grade it, as every pass is. The alpha is coverage. */
|
|
167
|
+
fragColor = vec4(applyOutputTransform(lit + emissive), uAlpha);
|
|
165
168
|
}`;
|
|
@@ -2,6 +2,7 @@ import { MAX_POINT_LIGHTS } from '../lightBudget.ts';
|
|
|
2
2
|
import { MAX_WATER_REFLECTION_FILTER_TAPS } from '../renderQuality.ts';
|
|
3
3
|
import { GERSTNER_GLSL } from './gerstner.ts';
|
|
4
4
|
import { FOG_GLSL } from './fog.ts';
|
|
5
|
+
import { OUTPUT_TRANSFORM_GLSL } from './outputTransform.ts';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* The sky-ocean, as an actual wave simulation rather than a tinted plane.
|
|
@@ -198,6 +199,7 @@ uniform sampler2D uReflectionMap;
|
|
|
198
199
|
uniform int uReflectionEnabled;
|
|
199
200
|
uniform vec2 uReflectionTexelSize;
|
|
200
201
|
uniform int uReflectionFilterTaps;
|
|
202
|
+
${OUTPUT_TRANSFORM_GLSL}
|
|
201
203
|
|
|
202
204
|
const vec2 REFLECTION_FILTER[${MAX_WATER_REFLECTION_FILTER_TAPS}] = vec2[${MAX_WATER_REFLECTION_FILTER_TAPS}](
|
|
203
205
|
vec2( 0.00, 0.00), vec2(-0.62, -0.31), vec2( 0.54, 0.43),
|
|
@@ -276,6 +278,14 @@ void main() {
|
|
|
276
278
|
float dist = distance(vWorldPos, uCameraPos);
|
|
277
279
|
float fog = mediumFog(dist, vWorldPos.y);
|
|
278
280
|
col = mix(col, atmosphereColor, fog);
|
|
281
|
+
/*
|
|
282
|
+
* **Graded here, before the mirror is mixed in**, as every pass grades what it draws when
|
|
283
|
+
* nothing after it will: the mirror's own passes graded what it holds, so mixing first would put
|
|
284
|
+
* the curve on it twice. The air's colour, which stands in where the mirror shows nothing, is
|
|
285
|
+
* graded to meet it, as the sky behind it is.
|
|
286
|
+
*/
|
|
287
|
+
col = applyOutputTransform(col);
|
|
288
|
+
vec3 gradedAir = applyOutputTransform(atmosphereColor);
|
|
279
289
|
|
|
280
290
|
// Transparency is angle-dependent, like real water: looking down you see
|
|
281
291
|
// straight through to the seabed, at grazing angles it turns reflective.
|
|
@@ -289,7 +299,7 @@ void main() {
|
|
|
289
299
|
// Project the displaced surface into the mirrored camera. The Gerstner
|
|
290
300
|
// displacement supplies broad distortion; the analytic normal adds the
|
|
291
301
|
// smaller ripples that make reflected silhouettes move with each crest.
|
|
292
|
-
vec3 reflected =
|
|
302
|
+
vec3 reflected = gradedAir;
|
|
293
303
|
float reflectionValid = 0.0;
|
|
294
304
|
if (uReflectionEnabled != 0 && vReflectionClip.w > 0.0) {
|
|
295
305
|
vec2 reflectionUv = vReflectionClip.xy / vReflectionClip.w * 0.5 + 0.5;
|
|
@@ -324,7 +334,7 @@ void main() {
|
|
|
324
334
|
filterWeight += weight;
|
|
325
335
|
}
|
|
326
336
|
sceneReflection /= max(filterWeight, 0.001);
|
|
327
|
-
reflected = mix(
|
|
337
|
+
reflected = mix(gradedAir, sceneReflection, reflectionValid);
|
|
328
338
|
}
|
|
329
339
|
// The atmosphere-colour fallback preserves the old sky reflection when a
|
|
330
340
|
// quality profile disables the extra scene pass. Foam scatters rather than
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { OUTPUT_TRANSFORM_GLSL } from './outputTransform.ts';
|
|
1
2
|
/**
|
|
2
3
|
* Visible wind: streaks of dust and debris carried past the camera.
|
|
3
4
|
*
|
|
@@ -117,6 +118,7 @@ in float vFade;
|
|
|
117
118
|
in float vAlong;
|
|
118
119
|
uniform vec3 uTint;
|
|
119
120
|
out vec4 outColor;
|
|
121
|
+
${OUTPUT_TRANSFORM_GLSL}
|
|
120
122
|
|
|
121
123
|
void main() {
|
|
122
124
|
// Tapered at both ends, so a streak reads as motion rather than as a stick.
|
|
@@ -125,6 +127,7 @@ void main() {
|
|
|
125
127
|
float taper = sin(vAlong * 3.14159);
|
|
126
128
|
float alpha = vFade * taper * taper * 0.13;
|
|
127
129
|
if (alpha <= 0.002) discard;
|
|
128
|
-
|
|
130
|
+
/* Graded where nothing after this will grade it, as every pass is. The alpha is coverage. */
|
|
131
|
+
outColor = vec4(applyOutputTransform(uTint), alpha);
|
|
129
132
|
}
|
|
130
133
|
`;
|
|
@@ -43,7 +43,7 @@ export interface SurfaceLayerLook {
|
|
|
43
43
|
|
|
44
44
|
/** What an occlusion read at the mesh's own coordinates darkens, and how far. */
|
|
45
45
|
export interface SurfaceMeshOcclusion {
|
|
46
|
-
/** 0 to 1:
|
|
46
|
+
/** 0 to 1: what `into` names times `mix(1, occlusion, strength)`. Absent: 1. */
|
|
47
47
|
readonly strength?: number;
|
|
48
48
|
/**
|
|
49
49
|
* `'color'`, the default, darkens the blended colour, and so every light on it, the sun's too.
|
|
@@ -51,6 +51,18 @@ export interface SurfaceMeshOcclusion {
|
|
|
51
51
|
* does, leaving the sun, the lamps and the reflections as they were.
|
|
52
52
|
*/
|
|
53
53
|
readonly into?: 'color' | 'ambient';
|
|
54
|
+
/**
|
|
55
|
+
* The colour's own strength, from 0 up and past 1: the blended colour times
|
|
56
|
+
* `max(0, 1 − colorStrength × (1 − occlusion))`, which up to 1 is the `mix` above and past it
|
|
57
|
+
* darkens faster than the occlusion does. Absent: `strength` where `into` is the colour, and 0
|
|
58
|
+
* where it is the ambient light — so named beside `into: 'ambient'` it darkens both, each at its
|
|
59
|
+
* own strength, as a material taking its ambient occlusion and a darker colour from one map does.
|
|
60
|
+
*
|
|
61
|
+
* **What it gives up**: past 1 the colour is black wherever `1 − occlusion` reaches
|
|
62
|
+
* `1 / colorStrength`, and black under every light, the sun's too, which is what such a material
|
|
63
|
+
* asks for and what an ambient occlusion alone would never do.
|
|
64
|
+
*/
|
|
65
|
+
readonly colorStrength?: number;
|
|
54
66
|
/** The range the occlusion's red is spread over, from its 0 to its 1. Absent: `[0, 1]`. */
|
|
55
67
|
readonly range?: readonly [number, number];
|
|
56
68
|
}
|
|
@@ -75,7 +87,8 @@ export function asksLayerLooks<Texture>(
|
|
|
75
87
|
layers.extrasAt !== undefined ||
|
|
76
88
|
layers.looks !== undefined ||
|
|
77
89
|
layers.repeats.some((repeat) => typeof repeat !== 'number') ||
|
|
78
|
-
|
|
90
|
+
colorOcclusion(layers.meshOcclusion) > 0 ||
|
|
91
|
+
ambientOcclusion(layers.meshOcclusion) > 0
|
|
79
92
|
);
|
|
80
93
|
}
|
|
81
94
|
|
|
@@ -85,15 +98,15 @@ export function asksLayerLooks<Texture>(
|
|
|
85
98
|
* `LAYER_LOOKS` on, so it must draw exactly as it did before.
|
|
86
99
|
*
|
|
87
100
|
* - **0 to 7**: the array layer each layer reads, base first (layer `i` where not given); where the
|
|
88
|
-
* maps beyond the layers start (the layer count where not given); the mesh occlusion's strength
|
|
89
|
-
*
|
|
101
|
+
* maps beyond the layers start (the layer count where not given); the mesh occlusion's strength
|
|
102
|
+
* on the colour, from 0 up, and on the ambient light, 0 to 1.
|
|
90
103
|
* - **8 to 47**: two vectors a layer, base first: its tint and its normal strength, then its
|
|
91
104
|
* roughness range and its metalness range.
|
|
92
105
|
* - **48 to 59**: each layer's specular (−1 for the surface's own), each layer's repeat down (its
|
|
93
106
|
* repeat across where it gave one number), and the range the occlusion is spread over.
|
|
94
107
|
*
|
|
95
108
|
* An array layer that is not a whole number at or above 0 reads layer `i`; a start that is not one
|
|
96
|
-
* is the count; a strength is held to 0..1; a tint channel, a normal strength or a specular that is
|
|
109
|
+
* is the count; a strength is held to 0..1, but for the colour's own, which is held at or above 0; a tint channel, a normal strength or a specular that is
|
|
97
110
|
* not a number at or above 0 is the identity; a repeat down that is not a positive number is the
|
|
98
111
|
* repeat across; a range end that is not a number is the identity's end.
|
|
99
112
|
*/
|
|
@@ -105,9 +118,9 @@ export function packLayerLooks<Texture>(
|
|
|
105
118
|
const picks = layers?.arrayLayers;
|
|
106
119
|
for (let i = 0; i < MAX_SURFACE_LAYERS; i++) out[i] = arrayLayer(picks?.[i], i);
|
|
107
120
|
out[5] = arrayLayer(layers?.extrasAt, count);
|
|
108
|
-
const occlusion =
|
|
109
|
-
out[6] = occlusion
|
|
110
|
-
out[7] = occlusion
|
|
121
|
+
const occlusion = layers?.meshOcclusion;
|
|
122
|
+
out[6] = colorOcclusion(occlusion);
|
|
123
|
+
out[7] = ambientOcclusion(occlusion);
|
|
111
124
|
for (let i = 0; i < MAX_SURFACE_LAYERS; i++) {
|
|
112
125
|
const look = layers?.looks?.[i] ?? null;
|
|
113
126
|
const at = 8 + i * 8;
|
|
@@ -124,18 +137,36 @@ export function packLayerLooks<Texture>(
|
|
|
124
137
|
const acrossIt = positiveOr(across(repeat), 1);
|
|
125
138
|
out[53 + i] = typeof repeat === 'object' ? positiveOr(repeat[1], acrossIt) : acrossIt;
|
|
126
139
|
}
|
|
127
|
-
|
|
128
|
-
out[
|
|
140
|
+
const range = typeof occlusion === 'object' ? occlusion.range : undefined;
|
|
141
|
+
out[58] = finiteOr(range?.[0], 0);
|
|
142
|
+
out[59] = finiteOr(range?.[1], 1);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/** The strength `meshOcclusion` names, held to 0..1: a number's own, an object's or 1, and 0 for none. */
|
|
146
|
+
function occlusionStrength(occlusion: number | SurfaceMeshOcclusion | undefined): number {
|
|
147
|
+
const strength =
|
|
148
|
+
typeof occlusion === 'number'
|
|
149
|
+
? occlusion
|
|
150
|
+
: occlusion === undefined
|
|
151
|
+
? 0
|
|
152
|
+
: (occlusion.strength ?? 1);
|
|
153
|
+
return Number.isFinite(strength) ? Math.min(Math.max(strength, 0), 1) : 0;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/** How hard the occlusion darkens the colour: its own strength where named, else `into`'s. */
|
|
157
|
+
function colorOcclusion(occlusion: number | SurfaceMeshOcclusion | undefined): number {
|
|
158
|
+
if (typeof occlusion === 'object' && occlusion.colorStrength !== undefined)
|
|
159
|
+
return atLeastZero(occlusion.colorStrength, 0);
|
|
160
|
+
return typeof occlusion === 'object' && occlusion.into === 'ambient'
|
|
161
|
+
? 0
|
|
162
|
+
: occlusionStrength(occlusion);
|
|
129
163
|
}
|
|
130
164
|
|
|
131
|
-
/**
|
|
132
|
-
function
|
|
133
|
-
occlusion
|
|
134
|
-
)
|
|
135
|
-
|
|
136
|
-
typeof occlusion === 'number' ? { strength: occlusion } : (occlusion ?? { strength: 0 });
|
|
137
|
-
const strength = given.strength ?? 1;
|
|
138
|
-
return { ...given, strength: Number.isFinite(strength) ? Math.min(Math.max(strength, 0), 1) : 0 };
|
|
165
|
+
/** How hard the occlusion darkens the ambient light: its strength where that is its target. */
|
|
166
|
+
function ambientOcclusion(occlusion: number | SurfaceMeshOcclusion | undefined): number {
|
|
167
|
+
return typeof occlusion === 'object' && occlusion.into === 'ambient'
|
|
168
|
+
? occlusionStrength(occlusion)
|
|
169
|
+
: 0;
|
|
139
170
|
}
|
|
140
171
|
|
|
141
172
|
function arrayLayer(value: number | undefined, otherwise: number): number {
|
|
@@ -112,8 +112,8 @@ export interface SurfaceLayers<Texture> {
|
|
|
112
112
|
* layers and any mask or added mask the array carries — darkening the surface by a strength from 0
|
|
113
113
|
* to 1: the large shading of a cliff that layers repeating across it cannot carry, as
|
|
114
114
|
* `meshNormal` carries its shape. A number is that strength, darkening the blended colour; the
|
|
115
|
-
* object form also chooses what it darkens
|
|
116
|
-
* none.
|
|
115
|
+
* object form also chooses what it darkens, the colour and the ambient light at strengths of their
|
|
116
|
+
* own, and the range its red is spread over. Absent or 0: none.
|
|
117
117
|
*/
|
|
118
118
|
readonly meshOcclusion?: number | SurfaceMeshOcclusion;
|
|
119
119
|
}
|
|
@@ -80,11 +80,17 @@ export class TextRenderer {
|
|
|
80
80
|
originY: number,
|
|
81
81
|
style: TextStyle,
|
|
82
82
|
timeSec: number,
|
|
83
|
+
/** The renderer's `passGrade`: the frame's, but none in a probe's face or a capture. */
|
|
84
|
+
outputTransform = 0,
|
|
85
|
+
outputExposure = 1,
|
|
83
86
|
): boolean {
|
|
84
87
|
if (this.layout.instanceCount === 0 || style.alpha <= 0) return false;
|
|
85
88
|
const gl = this.gl;
|
|
86
89
|
|
|
87
90
|
gl.useProgram(this.program);
|
|
91
|
+
const grade = this.uniforms['uOutputTransform'];
|
|
92
|
+
if (grade !== undefined) gl.uniform1i(grade, outputTransform);
|
|
93
|
+
setFloat(gl, this.uniforms['uOutputExposure'], outputExposure);
|
|
88
94
|
gl.bindVertexArray(this.vao);
|
|
89
95
|
|
|
90
96
|
/*
|
|
@@ -119,7 +119,7 @@ export const OUTPUT_TRANSFORM_CODE: Readonly<Record<string, number>> = {
|
|
|
119
119
|
/**
|
|
120
120
|
* The code a **forward** pass grades with: the transform's own, except `filmic`, which only the
|
|
121
121
|
* composite carries the constants for, and which a pass grading itself therefore draws as `aces`.
|
|
122
|
-
*
|
|
122
|
+
* `passGrade.ts` reads this for both backends, so neither can hand a forward stage a code it lacks.
|
|
123
123
|
*/
|
|
124
124
|
export function forwardTransformCode(transform: string): number {
|
|
125
125
|
return transform === 'filmic' ? 2 : (OUTPUT_TRANSFORM_CODE[transform] ?? 0);
|
|
@@ -253,10 +253,15 @@ export class WaterRenderer {
|
|
|
253
253
|
lightFalloff: 'smooth' | 'inverseSquare' = 'smooth',
|
|
254
254
|
windX = 0,
|
|
255
255
|
windZ = 0,
|
|
256
|
+
outputTransform = 0,
|
|
257
|
+
outputExposure = 1,
|
|
256
258
|
): void {
|
|
257
259
|
const u = this.uniforms;
|
|
258
260
|
const reflectionReady = reflection?.isReadyFor(settings.level) ?? false;
|
|
259
261
|
gl.useProgram(this.program);
|
|
262
|
+
/* The renderer's `passGrade`: the frame's, but none in a probe's face or a capture. */
|
|
263
|
+
gl.uniform1i(u['uOutputTransform'] ?? null, outputTransform);
|
|
264
|
+
gl.uniform1f(u['uOutputExposure'] ?? null, outputExposure);
|
|
260
265
|
gl.uniformMatrix4fv(u['uViewProj'] ?? null, false, camera.viewProjection);
|
|
261
266
|
gl.uniformMatrix4fv(
|
|
262
267
|
u['uReflectionViewProj'] ?? null,
|
|
@@ -86,6 +86,9 @@ export class WindStreakRenderer {
|
|
|
86
86
|
tint: Vec3,
|
|
87
87
|
/** True when the camera is below the waterline. */
|
|
88
88
|
submerged = false,
|
|
89
|
+
/** The renderer's `passGrade`: the frame's, but none in a probe's face or a capture. */
|
|
90
|
+
outputTransform = 0,
|
|
91
|
+
outputExposure = 1,
|
|
89
92
|
): boolean {
|
|
90
93
|
/* Chosen in `windStreakDraw.ts` so both backends show the same weather. */
|
|
91
94
|
const settled = resolveWindStreaks(
|
|
@@ -111,6 +114,8 @@ export class WindStreakRenderer {
|
|
|
111
114
|
gl.uniform1f(u['uCellSize'] ?? null, this.cellSize);
|
|
112
115
|
gl.uniform1f(u['uTime'] ?? null, timeSeconds);
|
|
113
116
|
gl.uniform3fv(u['uTint'] ?? null, tint);
|
|
117
|
+
gl.uniform1i(u['uOutputTransform'] ?? null, outputTransform);
|
|
118
|
+
gl.uniform1f(u['uOutputExposure'] ?? null, outputExposure);
|
|
114
119
|
|
|
115
120
|
gl.enable(gl.BLEND);
|
|
116
121
|
blendCovering(gl, gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
|