@driftengine/core 4.8.7 → 4.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.json +123 -11
- package/README.md +43 -38
- package/dist/index.d.ts +8 -1
- package/dist/index.js +11 -3
- package/dist/render/ambientHarmonics.d.ts +1 -1
- package/dist/render/ambientHarmonics.js +1 -1
- package/dist/render/areaLights.d.ts +4 -4
- package/dist/render/areaLights.js +1 -1
- package/dist/render/atmosphere.d.ts +13 -0
- package/dist/render/atmosphere.js +9 -1
- package/dist/render/backend/api.d.ts +19 -4
- package/dist/render/backend/createRenderer.d.ts +6 -0
- package/dist/render/backend/createRenderer.js +4 -1
- package/dist/render/backend/select.js +11 -5
- package/dist/render/backend/webgl2/boneAnimations.d.ts +29 -0
- package/dist/render/backend/webgl2/boneAnimations.js +80 -0
- package/dist/render/backend/webgl2/instanced.d.ts +5 -1
- package/dist/render/backend/webgl2/instanced.js +13 -1
- package/dist/render/backend/webgl2/renderer.d.ts +180 -4
- package/dist/render/backend/webgl2/renderer.js +550 -40
- package/dist/render/backend/webgl2/skinPaletteTexture.d.ts +5 -3
- package/dist/render/backend/webgl2/skinPaletteTexture.js +6 -4
- package/dist/render/backend/webgpu/boneAnimations.d.ts +34 -0
- package/dist/render/backend/webgpu/boneAnimations.js +76 -0
- package/dist/render/backend/webgpu/buffers.d.ts +19 -4
- package/dist/render/backend/webgpu/buffers.js +18 -11
- package/dist/render/backend/webgpu/compressedUpload.d.ts +0 -1
- package/dist/render/backend/webgpu/compressedUpload.js +53 -8
- package/dist/render/backend/webgpu/depthPass.d.ts +59 -3
- package/dist/render/backend/webgpu/depthPass.js +49 -14
- package/dist/render/backend/webgpu/device.d.ts +7 -1
- package/dist/render/backend/webgpu/device.js +31 -3
- package/dist/render/backend/webgpu/drawCommand.d.ts +18 -4
- package/dist/render/backend/webgpu/drawCommand.js +10 -3
- package/dist/render/backend/webgpu/flatPass.d.ts +100 -42
- package/dist/render/backend/webgpu/flatPass.js +191 -43
- package/dist/render/backend/webgpu/instanced.d.ts +14 -1
- package/dist/render/backend/webgpu/instanced.js +24 -1
- package/dist/render/backend/webgpu/materialStore.d.ts +101 -0
- package/dist/render/backend/webgpu/materialStore.js +265 -0
- package/dist/render/backend/webgpu/pipelineCache.d.ts +6 -0
- package/dist/render/backend/webgpu/pipelineCache.js +7 -0
- package/dist/render/backend/webgpu/postPass.d.ts +51 -9
- package/dist/render/backend/webgpu/postPass.js +16 -2
- package/dist/render/backend/webgpu/reflectionSurfacePass.d.ts +30 -0
- package/dist/render/backend/webgpu/reflectionSurfacePass.js +100 -0
- package/dist/render/backend/webgpu/renderer.d.ts +283 -37
- package/dist/render/backend/webgpu/renderer.js +1363 -202
- package/dist/render/backend/webgpu/skinPaletteRing.d.ts +7 -3
- package/dist/render/backend/webgpu/skinPaletteRing.js +13 -7
- package/dist/render/backend/webgpu/skinPaletteTexture.d.ts +6 -0
- package/dist/render/backend/webgpu/skinPaletteTexture.js +7 -1
- package/dist/render/backend/webgpu/staticBundles.d.ts +125 -0
- package/dist/render/backend/webgpu/staticBundles.js +241 -0
- package/dist/render/backend/webgpu/surfaceTexturePass.d.ts +10 -3
- package/dist/render/backend/webgpu/surfaceTexturePass.js +20 -2
- package/dist/render/backend/webgpu/uniformRing.d.ts +21 -0
- package/dist/render/backend/webgpu/uniformRing.js +9 -1
- package/dist/render/bloomChain.d.ts +3 -3
- package/dist/render/boneAnimation.d.ts +92 -0
- package/dist/render/boneAnimation.js +133 -0
- package/dist/render/compressedSource.d.ts +33 -13
- package/dist/render/compressedSource.js +70 -25
- package/dist/render/displayRange.d.ts +31 -0
- package/dist/render/displayRange.js +47 -0
- package/dist/render/filmicCurve.d.ts +74 -0
- package/dist/render/filmicCurve.js +203 -0
- package/dist/render/fog.d.ts +4 -1
- package/dist/render/fog.js +12 -2
- package/dist/render/frame/resources.d.ts +2 -2
- package/dist/render/frame/resources.js +6 -0
- package/dist/render/frameReflections.d.ts +40 -0
- package/dist/render/frameReflections.js +48 -0
- package/dist/render/glCompressed.js +83 -0
- package/dist/render/instances.d.ts +26 -0
- package/dist/render/lightBudget.d.ts +10 -0
- package/dist/render/lightBudget.js +10 -0
- package/dist/render/lightmap.d.ts +1 -1
- package/dist/render/mesh.d.ts +5 -0
- package/dist/render/mesh.js +6 -0
- package/dist/render/pass.d.ts +49 -0
- package/dist/render/pointLightSelection.d.ts +4 -4
- package/dist/render/reflectionSurfaceTargets.d.ts +28 -0
- package/dist/render/reflectionSurfaceTargets.js +99 -0
- package/dist/render/renderQuality.d.ts +39 -8
- package/dist/render/renderQuality.js +4 -0
- package/dist/render/sceneTarget.d.ts +5 -0
- package/dist/render/sceneTarget.js +24 -1
- package/dist/render/screenSpaceReflection.d.ts +7 -1
- package/dist/render/screenSpaceReflection.js +5 -0
- package/dist/render/shaders/arcane.d.ts +1 -1
- package/dist/render/shaders/bolt.d.ts +1 -1
- package/dist/render/shaders/boneAnimation.d.ts +19 -0
- package/dist/render/shaders/boneAnimation.js +63 -0
- package/dist/render/shaders/caustics.d.ts +1 -1
- package/dist/render/shaders/depth.d.ts +7 -0
- package/dist/render/shaders/depth.js +35 -10
- package/dist/render/shaders/film.d.ts +1 -1
- package/dist/render/shaders/filmLook.js +2 -1
- package/dist/render/shaders/fire.d.ts +1 -1
- package/dist/render/shaders/flat/glassTint.d.ts +1 -1
- package/dist/render/shaders/flat/glassTint.js +2 -0
- package/dist/render/shaders/flat/index.d.ts +16 -0
- package/dist/render/shaders/flat/index.js +33 -5
- package/dist/render/shaders/flat/main.d.ts +1 -1
- package/dist/render/shaders/flat/main.js +43 -5
- package/dist/render/shaders/flat/models.js +1 -1
- package/dist/render/shaders/flat/overlay.d.ts +16 -0
- package/dist/render/shaders/flat/overlay.js +117 -0
- package/dist/render/shaders/flat/pointShadow.js +3 -3
- package/dist/render/shaders/flat/preamble.js +38 -24
- package/dist/render/shaders/flat/reflectionSurface.d.ts +21 -0
- package/dist/render/shaders/flat/reflectionSurface.js +61 -0
- package/dist/render/shaders/fog.d.ts +1 -1
- package/dist/render/shaders/fog.js +9 -2
- package/dist/render/shaders/fringe.d.ts +29 -0
- package/dist/render/shaders/fringe.js +55 -0
- package/dist/render/shaders/generated/arcane.wgsl.d.ts +1 -1
- package/dist/render/shaders/generated/arcane.wgsl.js +1 -1
- package/dist/render/shaders/generated/bolt.wgsl.d.ts +1 -1
- package/dist/render/shaders/generated/bolt.wgsl.js +1 -1
- package/dist/render/shaders/generated/caustics.wgsl.d.ts +1 -1
- package/dist/render/shaders/generated/caustics.wgsl.js +1 -1
- package/dist/render/shaders/generated/depth.wgsl.d.ts +93 -0
- package/dist/render/shaders/generated/depth.wgsl.js +93 -0
- package/dist/render/shaders/generated/film.wgsl.d.ts +1 -1
- package/dist/render/shaders/generated/film.wgsl.js +1 -1
- package/dist/render/shaders/generated/fire.wgsl.d.ts +1 -1
- package/dist/render/shaders/generated/fire.wgsl.js +1 -1
- package/dist/render/shaders/generated/flat.wgsl.d.ts +3254 -2920
- package/dist/render/shaders/generated/flat.wgsl.js +3292 -2957
- package/dist/render/shaders/generated/line.wgsl.d.ts +1 -1
- package/dist/render/shaders/generated/line.wgsl.js +1 -1
- package/dist/render/shaders/generated/particle.wgsl.d.ts +4 -4
- package/dist/render/shaders/generated/particle.wgsl.js +4 -4
- package/dist/render/shaders/generated/rush.wgsl.d.ts +56 -26
- package/dist/render/shaders/generated/rush.wgsl.js +56 -26
- package/dist/render/shaders/generated/scatter.wgsl.d.ts +1 -1
- package/dist/render/shaders/generated/scatter.wgsl.js +1 -1
- package/dist/render/shaders/generated/smoke.wgsl.d.ts +1 -1
- package/dist/render/shaders/generated/smoke.wgsl.js +1 -1
- package/dist/render/shaders/generated/ssrResolve.wgsl.d.ts +29 -0
- package/dist/render/shaders/generated/ssrResolve.wgsl.js +29 -0
- package/dist/render/shaders/generated/ssrTrace.wgsl.d.ts +22 -2
- package/dist/render/shaders/generated/ssrTrace.wgsl.js +22 -2
- package/dist/render/shaders/generated/water.wgsl.d.ts +1 -1
- package/dist/render/shaders/generated/water.wgsl.js +1 -1
- package/dist/render/shaders/gpudriven/fog.wgsl.d.ts +2 -2
- package/dist/render/shaders/gpudriven/fog.wgsl.js +11 -3
- package/dist/render/shaders/line.d.ts +1 -1
- package/dist/render/shaders/outputTransform.d.ts +7 -0
- package/dist/render/shaders/outputTransform.js +28 -14
- package/dist/render/shaders/particle.d.ts +3 -3
- package/dist/render/shaders/rush.js +54 -11
- package/dist/render/shaders/scatter.d.ts +1 -1
- package/dist/render/shaders/smoke.d.ts +1 -1
- package/dist/render/shaders/ssrResolve.d.ts +17 -0
- package/dist/render/shaders/ssrResolve.js +51 -0
- package/dist/render/shaders/ssrTrace.js +26 -0
- package/dist/render/shaders/vertexChannel.d.ts +7 -0
- package/dist/render/shaders/vertexChannel.js +26 -0
- package/dist/render/shaders/water.d.ts +1 -1
- package/dist/render/ssrPass.d.ts +16 -0
- package/dist/render/ssrPass.js +106 -1
- package/dist/render/staticDraws.d.ts +47 -0
- package/dist/render/staticDraws.js +43 -0
- package/dist/render/surfaceOverlay.d.ts +132 -0
- package/dist/render/surfaceOverlay.js +85 -0
- package/dist/render/surfaceTexture.d.ts +57 -7
- package/dist/render/surfaceTexture.js +125 -17
- package/dist/render/temporalAa.d.ts +14 -0
- package/dist/render/temporalAa.js +20 -0
- package/dist/render/vertexDefaults.d.ts +17 -0
- package/dist/render/vertexDefaults.js +24 -0
- package/package.json +6 -6
- package/src/index.ts +24 -2
- package/src/render/ambientHarmonics.ts +1 -1
- package/src/render/areaLights.ts +4 -4
- package/src/render/atmosphere.ts +22 -1
- package/src/render/backend/api.ts +22 -3
- package/src/render/backend/createRenderer.ts +18 -1
- package/src/render/backend/select.ts +10 -5
- package/src/render/backend/webgl2/boneAnimations.ts +105 -0
- package/src/render/backend/webgl2/instanced.ts +20 -1
- package/src/render/backend/webgl2/renderer.ts +672 -37
- package/src/render/backend/webgl2/skinPaletteTexture.ts +6 -4
- package/src/render/backend/webgpu/boneAnimations.ts +97 -0
- package/src/render/backend/webgpu/buffers.ts +42 -16
- package/src/render/backend/webgpu/compressedUpload.ts +59 -9
- package/src/render/backend/webgpu/depthPass.ts +51 -10
- package/src/render/backend/webgpu/device.ts +42 -3
- package/src/render/backend/webgpu/drawCommand.ts +22 -4
- package/src/render/backend/webgpu/flatPass.ts +250 -40
- package/src/render/backend/webgpu/instanced.ts +32 -1
- package/src/render/backend/webgpu/materialStore.ts +276 -0
- package/src/render/backend/webgpu/pipelineCache.ts +7 -0
- package/src/render/backend/webgpu/postPass.ts +18 -0
- package/src/render/backend/webgpu/reflectionSurfacePass.ts +114 -0
- package/src/render/backend/webgpu/renderer.ts +1655 -230
- package/src/render/backend/webgpu/skinPaletteRing.ts +13 -7
- package/src/render/backend/webgpu/skinPaletteTexture.ts +7 -1
- package/src/render/backend/webgpu/staticBundles.ts +363 -0
- package/src/render/backend/webgpu/surfaceTexturePass.ts +29 -3
- package/src/render/backend/webgpu/uniformRing.ts +10 -1
- package/src/render/bloomChain.ts +3 -3
- package/src/render/boneAnimation.ts +223 -0
- package/src/render/compressedSource.ts +121 -29
- package/src/render/displayRange.ts +61 -0
- package/src/render/filmicCurve.ts +229 -0
- package/src/render/fog.ts +19 -3
- package/src/render/frame/resources.ts +6 -0
- package/src/render/frameReflections.ts +72 -0
- package/src/render/glCompressed.ts +83 -0
- package/src/render/instances.ts +27 -0
- package/src/render/lightBudget.ts +11 -0
- package/src/render/lightmap.ts +1 -1
- package/src/render/mesh.ts +6 -0
- package/src/render/pass.ts +53 -1
- package/src/render/pointLightSelection.ts +4 -4
- package/src/render/reflectionSurfaceTargets.ts +105 -0
- package/src/render/renderQuality.ts +44 -8
- package/src/render/sceneTarget.ts +30 -2
- package/src/render/screenSpaceReflection.ts +7 -1
- package/src/render/shaders/boneAnimation.ts +63 -0
- package/src/render/shaders/depth.ts +45 -10
- package/src/render/shaders/filmLook.ts +2 -1
- package/src/render/shaders/flat/glassTint.ts +5 -1
- package/src/render/shaders/flat/index.ts +49 -5
- package/src/render/shaders/flat/main.ts +43 -5
- package/src/render/shaders/flat/models.ts +1 -1
- package/src/render/shaders/flat/overlay.ts +117 -0
- package/src/render/shaders/flat/pointShadow.ts +3 -3
- package/src/render/shaders/flat/preamble.ts +38 -24
- package/src/render/shaders/flat/reflectionSurface.ts +61 -0
- package/src/render/shaders/fog.ts +9 -2
- package/src/render/shaders/fringe.ts +59 -0
- package/src/render/shaders/generated/arcane.wgsl.ts +1 -1
- package/src/render/shaders/generated/bolt.wgsl.ts +1 -1
- package/src/render/shaders/generated/caustics.wgsl.ts +1 -1
- package/src/render/shaders/generated/depth.wgsl.ts +95 -0
- package/src/render/shaders/generated/film.wgsl.ts +1 -1
- package/src/render/shaders/generated/fire.wgsl.ts +1 -1
- package/src/render/shaders/generated/flat.wgsl.ts +3292 -2957
- package/src/render/shaders/generated/line.wgsl.ts +1 -1
- package/src/render/shaders/generated/particle.wgsl.ts +4 -4
- package/src/render/shaders/generated/rush.wgsl.ts +56 -26
- package/src/render/shaders/generated/scatter.wgsl.ts +1 -1
- package/src/render/shaders/generated/smoke.wgsl.ts +1 -1
- package/src/render/shaders/generated/ssrResolve.wgsl.ts +30 -0
- package/src/render/shaders/generated/ssrTrace.wgsl.ts +22 -2
- package/src/render/shaders/generated/water.wgsl.ts +1 -1
- package/src/render/shaders/gpudriven/fog.wgsl.ts +11 -3
- package/src/render/shaders/outputTransform.ts +30 -14
- package/src/render/shaders/rush.ts +54 -11
- package/src/render/shaders/ssrResolve.ts +52 -0
- package/src/render/shaders/ssrTrace.ts +26 -0
- package/src/render/shaders/vertexChannel.ts +27 -0
- package/src/render/ssrPass.ts +138 -1
- package/src/render/staticDraws.ts +95 -0
- package/src/render/surfaceOverlay.ts +195 -0
- package/src/render/surfaceTexture.ts +161 -27
- package/src/render/temporalAa.ts +20 -0
- package/src/render/vertexDefaults.ts +28 -0
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `filmic` output transform: a parametric film curve, its five numbers, and the eight
|
|
3
|
+
* constants the resolve reads, decided once here for both backends.
|
|
4
|
+
*
|
|
5
|
+
* **Why a second filmic curve beside `aces`.** `aces` is the reference RRT and ODT fit, which
|
|
6
|
+
* holds a mid grey of 0.18 at about 0.11 of display linear: graded for a dark cinema and kept dark.
|
|
7
|
+
* The curve here holds 0.18 at 0.18 by construction, and is shaped by five numbers a grading
|
|
8
|
+
* volume carries — a slope through mid grey, a toe and a shoulder, and how far black and white are
|
|
9
|
+
* clipped past the ends — so a look authored against such a curve is matched by passing its numbers
|
|
10
|
+
* rather than by baking the difference into a colour lookup table, which has the fewest steps
|
|
11
|
+
* exactly where two curves differ most: in the shadows.
|
|
12
|
+
*
|
|
13
|
+
* **What the curve is.** In the ACEScg working space, after the ACES reference's glow and red
|
|
14
|
+
* modifier and a 4% desaturation: a straight line of `slope` through mid grey in log10, joined to a
|
|
15
|
+
* logistic toe below `toeMatch` and a logistic shoulder above `shoulderMatch`, blended by a smooth
|
|
16
|
+
* step between the two, then desaturated by 7% and taken back to linear sRGB. The toe's position is
|
|
17
|
+
* solved so that 0.18 in is 0.18 out.
|
|
18
|
+
*
|
|
19
|
+
* **What it gives up.** It needs the composite to grade: `screenEffects` and `hdrScene`, since the
|
|
20
|
+
* forward passes that grade a frame without one carry two uniforms between them and not eight.
|
|
21
|
+
* Without them every pass grades with `aces` and the renderer says so once at construction.
|
|
22
|
+
* **What would make it wrong** is a profile wanting this curve without a scene target, which would
|
|
23
|
+
* then pay six floats in every forward program to have it.
|
|
24
|
+
*/
|
|
25
|
+
/** The defaults the curve ships with where a volume states nothing. */
|
|
26
|
+
export const DEFAULT_FILMIC_CURVE = {
|
|
27
|
+
slope: 0.88,
|
|
28
|
+
toe: 0.55,
|
|
29
|
+
shoulder: 0.26,
|
|
30
|
+
blackClip: 0,
|
|
31
|
+
whiteClip: 0.04,
|
|
32
|
+
};
|
|
33
|
+
/** How many floats `resolveFilmicCurve` fills: two vectors of the resolve's uniforms. */
|
|
34
|
+
export const FILMIC_CONSTANTS = 8;
|
|
35
|
+
/** Mid grey, which the curve takes to itself. */
|
|
36
|
+
const MID_GREY = 0.18;
|
|
37
|
+
/** The largest toe or shoulder kept: at 1 the toe's or the shoulder's scale is zero. */
|
|
38
|
+
const MOST = 0.999;
|
|
39
|
+
/** The shallowest slope kept, which is still a curve rather than a flat line. */
|
|
40
|
+
const LEAST_SLOPE = 0.01;
|
|
41
|
+
/**
|
|
42
|
+
* The eight constants the resolve reads, into `out`: `uFilmA` = (slope, black clip, white clip,
|
|
43
|
+
* toe scale) and `uFilmB` = (shoulder scale, toe match, straight match, shoulder match). Returns
|
|
44
|
+
* whether any of the five numbers had to be brought into range.
|
|
45
|
+
*
|
|
46
|
+
* Here rather than in the shader, because they are one solve a curve and would be one per pixel
|
|
47
|
+
* there. **Clamped rather than refused**, because a grading volume is set from inside a frame and
|
|
48
|
+
* the frame loop never throws: a slope below 0.01, a toe, shoulder or clip outside 0 to 1, and a
|
|
49
|
+
* toe or shoulder of exactly 1 — whose scale is then zero and divides the curve by it — are each
|
|
50
|
+
* a picture made of NaN otherwise. A number that is not finite takes the default's. The renderer
|
|
51
|
+
* says once when anything was clamped.
|
|
52
|
+
*/
|
|
53
|
+
export function resolveFilmicCurve(curve, out,
|
|
54
|
+
/**
|
|
55
|
+
* The display's peak over paper white (`displayHeadroom`), 1 for a standard range. Above 1 the
|
|
56
|
+
* white clip is raised by the difference, so the shoulder rolls off toward the display's peak
|
|
57
|
+
* rather than toward white, and the toe and mid grey stay exactly where they were.
|
|
58
|
+
*/
|
|
59
|
+
headroom = 1) {
|
|
60
|
+
let clamped = false;
|
|
61
|
+
const within = (value, low, high, fallback) => {
|
|
62
|
+
const finite = Number.isFinite(value) ? value : fallback;
|
|
63
|
+
const kept = Math.min(Math.max(finite, low), high);
|
|
64
|
+
if (kept !== value)
|
|
65
|
+
clamped = true;
|
|
66
|
+
return kept;
|
|
67
|
+
};
|
|
68
|
+
const slope = within(curve.slope, LEAST_SLOPE, Number.MAX_VALUE, DEFAULT_FILMIC_CURVE.slope);
|
|
69
|
+
const toe = within(curve.toe, 0, MOST, DEFAULT_FILMIC_CURVE.toe);
|
|
70
|
+
const shoulder = within(curve.shoulder, 0, MOST, DEFAULT_FILMIC_CURVE.shoulder);
|
|
71
|
+
const blackClip = within(curve.blackClip, 0, 1, DEFAULT_FILMIC_CURVE.blackClip);
|
|
72
|
+
const whiteClip = within(curve.whiteClip, 0, 1, DEFAULT_FILMIC_CURVE.whiteClip) + Math.max(headroom, 1) - 1;
|
|
73
|
+
const toeScale = 1 + blackClip - toe;
|
|
74
|
+
const shoulderScale = 1 + whiteClip - shoulder;
|
|
75
|
+
let toeMatch;
|
|
76
|
+
if (toe > 0.8) {
|
|
77
|
+
/* Mid grey falls on the straight segment. */
|
|
78
|
+
toeMatch = (1 - toe - MID_GREY) / slope + Math.log10(MID_GREY);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
/* Mid grey falls on the toe: solve the toe's logistic for 0.18 in, 0.18 out. */
|
|
82
|
+
const bt = (MID_GREY + blackClip) / toeScale - 1;
|
|
83
|
+
toeMatch = Math.log10(MID_GREY) - 0.5 * Math.log((1 + bt) / (1 - bt)) * (toeScale / slope);
|
|
84
|
+
}
|
|
85
|
+
const straightMatch = (1 - toe) / slope - toeMatch;
|
|
86
|
+
const shoulderMatch = shoulder / slope - straightMatch;
|
|
87
|
+
out[0] = slope;
|
|
88
|
+
out[1] = blackClip;
|
|
89
|
+
out[2] = whiteClip;
|
|
90
|
+
out[3] = toeScale;
|
|
91
|
+
out[4] = shoulderScale;
|
|
92
|
+
out[5] = toeMatch;
|
|
93
|
+
out[6] = straightMatch;
|
|
94
|
+
out[7] = shoulderMatch;
|
|
95
|
+
return clamped;
|
|
96
|
+
}
|
|
97
|
+
/** Said once a renderer, the first time `setFilmicCurve` was handed a number out of range. */
|
|
98
|
+
export const FILMIC_CLAMPED = '[driftengine] setFilmicCurve was handed a number outside its range — a slope under 0.01, a ' +
|
|
99
|
+
'toe, shoulder or clip outside 0 to 1, or one that is not a number — and drew with it clamped.';
|
|
100
|
+
/**
|
|
101
|
+
* Said once at construction where `filmic` was asked for and the frame has no composite that
|
|
102
|
+
* grades: the passes grade with `aces`, which is the nearest curve they carry.
|
|
103
|
+
*/
|
|
104
|
+
export const FILMIC_WITHOUT_COMPOSITE = "[driftengine] outputTransform 'filmic' is applied by the composite, which grades only with " +
|
|
105
|
+
"`screenEffects` and `hdrScene` both on: without them every pass grades itself, with 'aces'.";
|
|
106
|
+
/**
|
|
107
|
+
* `filmicCurve(c)`: linear sRGB in, display-linear sRGB out, clamped to 0 to 1 — or, on a high
|
|
108
|
+
* range display, to the shoulder's own asymptote. Reads `uFilmA`, `uFilmB` and `uDisplayHeadroom`,
|
|
109
|
+
* which the including stage declares. The ACES helpers are the reference's own:
|
|
110
|
+
* saturation, `yc`, the glow's sigmoid, and hue in degrees.
|
|
111
|
+
*/
|
|
112
|
+
export const FILMIC_GLSL = `
|
|
113
|
+
/* sRGB to ACEScg (through D60), ACEScg back, and ACEScg to and from ACES2065-1. Columns. */
|
|
114
|
+
const mat3 FILM_SRGB_TO_AP1 = mat3(
|
|
115
|
+
0.61319, 0.07021, 0.02062,
|
|
116
|
+
0.33951, 0.91634, 0.10957,
|
|
117
|
+
0.04737, 0.01345, 0.86961
|
|
118
|
+
);
|
|
119
|
+
/* The inverse of the one above, computed rather than copied, so a round trip is the identity. */
|
|
120
|
+
const mat3 FILM_AP1_TO_SRGB = mat3(
|
|
121
|
+
1.70480, -0.13027, -0.02401,
|
|
122
|
+
-0.62168, 1.14082, -0.12900,
|
|
123
|
+
-0.08325, -0.01055, 1.15324
|
|
124
|
+
);
|
|
125
|
+
const mat3 FILM_AP1_TO_AP0 = mat3(
|
|
126
|
+
0.6954522414, 0.0447945634, -0.0055258826,
|
|
127
|
+
0.1406786965, 0.8596711185, 0.0040252103,
|
|
128
|
+
0.1638690622, 0.0955343182, 1.0015006723
|
|
129
|
+
);
|
|
130
|
+
const mat3 FILM_AP0_TO_AP1 = mat3(
|
|
131
|
+
1.4514393161, -0.0765537734, 0.0083161484,
|
|
132
|
+
-0.2365107469, 1.1762296998, -0.0060324498,
|
|
133
|
+
-0.2149285693, -0.0996759264, 0.9977163014
|
|
134
|
+
);
|
|
135
|
+
const vec3 FILM_AP1_LUMA = vec3(0.2722287168, 0.6740817658, 0.0536895174);
|
|
136
|
+
|
|
137
|
+
float filmSaturation(vec3 c) {
|
|
138
|
+
float hi = max(c.r, max(c.g, c.b));
|
|
139
|
+
float lo = min(c.r, min(c.g, c.b));
|
|
140
|
+
return (max(hi, 1e-10) - max(lo, 1e-10)) / max(hi, 1e-2);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
float filmYc(vec3 c) {
|
|
144
|
+
float chroma = sqrt(max(c.b * (c.b - c.g) + c.g * (c.g - c.r) + c.r * (c.r - c.b), 0.0));
|
|
145
|
+
return (c.b + c.g + c.r + 1.75 * chroma) / 3.0;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
float filmSigmoid(float x) {
|
|
149
|
+
float t = max(1.0 - abs(x / 2.0), 0.0);
|
|
150
|
+
return (1.0 + sign(x) * (1.0 - t * t)) / 2.0;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
float filmGlow(float yc, float gain, float mid) {
|
|
154
|
+
if (yc <= 2.0 / 3.0 * mid) return gain;
|
|
155
|
+
if (yc >= 2.0 * mid) return 0.0;
|
|
156
|
+
return gain * (mid / yc - 0.5);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/* Hue in degrees, -180 to 180 about red; 0 for a grey, which then takes no red modifier. */
|
|
160
|
+
float filmCentredHue(vec3 c) {
|
|
161
|
+
float y = sqrt(3.0) * (c.g - c.b);
|
|
162
|
+
float x = 2.0 * c.r - c.g - c.b;
|
|
163
|
+
if (abs(x) < 1e-10 && abs(y) < 1e-10) return 0.0;
|
|
164
|
+
return degrees(atan(y, x));
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
vec3 filmicCurve(vec3 linear) {
|
|
168
|
+
vec3 ap0 = FILM_AP1_TO_AP0 * (FILM_SRGB_TO_AP1 * linear);
|
|
169
|
+
/* The reference's glow, lifting dark saturated colours a little. */
|
|
170
|
+
float saturation = filmSaturation(ap0);
|
|
171
|
+
ap0 *= 1.0 + filmGlow(filmYc(ap0), 0.05 * filmSigmoid((saturation - 0.4) / 0.2), 0.08);
|
|
172
|
+
/* And its red modifier, pulling saturated reds toward a pivot so they do not run to orange. */
|
|
173
|
+
float weight = smoothstep(0.0, 1.0, 1.0 - abs(2.0 * filmCentredHue(ap0) / 135.0));
|
|
174
|
+
ap0.r += weight * weight * saturation * (0.03 - ap0.r) * (1.0 - 0.82);
|
|
175
|
+
vec3 work = max(FILM_AP0_TO_AP1 * ap0, vec3(0.0));
|
|
176
|
+
work = mix(vec3(dot(work, FILM_AP1_LUMA)), work, 0.96);
|
|
177
|
+
|
|
178
|
+
float slope = uFilmA.x;
|
|
179
|
+
float black = uFilmA.y;
|
|
180
|
+
float white = uFilmA.z;
|
|
181
|
+
float toeScale = uFilmA.w;
|
|
182
|
+
float shoulderScale = uFilmB.x;
|
|
183
|
+
float toeMatch = uFilmB.y;
|
|
184
|
+
float straightMatch = uFilmB.z;
|
|
185
|
+
float shoulderMatch = uFilmB.w;
|
|
186
|
+
/* log10, through log2: GLSL ES has no log10. */
|
|
187
|
+
vec3 logc = log2(max(work, vec3(1e-10))) * 0.30102999566;
|
|
188
|
+
vec3 straight = slope * (logc + straightMatch);
|
|
189
|
+
vec3 toeC = -black + (2.0 * toeScale) / (1.0 + exp((-2.0 * slope / toeScale) * (logc - toeMatch)));
|
|
190
|
+
vec3 shoulderC =
|
|
191
|
+
(1.0 + white) - (2.0 * shoulderScale) / (1.0 + exp((2.0 * slope / shoulderScale) * (logc - shoulderMatch)));
|
|
192
|
+
toeC = mix(straight, toeC, vec3(lessThan(logc, vec3(toeMatch))));
|
|
193
|
+
shoulderC = mix(straight, shoulderC, vec3(greaterThan(logc, vec3(shoulderMatch))));
|
|
194
|
+
vec3 t = clamp((logc - toeMatch) / (shoulderMatch - toeMatch), 0.0, 1.0);
|
|
195
|
+
if (shoulderMatch < toeMatch) t = 1.0 - t;
|
|
196
|
+
t = (3.0 - 2.0 * t) * t * t;
|
|
197
|
+
vec3 tone = mix(toeC, shoulderC, t);
|
|
198
|
+
tone = mix(vec3(dot(tone, FILM_AP1_LUMA)), tone, 0.93);
|
|
199
|
+
/* White is the ceiling on a standard display; on a high range one the shoulder's asymptote is. */
|
|
200
|
+
float ceiling = uDisplayHeadroom > 1.0 ? 1.0 + white : 1.0;
|
|
201
|
+
return clamp(FILM_AP1_TO_SRGB * max(tone, vec3(0.0)), 0.0, ceiling);
|
|
202
|
+
}
|
|
203
|
+
`;
|
package/dist/render/fog.d.ts
CHANGED
|
@@ -36,7 +36,10 @@ export interface FogOptions {
|
|
|
36
36
|
readonly underwaterFactor: number;
|
|
37
37
|
/** `MEDIUM_FOG` integrates a medium; `LINEAR_FOG` ramps between near and far. */
|
|
38
38
|
readonly mode: number;
|
|
39
|
-
/**
|
|
39
|
+
/**
|
|
40
|
+
* Where haze begins: the ramp's start in linear mode, and in the medium the distance along the
|
|
41
|
+
* ray it is integrated from (`Atmosphere.fogStart`), 0 at the camera.
|
|
42
|
+
*/
|
|
40
43
|
readonly near: number;
|
|
41
44
|
readonly far: number;
|
|
42
45
|
}
|
package/dist/render/fog.js
CHANGED
|
@@ -62,13 +62,23 @@ export function mediumFog(fog, dist, pointY) {
|
|
|
62
62
|
const wetLinear = fog.underwaterDensity * dist;
|
|
63
63
|
return mix(ramp, 1 - Math.pow(2, -wetLinear * wetLinear * 1.442695), fog.underwaterFactor);
|
|
64
64
|
}
|
|
65
|
+
/*
|
|
66
|
+
* **Where the medium begins along the ray**, `near` — the linear mode's slot, which this mode
|
|
67
|
+
* never read before `Atmosphere.fogStart`. The ray is integrated from that point on: the density
|
|
68
|
+
* there, carried over what is left of the ray. At a start of 0 every term below is the one it
|
|
69
|
+
* always was, so a world that sets none draws the same bits.
|
|
70
|
+
*/
|
|
71
|
+
const start = Math.min(fog.near, dist);
|
|
72
|
+
const before = dist > 0 ? start / dist : 0;
|
|
65
73
|
const t = (pointY - fog.eyeY) * fog.heightFalloff;
|
|
74
|
+
const rest = t * (1 - before);
|
|
66
75
|
/*
|
|
67
76
|
* `(1 - e^-t)/t`, which tends to 1 as the ray levels out. **Guarded rather than branched**: at
|
|
68
77
|
* `t = 0` the quotient is 0/0, and 1e-4 of a scale height is 8 mm.
|
|
69
78
|
*/
|
|
70
|
-
const denom = Math.abs(
|
|
71
|
-
const air = 1 -
|
|
79
|
+
const denom = Math.abs(rest) < 1e-4 ? 1e-4 : rest;
|
|
80
|
+
const air = 1 -
|
|
81
|
+
Math.exp((-fog.density * Math.exp(-t * before) * (dist - start) * (1 - Math.exp(-denom))) / denom);
|
|
72
82
|
if (fog.underwaterFactor <= 0)
|
|
73
83
|
return air;
|
|
74
84
|
/* Water is its own medium and keeps its own curve, so crossing the surface changes nothing
|
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
* A mask is a `number` and not a bitset object. Thirty-one bits is more than the table needs,
|
|
10
10
|
* a number compares and combines in one instruction, and the scheduler does this per node.
|
|
11
11
|
*/
|
|
12
|
-
export declare const FRAME_RESOURCES: readonly ['sceneColor', 'sceneDepth', 'canvas', 'cascade0', 'cascade1', 'cascade2', 'pointShadows', 'probeCube', 'mirrorColor', 'mirrorDepth', 'bloomChain', 'aoTarget', 'depthSnapshot', 'inset'];
|
|
12
|
+
export declare const FRAME_RESOURCES: readonly ['sceneColor', 'sceneDepth', 'canvas', 'cascade0', 'cascade1', 'cascade2', 'pointShadows', 'probeCube', 'mirrorColor', 'mirrorDepth', 'bloomChain', 'aoTarget', 'depthSnapshot', 'inset', 'colorSnapshot'];
|
|
13
13
|
export type FrameResource = (typeof FRAME_RESOURCES)[number];
|
|
14
|
-
export declare const RESOURCE_COUNT:
|
|
14
|
+
export declare const RESOURCE_COUNT: 15;
|
|
15
15
|
/** The single bit that stands for one resource. */
|
|
16
16
|
export declare function resourceBit(name: FrameResource): number;
|
|
17
17
|
/** A mask of the named resources, for declaring what a node reads or writes. */
|
|
@@ -30,6 +30,12 @@ export const FRAME_RESOURCES = [
|
|
|
30
30
|
'aoTarget',
|
|
31
31
|
'depthSnapshot',
|
|
32
32
|
'inset',
|
|
33
|
+
/*
|
|
34
|
+
* The frame's colour as a registered pass reads it: a copy taken at that pass's draw, so reading
|
|
35
|
+
* it constrains no attachment's store, as `depthSnapshot` does not. Last, so no bit before it
|
|
36
|
+
* moved when it arrived.
|
|
37
|
+
*/
|
|
38
|
+
'colorSnapshot',
|
|
33
39
|
];
|
|
34
40
|
export const RESOURCE_COUNT = FRAME_RESOURCES.length;
|
|
35
41
|
const BITS = new Map(FRAME_RESOURCES.map((name, i) => [name, 1 << i]));
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reflections traced through the frame's own materials: `RenderQuality.screenSpaceReflections`.
|
|
3
|
+
*
|
|
4
|
+
* **Every opaque lit surface reflects the frame by its own material**, where `ReflectiveSurface`
|
|
5
|
+
* reflects it by a box's: the lit stage leaves, per pixel, how much of the environment it showed and
|
|
6
|
+
* at what roughness (`shaders/flat/reflectionSurface.ts`), and a ray marched against the frame's
|
|
7
|
+
* depth swaps that share for what it finds — so a glossy panel mirrors the figures on it and the
|
|
8
|
+
* matte panel beside it barely does, in one mesh with one material map. Past `maxRoughness` a
|
|
9
|
+
* surface keeps the probes' reflection alone, which is what a march cannot do better than: a rough
|
|
10
|
+
* lobe wants many rays, and one ray blurred is only a fair stand-in for a narrow one.
|
|
11
|
+
*
|
|
12
|
+
* **What a surface reflects is what the lit stage already reflected**: a metal by its metalness, a
|
|
13
|
+
* dielectric where `setSurfaceReflectivity` or its material asks for one. A surface that reflects
|
|
14
|
+
* no environment reflects no frame either, which is what keeps the two from disagreeing.
|
|
15
|
+
*/
|
|
16
|
+
/** How the frame's materials reflect it. Every field optional; see `DEFAULT_FRAME_REFLECTIONS`. */
|
|
17
|
+
export interface FrameReflections {
|
|
18
|
+
/** The roughness past which a surface reflects the probes alone, faded over the last quarter. */
|
|
19
|
+
readonly maxRoughness?: number;
|
|
20
|
+
/** How far a ray travels before it gives up, in metres. */
|
|
21
|
+
readonly reachM?: number;
|
|
22
|
+
/** How deep a depth sample is believed to be, in metres. See `ScreenSpaceMarch.thicknessM`. */
|
|
23
|
+
readonly thicknessM?: number;
|
|
24
|
+
/** Samples along a ray, at most 32. */
|
|
25
|
+
readonly steps?: number;
|
|
26
|
+
/** How far a fully rough reflection is smeared, as a share of the frame's height. */
|
|
27
|
+
readonly blur?: number;
|
|
28
|
+
}
|
|
29
|
+
export type ResolvedFrameReflections = Required<FrameReflections>;
|
|
30
|
+
/** The march `ReflectiveSurface` defaults to, a ceiling at satin, and a smear of 3% of the frame. */
|
|
31
|
+
export declare const DEFAULT_FRAME_REFLECTIONS: ResolvedFrameReflections;
|
|
32
|
+
/**
|
|
33
|
+
* The option as the renderers read it: null where it is off, and every number held where the
|
|
34
|
+
* shader can use it — a ceiling above zero, a reach and a thickness above zero, a whole number of
|
|
35
|
+
* steps from 1 to 32, and a blur from none to a fifth of the frame. Clamped rather than refused,
|
|
36
|
+
* since a quality option is read at construction and a renderer that threw there would draw nothing.
|
|
37
|
+
*/
|
|
38
|
+
export declare function resolveFrameReflections(asked: boolean | FrameReflections | undefined): ResolvedFrameReflections | null;
|
|
39
|
+
/** What a renderer says once where the frame cannot carry these reflections, and why. */
|
|
40
|
+
export declare function frameReflectionsRefused(reason: string): string;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reflections traced through the frame's own materials: `RenderQuality.screenSpaceReflections`.
|
|
3
|
+
*
|
|
4
|
+
* **Every opaque lit surface reflects the frame by its own material**, where `ReflectiveSurface`
|
|
5
|
+
* reflects it by a box's: the lit stage leaves, per pixel, how much of the environment it showed and
|
|
6
|
+
* at what roughness (`shaders/flat/reflectionSurface.ts`), and a ray marched against the frame's
|
|
7
|
+
* depth swaps that share for what it finds — so a glossy panel mirrors the figures on it and the
|
|
8
|
+
* matte panel beside it barely does, in one mesh with one material map. Past `maxRoughness` a
|
|
9
|
+
* surface keeps the probes' reflection alone, which is what a march cannot do better than: a rough
|
|
10
|
+
* lobe wants many rays, and one ray blurred is only a fair stand-in for a narrow one.
|
|
11
|
+
*
|
|
12
|
+
* **What a surface reflects is what the lit stage already reflected**: a metal by its metalness, a
|
|
13
|
+
* dielectric where `setSurfaceReflectivity` or its material asks for one. A surface that reflects
|
|
14
|
+
* no environment reflects no frame either, which is what keeps the two from disagreeing.
|
|
15
|
+
*/
|
|
16
|
+
/** The march `ReflectiveSurface` defaults to, a ceiling at satin, and a smear of 3% of the frame. */
|
|
17
|
+
export const DEFAULT_FRAME_REFLECTIONS = Object.freeze({
|
|
18
|
+
maxRoughness: 0.6,
|
|
19
|
+
reachM: 8,
|
|
20
|
+
thicknessM: 0.25,
|
|
21
|
+
steps: 24,
|
|
22
|
+
blur: 0.03,
|
|
23
|
+
});
|
|
24
|
+
const finite = (value, fallback) => value !== undefined && Number.isFinite(value) ? value : fallback;
|
|
25
|
+
/**
|
|
26
|
+
* The option as the renderers read it: null where it is off, and every number held where the
|
|
27
|
+
* shader can use it — a ceiling above zero, a reach and a thickness above zero, a whole number of
|
|
28
|
+
* steps from 1 to 32, and a blur from none to a fifth of the frame. Clamped rather than refused,
|
|
29
|
+
* since a quality option is read at construction and a renderer that threw there would draw nothing.
|
|
30
|
+
*/
|
|
31
|
+
export function resolveFrameReflections(asked) {
|
|
32
|
+
if (asked === undefined || asked === false)
|
|
33
|
+
return null;
|
|
34
|
+
const given = asked === true ? {} : asked;
|
|
35
|
+
const d = DEFAULT_FRAME_REFLECTIONS;
|
|
36
|
+
return {
|
|
37
|
+
maxRoughness: Math.min(Math.max(finite(given.maxRoughness, d.maxRoughness), 0.01), 1),
|
|
38
|
+
reachM: Math.max(finite(given.reachM, d.reachM), 0.01),
|
|
39
|
+
thicknessM: Math.max(finite(given.thicknessM, d.thicknessM), 0.001),
|
|
40
|
+
steps: Math.min(Math.max(Math.round(finite(given.steps, d.steps)), 1), 32),
|
|
41
|
+
blur: Math.min(Math.max(finite(given.blur, d.blur), 0), 0.2),
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/** What a renderer says once where the frame cannot carry these reflections, and why. */
|
|
45
|
+
export function frameReflectionsRefused(reason) {
|
|
46
|
+
return (`screenSpaceReflections is not drawn: ${reason}. Surfaces keep the probes' reflection; ` +
|
|
47
|
+
'the trace needs `screenEffects` and `hdrScene`, and a frame of one sample.');
|
|
48
|
+
}
|
|
@@ -10,12 +10,95 @@ const INTERNAL = {
|
|
|
10
10
|
bc5: 0x8dbd, // COMPRESSED_RED_GREEN_RGTC2_EXT
|
|
11
11
|
bc7: 0x8e8c, // COMPRESSED_RGBA_BPTC_UNORM_EXT
|
|
12
12
|
'bc7-srgb': 0x8e8d, // COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT
|
|
13
|
+
'eac-r11': 0x9270, // COMPRESSED_R11_EAC
|
|
14
|
+
'eac-rg11': 0x9272, // COMPRESSED_RG11_EAC
|
|
15
|
+
'etc2-rgb8': 0x9274, // COMPRESSED_RGB8_ETC2
|
|
16
|
+
'etc2-rgb8-srgb': 0x9275, // COMPRESSED_SRGB8_ETC2
|
|
17
|
+
'etc2-rgb8a1': 0x9276, // COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
|
|
18
|
+
'etc2-rgb8a1-srgb': 0x9277, // COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
|
|
19
|
+
'etc2-rgba8': 0x9278, // COMPRESSED_RGBA8_ETC2_EAC
|
|
20
|
+
'etc2-rgba8-srgb': 0x9279, // COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
|
|
21
|
+
'astc-4x4': 0x93b0, // COMPRESSED_RGBA_ASTC_4x4_KHR
|
|
22
|
+
'astc-4x4-srgb': 0x93d0, // COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR
|
|
23
|
+
'astc-5x4': 0x93b1, // COMPRESSED_RGBA_ASTC_5x4_KHR
|
|
24
|
+
'astc-5x4-srgb': 0x93d1, // COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR
|
|
25
|
+
'astc-5x5': 0x93b2, // COMPRESSED_RGBA_ASTC_5x5_KHR
|
|
26
|
+
'astc-5x5-srgb': 0x93d2, // COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR
|
|
27
|
+
'astc-6x5': 0x93b3, // COMPRESSED_RGBA_ASTC_6x5_KHR
|
|
28
|
+
'astc-6x5-srgb': 0x93d3, // COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR
|
|
29
|
+
'astc-6x6': 0x93b4, // COMPRESSED_RGBA_ASTC_6x6_KHR
|
|
30
|
+
'astc-6x6-srgb': 0x93d4, // COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR
|
|
31
|
+
'astc-8x5': 0x93b5, // COMPRESSED_RGBA_ASTC_8x5_KHR
|
|
32
|
+
'astc-8x5-srgb': 0x93d5, // COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR
|
|
33
|
+
'astc-8x6': 0x93b6, // COMPRESSED_RGBA_ASTC_8x6_KHR
|
|
34
|
+
'astc-8x6-srgb': 0x93d6, // COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR
|
|
35
|
+
'astc-8x8': 0x93b7, // COMPRESSED_RGBA_ASTC_8x8_KHR
|
|
36
|
+
'astc-8x8-srgb': 0x93d7, // COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR
|
|
37
|
+
'astc-10x5': 0x93b8, // COMPRESSED_RGBA_ASTC_10x5_KHR
|
|
38
|
+
'astc-10x5-srgb': 0x93d8, // COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR
|
|
39
|
+
'astc-10x6': 0x93b9, // COMPRESSED_RGBA_ASTC_10x6_KHR
|
|
40
|
+
'astc-10x6-srgb': 0x93d9, // COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR
|
|
41
|
+
'astc-10x8': 0x93ba, // COMPRESSED_RGBA_ASTC_10x8_KHR
|
|
42
|
+
'astc-10x8-srgb': 0x93da, // COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR
|
|
43
|
+
'astc-10x10': 0x93bb, // COMPRESSED_RGBA_ASTC_10x10_KHR
|
|
44
|
+
'astc-10x10-srgb': 0x93db, // COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR
|
|
45
|
+
'astc-12x10': 0x93bc, // COMPRESSED_RGBA_ASTC_12x10_KHR
|
|
46
|
+
'astc-12x10-srgb': 0x93dc, // COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR
|
|
47
|
+
'astc-12x12': 0x93bd, // COMPRESSED_RGBA_ASTC_12x12_KHR
|
|
48
|
+
'astc-12x12-srgb': 0x93dd, // COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR
|
|
13
49
|
};
|
|
14
50
|
const BY_EXTENSION = [
|
|
15
51
|
['WEBGL_compressed_texture_s3tc', ['bc1', 'bc2', 'bc3']],
|
|
16
52
|
['WEBGL_compressed_texture_s3tc_srgb', ['bc1-srgb', 'bc2-srgb', 'bc3-srgb']],
|
|
17
53
|
['EXT_texture_compression_rgtc', ['bc4', 'bc5']],
|
|
18
54
|
['EXT_texture_compression_bptc', ['bc7', 'bc7-srgb']],
|
|
55
|
+
/* The two families a phone has: every GLES 3 device takes ETC2, and most take ASTC beside it. */
|
|
56
|
+
[
|
|
57
|
+
'WEBGL_compressed_texture_etc',
|
|
58
|
+
[
|
|
59
|
+
'etc2-rgb8',
|
|
60
|
+
'etc2-rgb8-srgb',
|
|
61
|
+
'etc2-rgb8a1',
|
|
62
|
+
'etc2-rgb8a1-srgb',
|
|
63
|
+
'etc2-rgba8',
|
|
64
|
+
'etc2-rgba8-srgb',
|
|
65
|
+
'eac-r11',
|
|
66
|
+
'eac-rg11',
|
|
67
|
+
],
|
|
68
|
+
],
|
|
69
|
+
[
|
|
70
|
+
'WEBGL_compressed_texture_astc',
|
|
71
|
+
[
|
|
72
|
+
'astc-4x4',
|
|
73
|
+
'astc-4x4-srgb',
|
|
74
|
+
'astc-5x4',
|
|
75
|
+
'astc-5x4-srgb',
|
|
76
|
+
'astc-5x5',
|
|
77
|
+
'astc-5x5-srgb',
|
|
78
|
+
'astc-6x5',
|
|
79
|
+
'astc-6x5-srgb',
|
|
80
|
+
'astc-6x6',
|
|
81
|
+
'astc-6x6-srgb',
|
|
82
|
+
'astc-8x5',
|
|
83
|
+
'astc-8x5-srgb',
|
|
84
|
+
'astc-8x6',
|
|
85
|
+
'astc-8x6-srgb',
|
|
86
|
+
'astc-8x8',
|
|
87
|
+
'astc-8x8-srgb',
|
|
88
|
+
'astc-10x5',
|
|
89
|
+
'astc-10x5-srgb',
|
|
90
|
+
'astc-10x6',
|
|
91
|
+
'astc-10x6-srgb',
|
|
92
|
+
'astc-10x8',
|
|
93
|
+
'astc-10x8-srgb',
|
|
94
|
+
'astc-10x10',
|
|
95
|
+
'astc-10x10-srgb',
|
|
96
|
+
'astc-12x10',
|
|
97
|
+
'astc-12x10-srgb',
|
|
98
|
+
'astc-12x12',
|
|
99
|
+
'astc-12x12-srgb',
|
|
100
|
+
],
|
|
101
|
+
],
|
|
19
102
|
];
|
|
20
103
|
/**
|
|
21
104
|
* The BC formats this context samples, enabling each extension that offers some. Enabling is what
|
|
@@ -66,6 +66,14 @@ export interface MeshInstances {
|
|
|
66
66
|
*/
|
|
67
67
|
readonly uvRegions?: Float32Array;
|
|
68
68
|
/** How many instances the arrays hold. Fixed at creation; the buffers are sized from it. */
|
|
69
|
+
/**
|
|
70
|
+
* Two floats each, the instance's clock for a batch that plays a bone animation
|
|
71
|
+
* (`InstancedOptions.animation`): its phase in seconds, added to the scene's time once the rate has
|
|
72
|
+
* scaled it, and its rate, 1 for the clip's own speed. **Absent, or an instance past its end, is
|
|
73
|
+
* `(0, 1)`** — every instance at the clip's speed and in step. Read by `uploadInstanced`, as the
|
|
74
|
+
* matrices are; a batch with no animation ignores it.
|
|
75
|
+
*/
|
|
76
|
+
readonly clocks?: Float32Array;
|
|
69
77
|
readonly capacity: number;
|
|
70
78
|
/** How many are live. The rest of the buffer is neither uploaded nor drawn. */
|
|
71
79
|
count: number;
|
|
@@ -103,6 +111,7 @@ export declare const INSTANCE_STRIDE: number;
|
|
|
103
111
|
* Writes nothing beyond `count`, and allocates nothing: `out` is the caller's staging array.
|
|
104
112
|
*/
|
|
105
113
|
export declare function packInstances(instances: MeshInstances, out: Float32Array): void;
|
|
114
|
+
import type { BoneAnimationHandle } from './boneAnimation.ts';
|
|
106
115
|
/** How a batch made by `createInstanced` behaves. */
|
|
107
116
|
export interface InstancedOptions {
|
|
108
117
|
/**
|
|
@@ -117,4 +126,21 @@ export interface InstancedOptions {
|
|
|
117
126
|
* place gains only the whole-batch test, which it could as well do itself.
|
|
118
127
|
*/
|
|
119
128
|
readonly cull?: boolean;
|
|
129
|
+
/**
|
|
130
|
+
* A bone animation every instance plays (`createBoneAnimation`): each vertex follows the bone its
|
|
131
|
+
* mesh's second coordinates name, at the instance's own moment of the clip (`MeshInstances.clocks`
|
|
132
|
+
* and the clock `setAnimationTime` sets), in the colour pass and in every shadow. The mesh must
|
|
133
|
+
* carry second coordinates. See `boneAnimation.ts`.
|
|
134
|
+
*
|
|
135
|
+
* **An animated batch is culled whole, never instance by instance**: its instances read their
|
|
136
|
+
* clocks by index, which a cull that compacts the survivors would reorder. And its bounds are the
|
|
137
|
+
* rest pose's, so a clip that carries vertices far from it wants a mesh whose bounds hold them.
|
|
138
|
+
*
|
|
139
|
+
* **What it gives up**: under reconstruction or the temporal resolve, a crowd's own movement is not
|
|
140
|
+
* in the frame's motion — the motion pass places a batch by its matrices, not by its clip — so its
|
|
141
|
+
* moving parts are reprojected as though still, which softens a fast clip a little; and a glass
|
|
142
|
+
* batch's coloured shadow is cast from rest. What would make the first wrong is a clip fast enough
|
|
143
|
+
* at the size it is seen to smear, which is then the motion pass's to learn.
|
|
144
|
+
*/
|
|
145
|
+
readonly animation?: BoneAnimationHandle;
|
|
120
146
|
}
|
|
@@ -243,6 +243,16 @@ export declare const SKIN_BLUR_ALBEDO_UNIT: number;
|
|
|
243
243
|
*/
|
|
244
244
|
export declare const PARTICLE_SPRITE_UNIT: number;
|
|
245
245
|
export declare const PARTICLE_DEPTH_UNIT: number;
|
|
246
|
+
/**
|
|
247
|
+
* A bone animation's places and turns and its batch's clocks (`shaders/boneAnimation.ts`): vertex
|
|
248
|
+
* samplers of the animated instanced program, so they count against the vertex stage's sixteen, not
|
|
249
|
+
* the lit stage's. Numbered past every unit before them rather than sharing the cloth's, which no
|
|
250
|
+
* animated program declares: a unit two programs both write is a binding one draw can leave for the
|
|
251
|
+
* other to read. Twenty-six to twenty-eight, inside the combined pool of thirty-two.
|
|
252
|
+
*/
|
|
253
|
+
export declare const BONE_PLACES_TEXTURE_UNIT: number;
|
|
254
|
+
export declare const BONE_TURNS_TEXTURE_UNIT: number;
|
|
255
|
+
export declare const INSTANCE_CLOCKS_TEXTURE_UNIT: number;
|
|
246
256
|
/**
|
|
247
257
|
* A cookie's tile, in texels a side.
|
|
248
258
|
*
|
|
@@ -244,6 +244,16 @@ export const SKIN_BLUR_ALBEDO_UNIT = SKIN_BLUR_DEPTH_UNIT + 1;
|
|
|
244
244
|
*/
|
|
245
245
|
export const PARTICLE_SPRITE_UNIT = SKIN_BLUR_ALBEDO_UNIT + 1;
|
|
246
246
|
export const PARTICLE_DEPTH_UNIT = PARTICLE_SPRITE_UNIT + 1;
|
|
247
|
+
/**
|
|
248
|
+
* A bone animation's places and turns and its batch's clocks (`shaders/boneAnimation.ts`): vertex
|
|
249
|
+
* samplers of the animated instanced program, so they count against the vertex stage's sixteen, not
|
|
250
|
+
* the lit stage's. Numbered past every unit before them rather than sharing the cloth's, which no
|
|
251
|
+
* animated program declares: a unit two programs both write is a binding one draw can leave for the
|
|
252
|
+
* other to read. Twenty-six to twenty-eight, inside the combined pool of thirty-two.
|
|
253
|
+
*/
|
|
254
|
+
export const BONE_PLACES_TEXTURE_UNIT = PARTICLE_DEPTH_UNIT + 1;
|
|
255
|
+
export const BONE_TURNS_TEXTURE_UNIT = BONE_PLACES_TEXTURE_UNIT + 1;
|
|
256
|
+
export const INSTANCE_CLOCKS_TEXTURE_UNIT = BONE_TURNS_TEXTURE_UNIT + 1;
|
|
247
257
|
/**
|
|
248
258
|
* A cookie's tile, in texels a side.
|
|
249
259
|
*
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* light = irradiance(uv) * max(0, dot(d.xyz, n) + d.w)
|
|
16
16
|
* diffuse += albedo * (1 - metal) * light
|
|
17
17
|
*
|
|
18
|
-
*
|
|
18
|
+
* A directional lightmap read, once its own vectors have decoded the
|
|
19
19
|
* page — the first-order spherical harmonic its direction carries, in this engine's axes. **Added
|
|
20
20
|
* to what the dynamic lights give**, and to the ambient: a consumer whose bake already holds the
|
|
21
21
|
* sky's light zeroes the ambient for those draws itself, with `setAmbientSH` and nine zeros.
|
package/dist/render/mesh.d.ts
CHANGED
|
@@ -63,6 +63,11 @@ export declare class Mesh {
|
|
|
63
63
|
readonly isSkinnedEight: boolean;
|
|
64
64
|
/** Whether it has texture coordinates, without which a material's maps read one texel. */
|
|
65
65
|
readonly hasUvs: boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Whether it carries a grain lane, which is where second coordinates ride (`lightmap.ts`): what
|
|
68
|
+
* a bone animation reads each vertex's bone from.
|
|
69
|
+
*/
|
|
70
|
+
readonly hasGrain: boolean;
|
|
66
71
|
/** How many vertices it has, which a cloth binding is checked against. */
|
|
67
72
|
readonly vertexCount: number;
|
|
68
73
|
/**
|
package/dist/render/mesh.js
CHANGED
|
@@ -136,6 +136,11 @@ export class Mesh {
|
|
|
136
136
|
isSkinnedEight;
|
|
137
137
|
/** Whether it has texture coordinates, without which a material's maps read one texel. */
|
|
138
138
|
hasUvs;
|
|
139
|
+
/**
|
|
140
|
+
* Whether it carries a grain lane, which is where second coordinates ride (`lightmap.ts`): what
|
|
141
|
+
* a bone animation reads each vertex's bone from.
|
|
142
|
+
*/
|
|
143
|
+
hasGrain;
|
|
139
144
|
/** How many vertices it has, which a cloth binding is checked against. */
|
|
140
145
|
vertexCount;
|
|
141
146
|
/**
|
|
@@ -304,6 +309,7 @@ export class Mesh {
|
|
|
304
309
|
else {
|
|
305
310
|
this.attachAttribute(gl, ATTR_TANGENT, data.tangents, 4);
|
|
306
311
|
}
|
|
312
|
+
this.hasGrain = data.grain !== undefined;
|
|
307
313
|
if (data.grain === undefined) {
|
|
308
314
|
gl.disableVertexAttribArray(ATTR_GRAIN);
|
|
309
315
|
this.constants.push({ location: ATTR_GRAIN, value: ABSENT_ATTRIBUTE['grain'] });
|
package/dist/render/pass.d.ts
CHANGED
|
@@ -117,6 +117,19 @@ export type PassContext = {
|
|
|
117
117
|
} & ({
|
|
118
118
|
readonly backend: 'webgl2';
|
|
119
119
|
readonly gl: WebGL2RenderingContext;
|
|
120
|
+
/**
|
|
121
|
+
* The frame's colour with everything drawn before this pass, for a pass declaring
|
|
122
|
+
* `reads: ['colorSnapshot']`, and null for one that does not or where the frame keeps no
|
|
123
|
+
* scene target (`screenEffects` off). A copy, never the attachment being drawn into, which
|
|
124
|
+
* WebGL2 cannot sample; taken afresh at each such pass's draw. WebGPU hands the same copy
|
|
125
|
+
* over in `PrepareContext.sceneColor`, where a bind group has to be built before the pass.
|
|
126
|
+
*/
|
|
127
|
+
readonly sceneColor: WebGLTexture | null;
|
|
128
|
+
/**
|
|
129
|
+
* The frame's depth as it stands, for a pass declaring `reads: ['depthSnapshot']`: a copy, at
|
|
130
|
+
* the buffer's own values and reversed as it is (1 near, 0 far). Null as `sceneColor` is.
|
|
131
|
+
*/
|
|
132
|
+
readonly sceneDepth: WebGLTexture | null;
|
|
120
133
|
} | {
|
|
121
134
|
readonly backend: 'webgpu';
|
|
122
135
|
readonly pass: GPURenderPassEncoder;
|
|
@@ -213,6 +226,42 @@ export type PrepareContext = {
|
|
|
213
226
|
* should not apply it either; the renderer's own verbs do not jitter a mirror.
|
|
214
227
|
*/
|
|
215
228
|
readonly jitter: Float32Array;
|
|
229
|
+
/**
|
|
230
|
+
* The frame's single-sample copy of its depth, or null where the frame keeps none (no
|
|
231
|
+
* composite: `screenEffects` off).
|
|
232
|
+
*
|
|
233
|
+
* One `r32float` texel a pixel holding the depth buffer's own value, reversed as the
|
|
234
|
+
* buffer is (`REVERSED_DEPTH`: 1 at the near plane, 0 at the far one). Unfilterable, so a
|
|
235
|
+
* pass binds it as `'unfilterable-float'` and reads it with a non-filtering sampler or
|
|
236
|
+
* `textureLoad`.
|
|
237
|
+
*
|
|
238
|
+
* **Handed over here, filled at the draw.** The view is the one this frame's copy will be
|
|
239
|
+
* written into, so a pass builds its bind groups with it before the frame's pass opens; the
|
|
240
|
+
* copy itself is taken when a pass that declares `reads: ['depthSnapshot']` is drawn, with
|
|
241
|
+
* everything drawn before it, which is what the soft edge of a translucent particle
|
|
242
|
+
* needs. A pass that does not declare that read finds whatever the frame last wrote there.
|
|
243
|
+
*/
|
|
244
|
+
readonly sceneDepth: GPUTextureView | null;
|
|
245
|
+
/**
|
|
246
|
+
* The frame's colour, for a pass that declares `reads: ['colorSnapshot']`, or null where no
|
|
247
|
+
* registered pass does or the frame keeps no composite (`screenEffects` off).
|
|
248
|
+
*
|
|
249
|
+
* At the scene's own size and format — under a reconstruction, the render's rather than the
|
|
250
|
+
* output's, since that is the picture a registered pass draws into — and filterable.
|
|
251
|
+
* **Handed over here, refilled at the draw**: the view is the texture each reading pass's
|
|
252
|
+
* draw copies the frame into, with everything drawn before it, so a distortion samples the
|
|
253
|
+
* scene behind it and a full-screen effect drawn last reads the whole frame and writes over
|
|
254
|
+
* it, in scene light, before the tone curve. A copy a reading pass, where `sceneDepth` is one
|
|
255
|
+
* a frame.
|
|
256
|
+
*
|
|
257
|
+
* **Under a reconstruction a pass that reads it is drawn after the upscale**, over the
|
|
258
|
+
* reconstructed picture and after every blended draw, whatever order it was asked in — at the
|
|
259
|
+
* output's size and the reconstruction's format, which `PassContext.format` names at that
|
|
260
|
+
* draw, so a pass drawn there keeps a pipeline for it. The view is then the output-size copy.
|
|
261
|
+
* `sceneDepth` stays the render's opaque depth: at a ratio above 1 its texels are coarser by
|
|
262
|
+
* the ratio, and a blended draw is in neither depth, as it never is.
|
|
263
|
+
*/
|
|
264
|
+
readonly sceneColor: GPUTextureView | null;
|
|
216
265
|
};
|
|
217
266
|
/**
|
|
218
267
|
* The world's distance field on the device, as the two buffers and four numbers that address it.
|