@driftengine/core 4.11.1 → 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 +102 -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 +5 -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 +33 -5
- package/dist/render/backend/webgl2/renderer.js +123 -49
- 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 +21 -8
- package/dist/render/backend/webgpu/renderer.js +103 -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/areaLight.d.ts +1 -1
- package/dist/render/shaders/flat/areaLight.js +1 -1
- package/dist/render/shaders/flat/glassTint.d.ts +1 -1
- package/dist/render/shaders/flat/glassTint.js +1 -0
- package/dist/render/shaders/flat/index.d.ts +5 -0
- package/dist/render/shaders/flat/index.js +1 -1
- package/dist/render/shaders/flat/layerLooks.d.ts +16 -0
- package/dist/render/shaders/flat/layerLooks.js +108 -0
- package/dist/render/shaders/flat/layered.d.ts +6 -4
- package/dist/render/shaders/flat/layered.js +77 -13
- package/dist/render/shaders/flat/main.d.ts +1 -1
- package/dist/render/shaders/flat/main.js +7 -2
- package/dist/render/shaders/flat/models.js +1 -1
- package/dist/render/shaders/flat/preamble.js +6 -0
- 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.d.ts +144 -16
- package/dist/render/shaders/generated/flat.wgsl.js +183 -55
- 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 +92 -0
- package/dist/render/surfaceLayerLooks.js +102 -0
- package/dist/render/surfaceLayers.d.ts +47 -6
- package/dist/render/surfaceLayers.js +5 -1
- 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/scripts/browser.d.mts +5 -0
- package/scripts/browser.mjs +68 -14
- package/scripts/look.d.mts +81 -0
- package/scripts/look.mjs +380 -0
- package/src/geometry/meshBuilder.ts +21 -2
- package/src/index.ts +13 -2
- package/src/math/color.ts +39 -0
- package/src/render/backend/webgl2/renderer.ts +174 -46
- 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 +112 -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/areaLight.ts +1 -1
- package/src/render/shaders/flat/glassTint.ts +3 -1
- package/src/render/shaders/flat/index.ts +6 -1
- package/src/render/shaders/flat/layerLooks.ts +108 -0
- package/src/render/shaders/flat/layered.ts +78 -13
- package/src/render/shaders/flat/main.ts +7 -2
- package/src/render/shaders/flat/models.ts +1 -1
- package/src/render/shaders/flat/preamble.ts +6 -0
- 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 +183 -55
- 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 +186 -0
- package/src/render/surfaceLayers.ts +52 -7
- 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
|
@@ -41,6 +41,7 @@ import { resolveTransmission } from '../../transmission.js';
|
|
|
41
41
|
import { resolveOcclusionFade } from '../../occlusionFade.js';
|
|
42
42
|
import { orthographicDepthSpan } from '../../lightMatrix.js';
|
|
43
43
|
import { LAYER_FLOATS, layerMaskMap, layeredProjection, layersFitBeside, packSurfaceLayers, } from '../../surfaceLayers.js';
|
|
44
|
+
import { LOOK_FLOATS, asksLayerLooks, packLayerLooks } from '../../surfaceLayerLooks.js';
|
|
44
45
|
import { FILM_FRAG, FILM_VERT } from '../../shaders/film.js';
|
|
45
46
|
import { SceneTarget } from '../../sceneTarget.js';
|
|
46
47
|
import { FILM_LOOK_WITHOUT_COMPOSITE } from '../../shaders/filmLook.js';
|
|
@@ -118,7 +119,9 @@ import { FlockRenderer } from '../../flockRenderer.js';
|
|
|
118
119
|
import { TextRenderer } from '../../textRenderer.js';
|
|
119
120
|
import { SdfTextRenderer } from '../../sdfTextRenderer.js';
|
|
120
121
|
import { MOTION_BLUR_MAX_UV, OBJECT_BLUR_UNKEPT, RUSH_REACH_UV, clampMotionShare, } from '../../vertexDefaults.js';
|
|
121
|
-
import { OUTPUT_TRANSFORM_CODE
|
|
122
|
+
import { OUTPUT_TRANSFORM_CODE } from '../../vertexDefaults.js';
|
|
123
|
+
import { gradeColorInto } from '../../gradeColor.js';
|
|
124
|
+
import { interfaceGrade, passGradeCode, passGradeExposure } from '../../passGrade.js';
|
|
122
125
|
import { DEFAULT_FILMIC_CURVE, FILMIC_CLAMPED, FILMIC_CONSTANTS, FILMIC_WITHOUT_COMPOSITE, resolveFilmicCurve, } from '../../filmicCurve.js';
|
|
123
126
|
import { deviceSnappedCellSize } from '../../textLayout.js';
|
|
124
127
|
import { WindStreakRenderer } from '../../windStreakRenderer.js';
|
|
@@ -963,15 +966,22 @@ export class WebGL2Renderer {
|
|
|
963
966
|
transmission = new Float32Array([-1, -1, -1, 0]);
|
|
964
967
|
/** `uLayers`, the current material's layers packed. See `surfaceLayers.ts`. */
|
|
965
968
|
layerFloats = new Float32Array(LAYER_FLOATS);
|
|
969
|
+
/** `uLayerLooks`, the current material's layer picks and looks packed. See `surfaceLayerLooks.ts`. */
|
|
970
|
+
lookFloats = new Float32Array(LOOK_FLOATS);
|
|
966
971
|
/** Whether the lit stage has room for layers' two vectors, and which refusals were said. */
|
|
967
972
|
layersRoom = null;
|
|
968
973
|
warnedLayersRoom = false;
|
|
974
|
+
/** Whether it has room for the layers' looks beside them, and whether the refusal was said. */
|
|
975
|
+
looksRoom = null;
|
|
976
|
+
warnedLooksRoom = false;
|
|
969
977
|
warnedLayersModelMap = false;
|
|
970
978
|
warnedLayersTriplanar = false;
|
|
971
979
|
warnedOverlayRoom = false;
|
|
972
980
|
warnedOverlayBlocks = false;
|
|
973
981
|
/** Whether a probe is being baked, so the passes that would recurse into one can tell. */
|
|
974
982
|
probePassActive = false;
|
|
983
|
+
/** `clearOf`'s scratch: a clear colour as the open target takes it. */
|
|
984
|
+
gradedClear = [0, 0, 0];
|
|
975
985
|
/**
|
|
976
986
|
* Whether a scene capture is being drawn (`captureScene`): an off-screen pass like a bake, so the
|
|
977
987
|
* frame's own view, its refraction copy and skin's spread are left alone, but lit as the frame is.
|
|
@@ -1685,8 +1695,8 @@ export class WebGL2Renderer {
|
|
|
1685
1695
|
sceneDepth: null,
|
|
1686
1696
|
};
|
|
1687
1697
|
const context = this.passContext;
|
|
1688
|
-
context.outputTransform = this.
|
|
1689
|
-
context.outputExposure = this.
|
|
1698
|
+
context.outputTransform = this.passGrade();
|
|
1699
|
+
context.outputExposure = this.passGradeExposure();
|
|
1690
1700
|
/*
|
|
1691
1701
|
* The copies a pass declared it reads, taken here with everything drawn before it: colour
|
|
1692
1702
|
* afresh at each reading pass, as WebGPU's `takePassColour` does, so a full-screen effect drawn
|
|
@@ -2815,11 +2825,11 @@ export class WebGL2Renderer {
|
|
|
2815
2825
|
finally {
|
|
2816
2826
|
target.end(gl);
|
|
2817
2827
|
gl.frontFace(gl.CCW);
|
|
2828
|
+
this.capturePassActive = false;
|
|
2818
2829
|
this.useFlatProgram();
|
|
2819
|
-
gl.uniform1i(this.flatUniforms['uOutputTransform'] ?? null, this.
|
|
2820
|
-
gl.uniform1f(this.flatUniforms['uOutputExposure'] ?? null, this.
|
|
2830
|
+
gl.uniform1i(this.flatUniforms['uOutputTransform'] ?? null, this.passGrade());
|
|
2831
|
+
gl.uniform1f(this.flatUniforms['uOutputExposure'] ?? null, this.passGradeExposure());
|
|
2821
2832
|
this.materials.dirty();
|
|
2822
|
-
this.capturePassActive = false;
|
|
2823
2833
|
this.temporalJittering = jittering;
|
|
2824
2834
|
this.restoreViewport();
|
|
2825
2835
|
}
|
|
@@ -3267,6 +3277,10 @@ export class WebGL2Renderer {
|
|
|
3267
3277
|
if (layers !== null)
|
|
3268
3278
|
this.askLit('LAYERED');
|
|
3269
3279
|
gl.uniform4fv(u['uLayers'] ?? null, this.layerFloats);
|
|
3280
|
+
packLayerLooks(layers, this.lookFloats);
|
|
3281
|
+
if (this.looksFit(layers))
|
|
3282
|
+
this.askLit('LAYER_LOOKS');
|
|
3283
|
+
gl.uniform4fv(u['uLayerLooks'] ?? null, this.lookFloats);
|
|
3270
3284
|
gl.uniform1i(u['uModelMap'] ?? null, MODEL_MAP_TEXTURE_UNIT);
|
|
3271
3285
|
packModel(material?.model ?? null, modelMap !== null, this.modelParams, material?.physicalSpecular === true);
|
|
3272
3286
|
/* The first physical highlight asked for is when the lit programs start carrying one. */
|
|
@@ -3539,6 +3553,27 @@ export class WebGL2Renderer {
|
|
|
3539
3553
|
}
|
|
3540
3554
|
return null;
|
|
3541
3555
|
}
|
|
3556
|
+
/**
|
|
3557
|
+
* Whether a layered material's picks and looks are drawn: asked for, and room for their fifteen
|
|
3558
|
+
* vectors beside the layers' four. Refused, the layers are drawn reading layer `i` of their arrays
|
|
3559
|
+
* as they are, said once — which on a material sharing its arrays reads the wrong textures, so
|
|
3560
|
+
* the sentence names the way out.
|
|
3561
|
+
*/
|
|
3562
|
+
looksFit(layers) {
|
|
3563
|
+
if (!asksLayerLooks(layers))
|
|
3564
|
+
return false;
|
|
3565
|
+
this.looksRoom ??= this.switchFits('LAYER_LOOKS', 'LAYERED');
|
|
3566
|
+
if (this.looksRoom)
|
|
3567
|
+
return true;
|
|
3568
|
+
if (!this.warnedLooksRoom) {
|
|
3569
|
+
this.warnedLooksRoom = true;
|
|
3570
|
+
console.warn("Renderer: a layered material's picks and looks are refused on this device. They take " +
|
|
3571
|
+
'fifteen fragment uniform vectors the lit shader does not have, so its layers read layer ' +
|
|
3572
|
+
'i of its arrays, untinted, at one repeat each. A lower `maxLights` makes the room, or ' +
|
|
3573
|
+
'WebGPU has it.');
|
|
3574
|
+
}
|
|
3575
|
+
return false;
|
|
3576
|
+
}
|
|
3542
3577
|
/** Says once that a layered material's triplanar projection is laid on the horizontal plane. */
|
|
3543
3578
|
warnLayersTriplanar() {
|
|
3544
3579
|
if (this.warnedLayersTriplanar)
|
|
@@ -3547,9 +3582,14 @@ export class WebGL2Renderer {
|
|
|
3547
3582
|
console.warn("Renderer: a layered material's triplanar projection is laid on the horizontal plane: every " +
|
|
3548
3583
|
"layer's maps on three planes would be three times the reads. See `SurfaceMaterial.layers`.");
|
|
3549
3584
|
}
|
|
3550
|
-
/**
|
|
3551
|
-
|
|
3585
|
+
/**
|
|
3586
|
+
* Whether the lit shader with `feature` compiled in, and `beside` with it where a switch means
|
|
3587
|
+
* nothing alone, fits this GPU's fragment uniform vectors.
|
|
3588
|
+
*/
|
|
3589
|
+
switchFits(feature, beside) {
|
|
3552
3590
|
const asIf = { [feature]: true };
|
|
3591
|
+
if (beside !== undefined)
|
|
3592
|
+
asIf[beside] = true;
|
|
3553
3593
|
return (countUniformVectors(this.flatFragAt(this.lightBudget, asIf)) <= this.fragmentVectorLimit());
|
|
3554
3594
|
}
|
|
3555
3595
|
/**
|
|
@@ -4069,7 +4109,7 @@ export class WebGL2Renderer {
|
|
|
4069
4109
|
if (fog !== this.surfaceFog)
|
|
4070
4110
|
gl.uniform1i(u['uFogEnabled'] ?? null, fog);
|
|
4071
4111
|
if (!toneMapped)
|
|
4072
|
-
gl.uniform1i(u['uOutputTransform'] ?? null, Math.min(this.
|
|
4112
|
+
gl.uniform1i(u['uOutputTransform'] ?? null, Math.min(this.passGrade(), 1));
|
|
4073
4113
|
if (blend) {
|
|
4074
4114
|
gl.enable(gl.BLEND);
|
|
4075
4115
|
if (options.additive === true)
|
|
@@ -4140,7 +4180,7 @@ export class WebGL2Renderer {
|
|
|
4140
4180
|
if (fog !== this.surfaceFog)
|
|
4141
4181
|
gl.uniform1i(u['uFogEnabled'] ?? null, this.surfaceFog);
|
|
4142
4182
|
if (!toneMapped)
|
|
4143
|
-
gl.uniform1i(u['uOutputTransform'] ?? null, this.
|
|
4183
|
+
gl.uniform1i(u['uOutputTransform'] ?? null, this.passGrade());
|
|
4144
4184
|
if (own)
|
|
4145
4185
|
this.materials.dirty();
|
|
4146
4186
|
this.useFlatProgram();
|
|
@@ -4292,7 +4332,7 @@ export class WebGL2Renderer {
|
|
|
4292
4332
|
// raining dust into the sea.
|
|
4293
4333
|
const surface = env.underwater?.surfaceY;
|
|
4294
4334
|
const submerged = surface !== undefined && (camera.position[1] ?? 0) < surface;
|
|
4295
|
-
if (streaks.draw(this.gl, this.frameViewFor(camera), wind, timeSeconds, tint, submerged)) {
|
|
4335
|
+
if (streaks.draw(this.gl, this.frameViewFor(camera), wind, timeSeconds, tint, submerged, this.passGrade(), this.passGradeExposure())) {
|
|
4296
4336
|
this.windStreakBudget.ask();
|
|
4297
4337
|
}
|
|
4298
4338
|
}
|
|
@@ -4320,7 +4360,7 @@ export class WebGL2Renderer {
|
|
|
4320
4360
|
*/
|
|
4321
4361
|
drawText(text, viewportWidth, viewportHeight, originX, originY, style, timeSec) {
|
|
4322
4362
|
this.scatterSkin();
|
|
4323
|
-
if (text.draw(viewportWidth, viewportHeight, originX, originY, style, timeSec)) {
|
|
4363
|
+
if (text.draw(viewportWidth, viewportHeight, originX, originY, style, timeSec, interfaceGrade(this.passGrade()), 1)) {
|
|
4324
4364
|
this.textBudget.ask();
|
|
4325
4365
|
}
|
|
4326
4366
|
}
|
|
@@ -4387,7 +4427,9 @@ export class WebGL2Renderer {
|
|
|
4387
4427
|
* real draw call touches the unit in the first place.
|
|
4388
4428
|
*/
|
|
4389
4429
|
/**
|
|
4390
|
-
* The
|
|
4430
|
+
* The grade a pass applies to what it draws into the target open now, and the exposure it
|
|
4431
|
+
* applies it at. The decision is `passGrade.ts`'s, for both backends; this only gathers the
|
|
4432
|
+
* state it is taken from.
|
|
4391
4433
|
*
|
|
4392
4434
|
* **Only where that pass is genuinely the last one to touch the frame.** With a scene target
|
|
4393
4435
|
* the resolve grades, so a pass that graded as well would be applying a curve to its own
|
|
@@ -4395,20 +4437,34 @@ export class WebGL2Renderer {
|
|
|
4395
4437
|
* `screenEffects` off there is no resolve at all and every pass writes straight to the canvas,
|
|
4396
4438
|
* so each one has to grade itself or the frame comes out half converted: linear values in an
|
|
4397
4439
|
* eight-bit buffer read as display values, which is a saturated, clipped version of the colour
|
|
4398
|
-
* the caller asked for rather than a slightly different one.
|
|
4440
|
+
* the caller asked for rather than a slightly different one. A probe's face or a capture is
|
|
4441
|
+
* never graded, and past the present every pass grades itself, composite or not.
|
|
4399
4442
|
*
|
|
4400
4443
|
* One pair of accessors rather than the expression written out at each site, because that is
|
|
4401
4444
|
* how the mesh pass and the particle pass came to disagree in the first place: the mesh pass
|
|
4402
4445
|
* gated, and the particle pass uploaded the transform unconditionally to a stage that did not
|
|
4403
4446
|
* yet declare it.
|
|
4404
4447
|
*/
|
|
4405
|
-
|
|
4406
|
-
|
|
4407
|
-
|
|
4408
|
-
|
|
4448
|
+
passGrade() {
|
|
4449
|
+
const storing = this.probePassActive || this.capturePassActive;
|
|
4450
|
+
const transform = this.quality.outputTransform;
|
|
4451
|
+
return passGradeCode(storing, this.framePresented, this.resolveGrades(), transform);
|
|
4452
|
+
}
|
|
4453
|
+
passGradeExposure() {
|
|
4454
|
+
const storing = this.probePassActive || this.capturePassActive;
|
|
4455
|
+
return passGradeExposure(storing, this.framePresented, this.resolveGrades(), this.exposure);
|
|
4456
|
+
}
|
|
4457
|
+
/** Whether the frame's resolve applies the transform, so the passes before it draw linear. */
|
|
4458
|
+
resolveGrades() {
|
|
4459
|
+
return this.sceneTarget !== null && this.quality.hdrScene;
|
|
4409
4460
|
}
|
|
4410
|
-
|
|
4411
|
-
|
|
4461
|
+
/**
|
|
4462
|
+
* A clear colour as the target open now takes it: graded as a pass would grade it, so a colour
|
|
4463
|
+
* handed to the renderer is linear wherever it lands — the clear too, which the resolve grades
|
|
4464
|
+
* with everything else under `hdrScene`. See `gradeColor.ts`. Into one scratch, read at once.
|
|
4465
|
+
*/
|
|
4466
|
+
clearOf(color) {
|
|
4467
|
+
return gradeColorInto(this.passGrade(), this.passGradeExposure(), color, this.gradedClear);
|
|
4412
4468
|
}
|
|
4413
4469
|
drawSdfText(handle, model, color, opacity) {
|
|
4414
4470
|
this.scatterSkin();
|
|
@@ -4418,7 +4474,7 @@ export class WebGL2Renderer {
|
|
|
4418
4474
|
if (viewProj === null)
|
|
4419
4475
|
return;
|
|
4420
4476
|
/* Geometry, so the remapped matrix: `frameViewProj` itself stays raw for the motion blur. */
|
|
4421
|
-
if (handle.draw(this.sceneMatrix(viewProj), model, color, opacity, this.
|
|
4477
|
+
if (handle.draw(this.sceneMatrix(viewProj), model, color, opacity, this.passGrade(), this.passGradeExposure())) {
|
|
4422
4478
|
this.sdfTextBudget.ask();
|
|
4423
4479
|
this.restoreSurfaceTextureUnit();
|
|
4424
4480
|
}
|
|
@@ -4432,7 +4488,7 @@ export class WebGL2Renderer {
|
|
|
4432
4488
|
}
|
|
4433
4489
|
drawFlock(flock, camera, timeSeconds, params, tint, windX = 0, windZ = 0) {
|
|
4434
4490
|
this.flockBudget.ask();
|
|
4435
|
-
flock.draw(this.gl, this.frameViewFor(camera), timeSeconds, params, tint, windX, windZ);
|
|
4491
|
+
flock.draw(this.gl, this.frameViewFor(camera), timeSeconds, params, tint, windX, windZ, this.passGrade(), this.passGradeExposure());
|
|
4436
4492
|
}
|
|
4437
4493
|
/**
|
|
4438
4494
|
* Build a scatter batch and fill it. Takes the data rather than handing back
|
|
@@ -4516,8 +4572,8 @@ export class WebGL2Renderer {
|
|
|
4516
4572
|
the uniform at all, so it was a write to a location that did not exist; now that the
|
|
4517
4573
|
stage grades itself it has to obey the same "only where this pass is last" rule the mesh
|
|
4518
4574
|
pass does, or a scene with a composite grades its particles twice. */
|
|
4519
|
-
gl.uniform1i(u['uOutputTransform'] ?? null, this.
|
|
4520
|
-
gl.uniform1f(u['uOutputExposure'] ?? null, this.
|
|
4575
|
+
gl.uniform1i(u['uOutputTransform'] ?? null, this.passGrade());
|
|
4576
|
+
gl.uniform1f(u['uOutputExposure'] ?? null, this.passGradeExposure());
|
|
4521
4577
|
gl.uniform3fv(u['uAmbient'] ?? null, env.ambient);
|
|
4522
4578
|
gl.uniform3fv(u['uAmbientGround'] ?? null, env.ambientGround ?? env.ambient);
|
|
4523
4579
|
gl.uniform1i(u['uNoiseOctaves'] ?? null, this.quality.plumeNoiseOctaves);
|
|
@@ -4595,6 +4651,8 @@ export class WebGL2Renderer {
|
|
|
4595
4651
|
gl.uniform3fv(u['uCoreColor'] ?? null, core);
|
|
4596
4652
|
gl.uniform3fv(u['uEdgeColor'] ?? null, edge);
|
|
4597
4653
|
gl.uniform1f(u['uCoreGain'] ?? null, coreGain);
|
|
4654
|
+
gl.uniform1i(u['uOutputTransform'] ?? null, this.passGrade());
|
|
4655
|
+
gl.uniform1f(u['uOutputExposure'] ?? null, this.passGradeExposure());
|
|
4598
4656
|
bindAtmosphere(gl, u, env, this.reflectionPassActive ? this.reflectionAtmosphereY : (camera.position[1] ?? 0), this.quality.underwaterAtmosphere);
|
|
4599
4657
|
batch.drawTo(gl, count);
|
|
4600
4658
|
}
|
|
@@ -4652,8 +4710,8 @@ export class WebGL2Renderer {
|
|
|
4652
4710
|
gl.uniform3fv(u['uColor'] ?? null, color);
|
|
4653
4711
|
gl.uniform1f(u['uOpacity'] ?? null, opacity);
|
|
4654
4712
|
gl.uniform1f(u['uSoftness'] ?? null, softness);
|
|
4655
|
-
gl.uniform1i(u['uOutputTransform'] ?? null, this.
|
|
4656
|
-
gl.uniform1f(u['uOutputExposure'] ?? null, this.
|
|
4713
|
+
gl.uniform1i(u['uOutputTransform'] ?? null, this.passGrade());
|
|
4714
|
+
gl.uniform1f(u['uOutputExposure'] ?? null, this.passGradeExposure());
|
|
4657
4715
|
bindAtmosphere(gl, u, env, this.reflectionPassActive ? this.reflectionAtmosphereY : (camera.position[1] ?? 0), this.quality.underwaterAtmosphere);
|
|
4658
4716
|
lines.drawTo(gl, count, additive);
|
|
4659
4717
|
}
|
|
@@ -4686,6 +4744,8 @@ export class WebGL2Renderer {
|
|
|
4686
4744
|
gl.uniform3fv(u['uDirectionalColor'] ?? null, env.directionalColor);
|
|
4687
4745
|
gl.uniform3fv(u['uAmbient'] ?? null, env.ambient);
|
|
4688
4746
|
gl.uniform3fv(u['uCameraPos'] ?? null, camera.position);
|
|
4747
|
+
gl.uniform1i(u['uOutputTransform'] ?? null, this.passGrade());
|
|
4748
|
+
gl.uniform1f(u['uOutputExposure'] ?? null, this.passGradeExposure());
|
|
4689
4749
|
bindAtmosphere(gl, u, env, this.reflectionPassActive ? this.reflectionAtmosphereY : (camera.position[1] ?? 0), this.quality.underwaterAtmosphere);
|
|
4690
4750
|
// Foliage is thin and seen from both faces; culling it loses half of it.
|
|
4691
4751
|
gl.disable(gl.CULL_FACE);
|
|
@@ -4819,13 +4879,13 @@ export class WebGL2Renderer {
|
|
|
4819
4879
|
// --- Draws that own their context ----------------------------------------
|
|
4820
4880
|
drawPlumes(plumes, camera, timeSeconds, env, windX = 0, windZ = 0, originX = 0, originY = 0, originZ = 0) {
|
|
4821
4881
|
this.scatterSkin();
|
|
4822
|
-
plumes.draw(this.gl, this.frameViewFor(camera), timeSeconds, env, this.quality.underwaterAtmosphere, this.reflectionPassActive ? this.reflectionAtmosphereY : (camera.position[1] ?? 0), this.reflectionPassActive ? (this.planarReflection?.clipPlane ?? null) : null, windX, windZ, originX, originY, originZ);
|
|
4882
|
+
plumes.draw(this.gl, this.frameViewFor(camera), timeSeconds, env, this.quality.underwaterAtmosphere, this.reflectionPassActive ? this.reflectionAtmosphereY : (camera.position[1] ?? 0), this.reflectionPassActive ? (this.planarReflection?.clipPlane ?? null) : null, windX, windZ, originX, originY, originZ, this.passGrade(), this.passGradeExposure());
|
|
4823
4883
|
}
|
|
4824
4884
|
drawWater(water, camera, timeSeconds, settings, env, windX = 0, windZ = 0) {
|
|
4825
4885
|
if (!this.quality.water)
|
|
4826
4886
|
return;
|
|
4827
4887
|
this.waterBudget.ask();
|
|
4828
|
-
water.draw(this.gl, this.frameViewFor(camera), timeSeconds, settings, env.directionalDir, env.directionalColor, env.ambient, env, this.quality.underwaterAtmosphere, this.reflectionReadyThisFrame ? this.planarReflection : null, env, this.quality.pointLightFalloff, windX, windZ);
|
|
4888
|
+
water.draw(this.gl, this.frameViewFor(camera), timeSeconds, settings, env.directionalDir, env.directionalColor, env.ambient, env, this.quality.underwaterAtmosphere, this.reflectionReadyThisFrame ? this.planarReflection : null, env, this.quality.pointLightFalloff, windX, windZ, this.passGrade(), this.passGradeExposure());
|
|
4829
4889
|
}
|
|
4830
4890
|
/**
|
|
4831
4891
|
* Draw after the opaque scene: this is light added to surfaces already shaded,
|
|
@@ -4835,7 +4895,7 @@ export class WebGL2Renderer {
|
|
|
4835
4895
|
this.scatterSkin();
|
|
4836
4896
|
if (caustics === null || !this.quality.water)
|
|
4837
4897
|
return;
|
|
4838
|
-
const drew = caustics.draw(this.gl, this.frameViewFor(camera), timeSeconds, env.directionalDir, env.directionalColor, env.ambient, env, this.quality.underwaterAtmosphere, windX, windZ, strength);
|
|
4898
|
+
const drew = caustics.draw(this.gl, this.frameViewFor(camera), timeSeconds, env.directionalDir, env.directionalColor, env.ambient, env, this.quality.underwaterAtmosphere, windX, windZ, strength, this.passGrade(), this.passGradeExposure());
|
|
4839
4899
|
if (drew)
|
|
4840
4900
|
this.causticsBudget.ask();
|
|
4841
4901
|
}
|
|
@@ -4872,7 +4932,7 @@ export class WebGL2Renderer {
|
|
|
4872
4932
|
return null;
|
|
4873
4933
|
this.reflectionReadyThisFrame = false;
|
|
4874
4934
|
this.reflectionAtmosphereY = source.position[1] ?? 0;
|
|
4875
|
-
const camera = reflection.begin(this.gl, this.canvas.width, this.canvas.height, source, planeY, clearColor);
|
|
4935
|
+
const camera = reflection.begin(this.gl, this.canvas.width, this.canvas.height, source, planeY, this.clearOf(clearColor));
|
|
4876
4936
|
this.gpuTimer.begin('reflection');
|
|
4877
4937
|
this.reflectionPassActive = true;
|
|
4878
4938
|
return camera;
|
|
@@ -5495,6 +5555,7 @@ export class WebGL2Renderer {
|
|
|
5495
5555
|
worldUvs: asIf.WORLD_UVS ?? this.litOn.WORLD_UVS,
|
|
5496
5556
|
movingSun: asIf.MOVING_SUN ?? this.litOn.MOVING_SUN,
|
|
5497
5557
|
layered: asIf.LAYERED ?? this.litOn.LAYERED,
|
|
5558
|
+
layerLooks: asIf.LAYER_LOOKS ?? this.litOn.LAYER_LOOKS,
|
|
5498
5559
|
maxLights: budget.maxLights,
|
|
5499
5560
|
maxAreaLights: budget.maxAreaLights,
|
|
5500
5561
|
});
|
|
@@ -6009,7 +6070,8 @@ export class WebGL2Renderer {
|
|
|
6009
6070
|
gl.clear(gl.DEPTH_BUFFER_BIT);
|
|
6010
6071
|
}
|
|
6011
6072
|
else {
|
|
6012
|
-
|
|
6073
|
+
const clear = this.clearOf(clearColor);
|
|
6074
|
+
gl.clearColor(clear[0], clear[1], clear[2], 1);
|
|
6013
6075
|
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
|
6014
6076
|
}
|
|
6015
6077
|
/*
|
|
@@ -6103,6 +6165,9 @@ export class WebGL2Renderer {
|
|
|
6103
6165
|
gl.uniformMatrix4fv(this.panelUniforms['uClipCorrection'] ?? null, false, IDENTITY_MAT4);
|
|
6104
6166
|
gl.uniform3fv(this.panelUniforms['uColor'] ?? null, color);
|
|
6105
6167
|
gl.uniform1f(this.panelUniforms['uAlpha'] ?? null, alpha);
|
|
6168
|
+
/* An interface: the screen encode, never the curve. See `interfaceGrade`. */
|
|
6169
|
+
gl.uniform1i(this.panelUniforms['uOutputTransform'] ?? null, interfaceGrade(this.passGrade()));
|
|
6170
|
+
gl.uniform1f(this.panelUniforms['uOutputExposure'] ?? null, 1);
|
|
6106
6171
|
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
|
6107
6172
|
gl.bindVertexArray(null);
|
|
6108
6173
|
gl.depthMask(true);
|
|
@@ -6785,7 +6850,8 @@ export class WebGL2Renderer {
|
|
|
6785
6850
|
this.sceneTarget?.begin(this.canvas.width, this.canvas.height);
|
|
6786
6851
|
/* The materials' maps on the scene's framebuffer, cleared and disabled: `reflectionKeeps`. */
|
|
6787
6852
|
this.reflectionTargets?.begin(this.canvas.width, this.canvas.height);
|
|
6788
|
-
|
|
6853
|
+
const clear = this.clearOf(clearColor);
|
|
6854
|
+
gl.clearColor(clear[0], clear[1], clear[2], 1);
|
|
6789
6855
|
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
|
6790
6856
|
}
|
|
6791
6857
|
/**
|
|
@@ -6920,7 +6986,7 @@ export class WebGL2Renderer {
|
|
|
6920
6986
|
exposure: this.exposure,
|
|
6921
6987
|
film: this.filmConstants,
|
|
6922
6988
|
}
|
|
6923
|
-
: { transform: 0, exposure: 1 };
|
|
6989
|
+
: { transform: 0, exposure: 1, sceneGraded: this.passGrade() !== 0 };
|
|
6924
6990
|
/*
|
|
6925
6991
|
* Depth of field, on the same ceiling-and-dial split as bloom above: `depthOfField` decides
|
|
6926
6992
|
* how far a defocused point may spread and this frame's `setDepthOfField` decides where the
|
|
@@ -6970,7 +7036,7 @@ export class WebGL2Renderer {
|
|
|
6970
7036
|
else if (this.sceneTarget !== null) {
|
|
6971
7037
|
this.decals ??= new DecalPass(this.gl);
|
|
6972
7038
|
this.sceneTarget.bind();
|
|
6973
|
-
this.decals.drawDecals(this.decalQueue, marks, this.frameViewProj, this.frameEye, this.canvas.width, this.canvas.height);
|
|
7039
|
+
this.decals.drawDecals(this.decalQueue, marks, this.frameViewProj, this.frameEye, this.canvas.width, this.canvas.height, this.passGrade());
|
|
6974
7040
|
}
|
|
6975
7041
|
}
|
|
6976
7042
|
/*
|
|
@@ -7122,7 +7188,7 @@ export class WebGL2Renderer {
|
|
|
7122
7188
|
/* The march finished on the default framebuffer, which is not where the frame is being
|
|
7123
7189
|
drawn. See `resolveReflections`, which is the same two-step for the same reason. */
|
|
7124
7190
|
this.sceneTarget.bind();
|
|
7125
|
-
this.medium.compositeMedium(depthCopy, this.canvas.width, this.canvas.height);
|
|
7191
|
+
this.medium.compositeMedium(depthCopy, this.canvas.width, this.canvas.height, this.passGrade(), this.passGradeExposure());
|
|
7126
7192
|
}
|
|
7127
7193
|
}
|
|
7128
7194
|
}
|
|
@@ -7351,6 +7417,7 @@ export class WebGL2Renderer {
|
|
|
7351
7417
|
resolveTransmission(null, this.transmission);
|
|
7352
7418
|
/* Nor layers: one layer until a material asks for more. */
|
|
7353
7419
|
this.layerFloats.fill(0);
|
|
7420
|
+
this.lookFloats.fill(0);
|
|
7354
7421
|
this.overlayMaps = null;
|
|
7355
7422
|
this.overlayTexture = null;
|
|
7356
7423
|
/* Nor an ambient of its own: the frame's, until a draw asks. See `setAmbientSH`. */
|
|
@@ -7494,6 +7561,7 @@ export class WebGL2Renderer {
|
|
|
7494
7561
|
gl.uniform4fv(u['uOverlay'] ?? null, this.overlayFloats);
|
|
7495
7562
|
gl.uniform4fv(u['uWorldUv'] ?? null, this.projection);
|
|
7496
7563
|
gl.uniform4fv(u['uLayers'] ?? null, this.layerFloats);
|
|
7564
|
+
gl.uniform4fv(u['uLayerLooks'] ?? null, this.lookFloats);
|
|
7497
7565
|
/* Neither refracting nor glass, which is every draw that does not say otherwise. See
|
|
7498
7566
|
`bindSeeThrough` for the four numbers in the one vector. */
|
|
7499
7567
|
gl.uniform4f(u['uSeeThrough'] ?? null, 0, 0, 0, 0);
|
|
@@ -7541,12 +7609,11 @@ export class WebGL2Renderer {
|
|
|
7541
7609
|
* exists to keep. With `screenEffects` off there is no resolve at all and the mesh pass
|
|
7542
7610
|
* writes straight to the canvas, so it stays where it always was.
|
|
7543
7611
|
*
|
|
7544
|
-
*
|
|
7545
|
-
*
|
|
7546
|
-
* inconsistency that existed everywhere before this moved.
|
|
7612
|
+
* Every other pass grades through the same gate, `passGrade`, so a frame without a composite
|
|
7613
|
+
* is graded pass by pass to the curve a composite would have applied once.
|
|
7547
7614
|
*/
|
|
7548
|
-
gl.uniform1i(u['uOutputTransform'] ?? null, this.
|
|
7549
|
-
gl.uniform1f(u['uOutputExposure'] ?? null, this.
|
|
7615
|
+
gl.uniform1i(u['uOutputTransform'] ?? null, this.passGrade());
|
|
7616
|
+
gl.uniform1f(u['uOutputExposure'] ?? null, this.passGradeExposure());
|
|
7550
7617
|
gl.uniform3fv(u['uCameraPos'] ?? null, camera.position);
|
|
7551
7618
|
/*
|
|
7552
7619
|
* Solid, every frame, before anything asks otherwise. A GL uniform starts at
|
|
@@ -7999,7 +8066,7 @@ export class WebGL2Renderer {
|
|
|
7999
8066
|
return;
|
|
8000
8067
|
const depth = scene.snapshotDepth(true);
|
|
8001
8068
|
mat4.invert(this.skinInverseProjection, projection);
|
|
8002
|
-
skin.spread(scene, depth, this.emptyTexture2D, projection, this.skinInverseProjection);
|
|
8069
|
+
skin.spread(scene, depth, this.emptyTexture2D, projection, this.skinInverseProjection, this.passGrade(), this.passGradeExposure());
|
|
8003
8070
|
this.useFlatProgram();
|
|
8004
8071
|
}
|
|
8005
8072
|
/** One draw of a mesh, as `drawMesh` describes, of the half of a skin `half` names. */
|
|
@@ -8322,7 +8389,7 @@ export class WebGL2Renderer {
|
|
|
8322
8389
|
means rather than dropping the whole transform. `Math.min` rather than a literal, so a
|
|
8323
8390
|
renderer asked for `none` stays at none and one asked for `srgb` is already there. */
|
|
8324
8391
|
if (!toneMapped)
|
|
8325
|
-
gl.uniform1i(u['uOutputTransform'] ?? null, Math.min(this.
|
|
8392
|
+
gl.uniform1i(u['uOutputTransform'] ?? null, Math.min(this.passGrade(), 1));
|
|
8326
8393
|
/* Scoped and handed back like every other state here, so a tinted draw cannot leak its
|
|
8327
8394
|
colour onto the next one. See `TranslucentMeshOptions.tint`. */
|
|
8328
8395
|
const tint = options.tint ?? null;
|
|
@@ -8407,7 +8474,7 @@ export class WebGL2Renderer {
|
|
|
8407
8474
|
if (fog !== this.surfaceFog)
|
|
8408
8475
|
gl.uniform1i(u['uFogEnabled'] ?? null, this.surfaceFog);
|
|
8409
8476
|
if (!toneMapped)
|
|
8410
|
-
gl.uniform1i(u['uOutputTransform'] ?? null, this.
|
|
8477
|
+
gl.uniform1i(u['uOutputTransform'] ?? null, this.passGrade());
|
|
8411
8478
|
if (own)
|
|
8412
8479
|
this.materials.dirty();
|
|
8413
8480
|
}
|
|
@@ -8496,7 +8563,7 @@ export class WebGL2Renderer {
|
|
|
8496
8563
|
/*
|
|
8497
8564
|
* **A probe stores radiance, not display pixels.**
|
|
8498
8565
|
*
|
|
8499
|
-
* `
|
|
8566
|
+
* `passGrade()` is the ACES curve and the sRGB encode whenever the frame has no HDR target,
|
|
8500
8567
|
* so every face was baked through the whole output transform and the shader then sampled the
|
|
8501
8568
|
* result as though it were light. Two things came of that and both read as "the reflection is
|
|
8502
8569
|
* dull": the curve pulls everything bright toward 1 *before* it reaches the cube, so no
|
|
@@ -8546,16 +8613,17 @@ export class WebGL2Renderer {
|
|
|
8546
8613
|
}
|
|
8547
8614
|
finally {
|
|
8548
8615
|
this.gl.frontFace(this.gl.CCW);
|
|
8549
|
-
this.useFlatProgram();
|
|
8550
|
-
this.gl.uniform1i(this.flatUniforms['uOutputTransform'] ?? null, this.gradeCode());
|
|
8551
|
-
this.gl.uniform1f(this.flatUniforms['uOutputExposure'] ?? null, this.gradeExposure());
|
|
8552
|
-
this.materials.dirty();
|
|
8553
8616
|
/*
|
|
8554
8617
|
* Cleared even if a caller's own draw threw, because leaving this set would keep every
|
|
8555
|
-
* later frame reading the placeholder and quietly reflecting nothing.
|
|
8618
|
+
* later frame reading the placeholder and quietly reflecting nothing. Before the grade is
|
|
8619
|
+
* put back, which asks it.
|
|
8556
8620
|
*/
|
|
8557
8621
|
this.probePassActive = false;
|
|
8558
8622
|
this.probeBounce = false;
|
|
8623
|
+
this.useFlatProgram();
|
|
8624
|
+
this.gl.uniform1i(this.flatUniforms['uOutputTransform'] ?? null, this.passGrade());
|
|
8625
|
+
this.gl.uniform1f(this.flatUniforms['uOutputExposure'] ?? null, this.passGradeExposure());
|
|
8626
|
+
this.materials.dirty();
|
|
8559
8627
|
/* Back to the canvas, or to the frame's own target if one is bound. See `SceneTarget`. */
|
|
8560
8628
|
if (this.sceneTarget !== null && !this.framePresented)
|
|
8561
8629
|
this.sceneTarget.bind();
|
|
@@ -8739,6 +8807,8 @@ export class WebGL2Renderer {
|
|
|
8739
8807
|
gl.uniformMatrix4fv(u['uModel'] ?? null, false, model);
|
|
8740
8808
|
gl.uniform3fv(u['uCameraPos'] ?? null, camera.position);
|
|
8741
8809
|
gl.uniform1f(u['uStrength'] ?? null, Math.min(shown, 1));
|
|
8810
|
+
gl.uniform1i(u['uOutputTransform'] ?? null, this.passGrade());
|
|
8811
|
+
gl.uniform1f(u['uOutputExposure'] ?? null, this.passGradeExposure());
|
|
8742
8812
|
gl.uniform1f(u['uLength'] ?? null, length);
|
|
8743
8813
|
gl.uniform1f(u['uSpread'] ?? null, spread);
|
|
8744
8814
|
gl.uniform1f(u['uDust'] ?? null, clamp(options.dust ?? 0, 0, 1));
|
|
@@ -8871,6 +8941,8 @@ export class WebGL2Renderer {
|
|
|
8871
8941
|
gl.uniform3fv(u['uCameraPos'] ?? null, camera.position);
|
|
8872
8942
|
gl.uniform1f(u['uTime'] ?? null, timeSeconds);
|
|
8873
8943
|
gl.uniform1f(u['uSheen'] ?? null, sheen);
|
|
8944
|
+
gl.uniform1i(u['uOutputTransform'] ?? null, this.passGrade());
|
|
8945
|
+
gl.uniform1f(u['uOutputExposure'] ?? null, this.passGradeExposure());
|
|
8874
8946
|
gl.uniform1f(u['uFilmRoughness'] ?? null, Math.min(1, Math.max(0, options.roughness ?? 0)));
|
|
8875
8947
|
gl.uniform1f(u['uFilmRoughnessCycles'] ?? null, Math.max(0.01, options.roughnessCyclesPerMetre ?? 60));
|
|
8876
8948
|
gl.uniform1i(u['uClipEnabled'] ?? null, this.reflectionPassActive ? 1 : 0);
|
|
@@ -8914,6 +8986,8 @@ export class WebGL2Renderer {
|
|
|
8914
8986
|
gl.uniform1f(u['uMoonPhase'] ?? null, sky.moonPhase);
|
|
8915
8987
|
gl.uniform1f(u['uNightFactor'] ?? null, sky.nightFactor);
|
|
8916
8988
|
gl.uniform2f(u['uCloudOffset'] ?? null, sky.cloudOffsetX, sky.cloudOffsetZ);
|
|
8989
|
+
gl.uniform1i(u['uOutputTransform'] ?? null, this.passGrade());
|
|
8990
|
+
gl.uniform1f(u['uOutputExposure'] ?? null, this.passGradeExposure());
|
|
8917
8991
|
bindAtmosphere(gl, u, env, this.reflectionPassActive ? this.reflectionAtmosphereY : (camera.position[1] ?? 0), this.quality.underwaterAtmosphere);
|
|
8918
8992
|
gl.bindVertexArray(this.skyVao);
|
|
8919
8993
|
gl.depthMask(false);
|
|
@@ -46,7 +46,9 @@ export declare class GlSkinScatter {
|
|
|
46
46
|
* is the frame's depth as a single-sampled texture, or null where none could be had — and then
|
|
47
47
|
* the diffuse goes back unspread rather than not at all, so the skin keeps its light.
|
|
48
48
|
*/
|
|
49
|
-
spread(scene: SceneTarget, depth: WebGLTexture | null, empty: WebGLTexture, projection: ArrayLike<number>, inverse: ArrayLike<number
|
|
49
|
+
spread(scene: SceneTarget, depth: WebGLTexture | null, empty: WebGLTexture, projection: ArrayLike<number>, inverse: ArrayLike<number>,
|
|
50
|
+
/** The frame's grade, which the second axis applies to the light it adds. */
|
|
51
|
+
outputTransform?: number, outputExposure?: number): void;
|
|
50
52
|
/** Spent at the frame's start: what was drawn into the target was last frame's. */
|
|
51
53
|
reset(): void;
|
|
52
54
|
/** A multisampled target into its single-sampled texture. */
|
|
@@ -123,7 +123,9 @@ export class GlSkinScatter {
|
|
|
123
123
|
* is the frame's depth as a single-sampled texture, or null where none could be had — and then
|
|
124
124
|
* the diffuse goes back unspread rather than not at all, so the skin keeps its light.
|
|
125
125
|
*/
|
|
126
|
-
spread(scene, depth, empty, projection, inverse
|
|
126
|
+
spread(scene, depth, empty, projection, inverse,
|
|
127
|
+
/** The frame's grade, which the second axis applies to the light it adds. */
|
|
128
|
+
outputTransform = 0, outputExposure = 1) {
|
|
127
129
|
const { gl } = this;
|
|
128
130
|
if (this.multisampled !== null) {
|
|
129
131
|
this.resolve(this.drawFramebuffer, this.resolveFramebuffer);
|
|
@@ -139,6 +141,8 @@ export class GlSkinScatter {
|
|
|
139
141
|
gl.uniform1i(u['uSkin'] ?? null, SKIN_BLUR_TEXTURE_UNIT);
|
|
140
142
|
gl.uniform1i(u['uDepth'] ?? null, SKIN_BLUR_DEPTH_UNIT);
|
|
141
143
|
gl.uniform1i(u['uAlbedo'] ?? null, SKIN_BLUR_ALBEDO_UNIT);
|
|
144
|
+
gl.uniform1i(u['uOutputTransform'] ?? null, outputTransform);
|
|
145
|
+
gl.uniform1f(u['uOutputExposure'] ?? null, outputExposure);
|
|
142
146
|
gl.activeTexture(gl.TEXTURE0 + SKIN_BLUR_ALBEDO_UNIT);
|
|
143
147
|
gl.bindTexture(gl.TEXTURE_2D, this.albedo ?? empty);
|
|
144
148
|
/* The four terms that carry a depth back to view-space metres: the occlusion blur's own. */
|
|
@@ -11,7 +11,7 @@ import type { PipelineCache } from './pipelineCache.ts';
|
|
|
11
11
|
export declare const BOLT_VERT_FIELDS: UniformFields;
|
|
12
12
|
export declare const BOLT_VERT_SIZE: 96;
|
|
13
13
|
export declare const BOLT_FRAG_FIELDS: UniformFields;
|
|
14
|
-
export declare const BOLT_FRAG_SIZE:
|
|
14
|
+
export declare const BOLT_FRAG_SIZE: 144;
|
|
15
15
|
/** A batch of arcs on the device, behind the surface's opaque handle. */
|
|
16
16
|
export interface GpuBolts {
|
|
17
17
|
readonly fromBuffer: GPUBuffer;
|
|
@@ -10,7 +10,7 @@ import type { PipelineCache } from './pipelineCache.ts';
|
|
|
10
10
|
export declare const CAUSTICS_VERT_FIELDS: UniformFields;
|
|
11
11
|
export declare const CAUSTICS_VERT_SIZE: 64;
|
|
12
12
|
export declare const CAUSTICS_FRAG_FIELDS: UniformFields;
|
|
13
|
-
export declare const CAUSTICS_FRAG_SIZE:
|
|
13
|
+
export declare const CAUSTICS_FRAG_SIZE: 160;
|
|
14
14
|
/** A lit surface on the device, behind the API's opaque handle. */
|
|
15
15
|
export interface GpuCaustics {
|
|
16
16
|
readonly vertexBuffers: readonly GPUBuffer[];
|
|
@@ -14,7 +14,7 @@ import type { PipelineCache } from './pipelineCache.ts';
|
|
|
14
14
|
export declare const FILM_VERT_FIELDS: UniformFields;
|
|
15
15
|
export declare const FILM_VERT_SIZE: 128;
|
|
16
16
|
export declare const FILM_FRAG_FIELDS: UniformFields;
|
|
17
|
-
export declare const FILM_FRAG_SIZE:
|
|
17
|
+
export declare const FILM_FRAG_SIZE: 160;
|
|
18
18
|
export declare function createFilmBindGroupLayout(device: GPUDevice): GPUBindGroupLayout;
|
|
19
19
|
/** Bound once against both rings; a dynamic offset per film. See `createPanelBindGroup`. */
|
|
20
20
|
export declare function createFilmBindGroup(device: GPUDevice, layout: GPUBindGroupLayout, vertices: GPUBuffer, fragments: GPUBuffer, reflection: GPUTextureView, sampler: GPUSampler): GPUBindGroup;
|
|
@@ -10,7 +10,7 @@ import type { PipelineCache } from './pipelineCache.ts';
|
|
|
10
10
|
export declare const FLOCK_VERT_FIELDS: UniformFields;
|
|
11
11
|
export declare const FLOCK_VERT_SIZE: 112;
|
|
12
12
|
export declare const FLOCK_FRAG_FIELDS: UniformFields;
|
|
13
|
-
export declare const FLOCK_FRAG_SIZE:
|
|
13
|
+
export declare const FLOCK_FRAG_SIZE: 32;
|
|
14
14
|
/** A flock on the device, behind the surface's opaque handle. */
|
|
15
15
|
export interface GpuFlock {
|
|
16
16
|
readonly corners: GPUBuffer;
|
|
@@ -19,7 +19,9 @@ import type { PassContext, PassDefinition, PassDevice, PrepareContext } from '..
|
|
|
19
19
|
* can look at, and looking is what a number cannot replace: if the geometry is in the right places
|
|
20
20
|
* at the right sizes the composition is right, and if a cascade boundary shows as a seam the fade
|
|
21
21
|
* is wrong. Wave 4A's own recorded failure — a phantom surface that passed 111,907 parity samples
|
|
22
|
-
* and was found by looking at a picture — is why this exists at all.
|
|
22
|
+
* and was found by looking at a picture — is why this exists at all. **So it is not graded**, alone
|
|
23
|
+
* of the passes that draw into a frame: what it shows are the field's values, which a curve would
|
|
24
|
+
* bend into a picture of something else.
|
|
23
25
|
*
|
|
24
26
|
* **The field it marches is one frame old**, because the renderer composes at `endFrame` and
|
|
25
27
|
* `prepare` runs at `beginFrame`. `PrepareContext.distanceField` says why that is right rather
|
|
@@ -660,7 +660,16 @@ export declare class GpuDrivenPass implements PassDefinition {
|
|
|
660
660
|
private readonly scheduled;
|
|
661
661
|
private readonly graphScratch;
|
|
662
662
|
private readonly shape;
|
|
663
|
-
|
|
663
|
+
/**
|
|
664
|
+
* The frame's grade for the blit, `PassContext.outputTransform` and its exposure, and the code it
|
|
665
|
+
* was last written with, so a frame writes it only when it changes. See `present.wgsl.ts`.
|
|
666
|
+
*/
|
|
667
|
+
private gradeBuffer;
|
|
668
|
+
private readonly gradeStaging;
|
|
669
|
+
private readonly gradeInts;
|
|
670
|
+
private readonly gradeFloats;
|
|
671
|
+
private gradeWrittenCode;
|
|
672
|
+
private gradeWrittenExposure;
|
|
664
673
|
constructor(scene: StreamingScene, materials: readonly GpuDrivenMaterial[], shadow?: GpuDrivenShadowOptions);
|
|
665
674
|
/** How many clusters the scene holds, which every per-cluster dispatch is sized by. */
|
|
666
675
|
get clusterCount(): number;
|