@driftengine/core 4.4.1 → 4.5.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 +72 -0
- package/README.md +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +7 -0
- package/dist/render/backend/api.d.ts +17 -11
- package/dist/render/backend/webgl2/glassTintPrograms.d.ts +13 -0
- package/dist/render/backend/webgl2/glassTintPrograms.js +38 -0
- package/dist/render/backend/webgl2/renderer.d.ts +82 -8
- package/dist/render/backend/webgl2/renderer.js +373 -105
- package/dist/render/backend/webgpu/buffers.d.ts +19 -1
- package/dist/render/backend/webgpu/buffers.js +27 -1
- package/dist/render/backend/webgpu/depthPass.d.ts +1 -1
- package/dist/render/backend/webgpu/depthPass.js +2 -1
- package/dist/render/backend/webgpu/flatPass.d.ts +2 -0
- package/dist/render/backend/webgpu/flatPass.js +20 -1
- package/dist/render/backend/webgpu/glassTintPass.d.ts +28 -0
- package/dist/render/backend/webgpu/glassTintPass.js +205 -0
- package/dist/render/backend/webgpu/gpuDrivenPass.d.ts +60 -1
- package/dist/render/backend/webgpu/gpuDrivenPass.js +305 -5
- package/dist/render/backend/webgpu/instanced.d.ts +12 -1
- package/dist/render/backend/webgpu/instanced.js +20 -1
- package/dist/render/backend/webgpu/latePass.d.ts +26 -0
- package/dist/render/backend/webgpu/latePass.js +133 -0
- package/dist/render/backend/webgpu/lightVolumePass.js +5 -1
- package/dist/render/backend/webgpu/motionPass.d.ts +95 -0
- package/dist/render/backend/webgpu/motionPass.js +491 -0
- package/dist/render/backend/webgpu/pipelineCache.d.ts +10 -1
- package/dist/render/backend/webgpu/pipelineCache.js +11 -1
- package/dist/render/backend/webgpu/pointGlassTintPass.d.ts +32 -0
- package/dist/render/backend/webgpu/pointGlassTintPass.js +193 -0
- package/dist/render/backend/webgpu/pointShadowPass.d.ts +35 -6
- package/dist/render/backend/webgpu/pointShadowPass.js +105 -20
- package/dist/render/backend/webgpu/postPass.d.ts +21 -15
- package/dist/render/backend/webgpu/postPass.js +17 -4
- package/dist/render/backend/webgpu/renderer.d.ts +181 -54
- package/dist/render/backend/webgpu/renderer.js +1011 -394
- package/dist/render/backend/webgpu/scatterPass.js +2 -1
- package/dist/render/backend/webgpu/skinPaletteRing.d.ts +4 -0
- package/dist/render/backend/webgpu/skinPaletteRing.js +4 -0
- package/dist/render/backend/webgpu/snapshotMips.d.ts +29 -0
- package/dist/render/backend/webgpu/snapshotMips.js +52 -0
- package/dist/render/backend/webgpu/surfaceTexturePass.d.ts +5 -0
- package/dist/render/backend/webgpu/surfaceTexturePass.js +1 -1
- package/dist/render/flameLight.js +15 -2
- package/dist/render/glass.d.ts +45 -0
- package/dist/render/glass.js +39 -0
- package/dist/render/glassCasters.d.ts +40 -0
- package/dist/render/glassCasters.js +84 -0
- package/dist/render/glassShadow.d.ts +78 -0
- package/dist/render/glassShadow.js +125 -0
- package/dist/render/globalMediumPass.d.ts +2 -3
- package/dist/render/globalMediumPass.js +2 -8
- package/dist/render/gpudriven/lit.d.ts +12 -0
- package/dist/render/gpudriven/lit.js +23 -0
- package/dist/render/gpudriven/materialTable.d.ts +15 -5
- package/dist/render/gpudriven/materialTable.js +26 -6
- package/dist/render/gpudriven/pipeline.d.ts +1 -1
- package/dist/render/gpudriven/pipeline.js +4 -3
- package/dist/render/gpudriven/sunGlass.d.ts +35 -0
- package/dist/render/gpudriven/sunGlass.js +89 -0
- package/dist/render/lightBudget.d.ts +17 -5
- package/dist/render/lightBudget.js +17 -5
- package/dist/render/pointGlassTint.d.ts +59 -0
- package/dist/render/pointGlassTint.js +198 -0
- package/dist/render/pointShadowArray.d.ts +56 -3
- package/dist/render/pointShadowArray.js +127 -16
- package/dist/render/pointShadowBudget.js +51 -41
- package/dist/render/pointShadowMap.d.ts +23 -1
- package/dist/render/pointShadowMap.js +27 -1
- package/dist/render/recon/changeFrames.d.ts +15 -0
- package/dist/render/recon/changeFrames.js +21 -0
- package/dist/render/recon/disocclusion.d.ts +36 -3
- package/dist/render/recon/disocclusion.js +56 -4
- package/dist/render/recon/lateRouting.d.ts +14 -0
- package/dist/render/recon/lateRouting.js +18 -0
- package/dist/render/recon/mover.d.ts +57 -0
- package/dist/render/recon/mover.js +86 -0
- package/dist/render/recon/resolve.js +95 -12
- package/dist/render/renderQuality.d.ts +35 -0
- package/dist/render/renderQuality.js +7 -0
- package/dist/render/rendererHarness.js +12 -0
- package/dist/render/sceneTarget.d.ts +9 -1
- package/dist/render/sceneTarget.js +59 -13
- package/dist/render/shaders/depth.d.ts +16 -1
- package/dist/render/shaders/depth.js +85 -9
- package/dist/render/shaders/flat/directionalShadow.js +91 -6
- package/dist/render/shaders/flat/glassTint.d.ts +6 -0
- package/dist/render/shaders/flat/glassTint.js +25 -0
- package/dist/render/shaders/flat/index.d.ts +13 -0
- package/dist/render/shaders/flat/index.js +4 -0
- package/dist/render/shaders/flat/lampGlass.d.ts +1 -0
- package/dist/render/shaders/flat/lampGlass.js +183 -0
- package/dist/render/shaders/flat/main.d.ts +1 -1
- package/dist/render/shaders/flat/main.js +115 -15
- package/dist/render/shaders/flat/pointShadow.d.ts +1 -1
- package/dist/render/shaders/flat/pointShadow.js +2 -0
- package/dist/render/shaders/flat/preamble.js +21 -6
- package/dist/render/shaders/generated/depth.wgsl.d.ts +227 -4
- package/dist/render/shaders/generated/depth.wgsl.js +227 -4
- package/dist/render/shaders/generated/flat.wgsl.d.ts +360 -312
- package/dist/render/shaders/generated/flat.wgsl.js +376 -328
- package/dist/render/shaders/generated/globalMedium.wgsl.d.ts +3 -13
- package/dist/render/shaders/generated/globalMedium.wgsl.js +3 -13
- package/dist/render/shaders/generated/lightVolume.wgsl.d.ts +3 -13
- package/dist/render/shaders/generated/lightVolume.wgsl.js +4 -14
- package/dist/render/shaders/generated/octahedralResolve.wgsl.d.ts +29 -0
- package/dist/render/shaders/generated/octahedralResolve.wgsl.js +29 -0
- package/dist/render/shaders/generated/temporalResolve.wgsl.d.ts +31 -6
- package/dist/render/shaders/generated/temporalResolve.wgsl.js +31 -6
- package/dist/render/shaders/globalMedium.js +6 -6
- package/dist/render/shaders/gpudriven/blendRaster.wgsl.d.ts +7 -0
- package/dist/render/shaders/gpudriven/blendRaster.wgsl.js +86 -1
- package/dist/render/shaders/gpudriven/cull.wgsl.d.ts +1 -1
- package/dist/render/shaders/gpudriven/cull.wgsl.js +11 -2
- package/dist/render/shaders/gpudriven/materialTable.wgsl.d.ts +1 -1
- package/dist/render/shaders/gpudriven/materialTable.wgsl.js +3 -1
- package/dist/render/shaders/gpudriven/shade.wgsl.js +50 -1
- package/dist/render/shaders/gpudriven/sunGlass.wgsl.d.ts +9 -0
- package/dist/render/shaders/gpudriven/sunGlass.wgsl.js +133 -0
- package/dist/render/shaders/lightVolume.js +6 -6
- package/dist/render/shaders/octahedralResolve.d.ts +8 -0
- package/dist/render/shaders/octahedralResolve.js +48 -17
- package/dist/render/shaders/recon/lateDepth.wgsl.d.ts +1 -0
- package/dist/render/shaders/recon/lateDepth.wgsl.js +44 -0
- package/dist/render/shaders/recon/motion.wgsl.d.ts +1 -1
- package/dist/render/shaders/recon/motion.wgsl.js +84 -0
- package/dist/render/shaders/recon/resolve.wgsl.d.ts +1 -1
- package/dist/render/shaders/recon/resolve.wgsl.js +112 -8
- package/dist/render/shaders/temporalResolve.js +133 -5
- package/dist/render/shadowCasters.d.ts +20 -1
- package/dist/render/shadowCasters.js +15 -1
- package/dist/render/shadowMap.d.ts +54 -5
- package/dist/render/shadowMap.js +190 -36
- package/dist/render/sunGlassTint.d.ts +25 -0
- package/dist/render/sunGlassTint.js +79 -0
- package/dist/render/temporalAa.d.ts +145 -0
- package/dist/render/temporalAa.js +190 -0
- package/dist/render/temporalPass.d.ts +16 -14
- package/dist/render/temporalPass.js +59 -14
- package/dist/render/translucentQueue.d.ts +6 -0
- package/dist/render/translucentQueue.js +15 -1
- package/package.json +6 -6
- package/src/index.ts +10 -0
- package/src/render/backend/api.ts +15 -9
- package/src/render/backend/webgl2/glassTintPrograms.ts +58 -0
- package/src/render/backend/webgl2/renderer.ts +422 -109
- package/src/render/backend/webgpu/buffers.ts +50 -2
- package/src/render/backend/webgpu/depthPass.ts +2 -1
- package/src/render/backend/webgpu/flatPass.ts +22 -1
- package/src/render/backend/webgpu/glassTintPass.ts +244 -0
- package/src/render/backend/webgpu/gpuDrivenPass.ts +349 -5
- package/src/render/backend/webgpu/instanced.ts +21 -1
- package/src/render/backend/webgpu/latePass.ts +152 -0
- package/src/render/backend/webgpu/lightVolumePass.ts +5 -1
- package/src/render/backend/webgpu/motionPass.ts +535 -0
- package/src/render/backend/webgpu/pipelineCache.ts +12 -1
- package/src/render/backend/webgpu/pointGlassTintPass.ts +233 -0
- package/src/render/backend/webgpu/pointShadowPass.ts +158 -26
- package/src/render/backend/webgpu/postPass.ts +34 -4
- package/src/render/backend/webgpu/renderer.ts +1178 -425
- package/src/render/backend/webgpu/scatterPass.ts +2 -1
- package/src/render/backend/webgpu/skinPaletteRing.ts +4 -0
- package/src/render/backend/webgpu/snapshotMips.ts +80 -0
- package/src/render/backend/webgpu/surfaceTexturePass.ts +1 -1
- package/src/render/flameLight.ts +15 -2
- package/src/render/glass.ts +74 -0
- package/src/render/glassCasters.ts +164 -0
- package/src/render/glassShadow.ts +153 -0
- package/src/render/globalMediumPass.ts +4 -11
- package/src/render/gpudriven/lit.ts +31 -0
- package/src/render/gpudriven/materialTable.ts +28 -6
- package/src/render/gpudriven/pipeline.ts +4 -3
- package/src/render/gpudriven/sunGlass.ts +117 -0
- package/src/render/lightBudget.ts +19 -5
- package/src/render/pointGlassTint.ts +250 -0
- package/src/render/pointShadowArray.ts +188 -22
- package/src/render/pointShadowBudget.ts +49 -39
- package/src/render/pointShadowMap.ts +41 -0
- package/src/render/recon/changeFrames.ts +24 -0
- package/src/render/recon/disocclusion.ts +54 -3
- package/src/render/recon/lateRouting.ts +29 -0
- package/src/render/recon/mover.ts +118 -0
- package/src/render/recon/resolve.ts +137 -10
- package/src/render/renderQuality.ts +47 -0
- package/src/render/rendererHarness.ts +12 -0
- package/src/render/sceneTarget.ts +66 -12
- package/src/render/shaders/depth.ts +109 -9
- package/src/render/shaders/flat/directionalShadow.ts +97 -6
- package/src/render/shaders/flat/glassTint.ts +25 -0
- package/src/render/shaders/flat/index.ts +17 -0
- package/src/render/shaders/flat/lampGlass.ts +185 -0
- package/src/render/shaders/flat/main.ts +115 -15
- package/src/render/shaders/flat/pointShadow.ts +2 -0
- package/src/render/shaders/flat/preamble.ts +21 -6
- package/src/render/shaders/generated/depth.wgsl.ts +234 -4
- package/src/render/shaders/generated/flat.wgsl.ts +376 -328
- package/src/render/shaders/generated/globalMedium.wgsl.ts +3 -13
- package/src/render/shaders/generated/lightVolume.wgsl.ts +4 -14
- package/src/render/shaders/generated/octahedralResolve.wgsl.ts +30 -0
- package/src/render/shaders/generated/temporalResolve.wgsl.ts +31 -6
- package/src/render/shaders/globalMedium.ts +6 -6
- package/src/render/shaders/gpudriven/blendRaster.wgsl.ts +88 -1
- package/src/render/shaders/gpudriven/cull.wgsl.ts +11 -2
- package/src/render/shaders/gpudriven/materialTable.wgsl.ts +3 -1
- package/src/render/shaders/gpudriven/shade.wgsl.ts +50 -1
- package/src/render/shaders/gpudriven/sunGlass.wgsl.ts +139 -0
- package/src/render/shaders/lightVolume.ts +6 -6
- package/src/render/shaders/octahedralResolve.ts +50 -17
- package/src/render/shaders/recon/lateDepth.wgsl.ts +47 -0
- package/src/render/shaders/recon/motion.wgsl.ts +84 -0
- package/src/render/shaders/recon/resolve.wgsl.ts +112 -8
- package/src/render/shaders/temporalResolve.ts +141 -5
- package/src/render/shadowCasters.ts +28 -1
- package/src/render/shadowMap.ts +231 -37
- package/src/render/sunGlassTint.ts +86 -0
- package/src/render/temporalAa.ts +227 -0
- package/src/render/temporalPass.ts +88 -12
- package/src/render/translucentQueue.ts +20 -1
package/CHANGELOG.json
CHANGED
|
@@ -1,4 +1,76 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "4.5.0",
|
|
4
|
+
"date": "2026-09-29",
|
|
5
|
+
"entries": [
|
|
6
|
+
{
|
|
7
|
+
"kind": "added",
|
|
8
|
+
"short": "Moving objects stay sharp under reconstruction: name each with createMover() and it no longer leaves a ghost or a doubled edge.",
|
|
9
|
+
"text": "**A reconstruction can follow what moves, when the draw says what it is.** DriftTR reprojects each pixel by where its surface was last frame, and it knew that only for a draw handed last frame's model matrix. A consumer that passed none, which was every consumer measured, got the camera's motion for everything: right for the world, wrong for anything that moved, so a mover trailed a ghost and a doubled edge.\n\n`createMover()` makes an identity for one moving object, and `drawMesh` takes it where it took last frame's matrix. The renderer keeps that object's last model and, for a skinned draw, its last joint palette, so a bending limb reprojects as well as a sliding body. A matrix works exactly as it did. A mover drawn twice in one frame is two objects wearing one identity: the second draw is warned about once and records no motion.\n\nMeasured on `demo/dev/ghost.html` against a native four-sample frame, trail pixels without and with a mover: a slide 6,602 → 1,150, a spin 8,599 → 3,012, a skinned limb 11,648 → 1,518. **A cut is still the consumer's to say**: call `renderer.cameraCut()` where the view jumps, or the first frames after it blend the old view in. Only a reconstruction reads any of this, and reconstruction is WebGPU's."
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"kind": "added",
|
|
13
|
+
"short": "Glass: a pane shows what is behind it, blurred as far as it is frosted, keeps its own highlight, and glows with the lights behind it.",
|
|
14
|
+
"text": "**`TranslucentMeshOptions.glass`: `{ transmission, frost, tint }`.** A pane shows what is behind it by how much it lets through less what Schlick's Fresnel reflects at the view angle, keeps its own lighting and highlight, blurs what it shows by reading the level of the frame copy's mip chain its frost picks, and glows with every light behind it (the sun, lamps, rectangles and DriftLight) in proportion to its frost. It is two-sided and symmetric: seen from behind it passes and glows with the light beyond it as it does from in front. A glass caster writes no depth, so a lantern's own light leaves the lantern.\n\nA model says so three ways. `.drft` 1.19 carries the three fields; the glTF reader maps `KHR_materials_transmission`, `KHR_materials_diffuse_transmission` and `KHR_materials_volume`, rough glass arriving as frosted glass; and `DrftLoaderOptions.surface` can declare a file's opaque pane glass, which lands on `DrftPart.glass`. Both backends agree to a level on a bought courtyard's lantern at night, its panes from 95 to 246."
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"kind": "added",
|
|
18
|
+
"short": "Light through glass takes the glass's colour: sunlight and lamplight through a stained or frosted pane land tinted, and frost spreads the colour.",
|
|
19
|
+
"text": "**Coloured shadows, for every light that casts one, on both backends.** Light through a pane takes `transmission × (1 − F) × tint`: the sun's static and moving maps, pooled and live lamps, and rectangles. Each map gains a glass depth layer, the nearest pane, and an RGBA8 tint, every pane on the ray multiplied together with its clarity. A receiver is tinted only behind a pane; its outline comes from depth-tested taps and its colour from taps spread by frost and read at the tint's matching mip level, unmixed from the ground around the pane, so a frosted patch is softer and passes the light a clear one does. Measured on `demo/dev/glassShadow.html`, both backends within 0.4 levels: clear sun patches 149/56 against 149.1/55.6 derived by hand, a lamp's 47.2/30.0 against 47.1/29.8; frost moves the light it passes by 0.1 to 1.4%.\n\n**`RenderQualityOptions.glassShadows`** is `'full'`, `'half'` (the tints at half size) or `'off'`. Nothing is allocated until a glass caster reaches a map; then, at `'full'`, 78 MB for the sun's two maps and 9.8 MB a lamp layer, roughly halved at `'half'`. `'off'` casts nothing through glass and compiles the lookup out of the lit shader, which a world that never casts through glass should say: a lookup that finds no glass still costs the lit pass its registers, 0.27 ms on WebGPU and 0.42 ms on WebGL2 at 720p on a bought courtyard at night. Where glass does cast, that courtyard's lit pass costs 2.3 ms more on either backend, its lamps being enclosed in frosted glass.\n\n**What it gives up**: a pane is thin, so a solid of glass under-darkens and bends light once; DriftLight's summed far field and the probes' bounce are not tinted; frost spreads colour only inside the opaque frame's shadow; and a second copy of a pane's triangles is a second pane, so two-sided glass is declared with `doubleSided`. The core bundle grows 91.6 KB gzipped, nearly all of it the lit shaders' generated WGSL."
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"kind": "added",
|
|
23
|
+
"short": "The GPU-driven renderer draws glass, and its sunlight through glass takes the glass's colour.",
|
|
24
|
+
"text": "**`GpuDrivenMaterial.glass` takes the same `{ transmission, frost, tint }`.** A glass material is drawn in the renderer's blended half with the forward renderer's see-through, frost, Fresnel and sun glow, reading a mip chain of the opaque colour, and `GpuDrivenShadowOptions.glass` gives its sun a third light-space cut for glass, drawn into a glass layer and a tint as the forward sun's is. Its arithmetic is checked on the device against the TypeScript reference by `scripts/gpu-parity.mjs`, and its clear patches measure the forward renderer's 149/56. Its glass shadow ignores cutouts, as its opaque shadow does."
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"kind": "changed",
|
|
28
|
+
"short": "Under reconstruction, glass, captions, particles and other see-through things are drawn at full resolution, sharp and without trails.",
|
|
29
|
+
"text": "**While reconstructing, every blended draw lands after the upscale, at output resolution.** A translucent pane, a caption, a spark or a plume has no one depth a reprojection can trust, so drawn into the reconstructed picture it trailed and softened with whatever was behind it. Blended meshes, particles, plumes, bolts, lines, film, caustics and world text now draw in a late pass on the output-size frame, unjittered and depth-tested against the upscaled depth; refraction and order-independent panes read the reconstructed picture and land in it. On the ghost page a moving translucent pane's trail went from 5,751 pixels to 20, and particles' from 2,464 to 0.\n\n**Light volumes stay reconstructed**: their march reads render-size depth and is among the most expensive passes in a frame, so they keep the render size. Without a reconstruction nothing changes, and every published scene draws identically, to the pixel on WebGPU."
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"kind": "fixed",
|
|
33
|
+
"short": "Crowds of instanced objects and meshes rewritten every frame no longer leave a ghost behind them under reconstruction.",
|
|
34
|
+
"text": "**Two kinds of motion had no way to say where they had been.** An instanced batch carried one placement per instance and no previous one, and a mesh rewritten with `updateMesh` moved its vertices under a draw that looked still, so both were reprojected by the camera's motion alone and ghosted under reconstruction whatever the consumer passed. Each now keeps last frame's state beside this frame's, slot for slot and vertex for vertex, and needs nothing from the caller: the batch and the mesh are their own identity. An instanced crowd's trail on the ghost page went from 8,961 pixels to 1,340."
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"kind": "fixed",
|
|
38
|
+
"short": "WebGL2: a pane in front of a reflection probe no longer turns the whole frame grey, and a double-sided instanced batch draws both of its sides.",
|
|
39
|
+
"text": "**Three WebGL2 defects, each reached first by glass.** The copy of the frame that refraction reads rebound the scene's framebuffer on its way out rather than the caller's, so a pane drawn into a reflection probe's face attached the probe's next face to the scene and the whole frame went flat grey. WebGL2 also took that copy inside a probe bake at all, which WebGPU has always refused: the copy is of the frame on screen, not of the face. And an instanced batch never turned culling off for a double-sided material, so its far faces were missing on WebGL2 alone; 28 of one bought courtyard's 53 double-sided materials are instanced."
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"kind": "note",
|
|
43
|
+
"short": "DrftPart.glass is a new required field: code that builds its own DrftPart adds glass: null.",
|
|
44
|
+
"text": "**`DrftPart.glass` is required**, `null` for a part that is not glass, so a consumer that constructs a `DrftPart` itself, a test stub for instance, adds `glass: null` or no longer typechecks. Parts the loader makes carry it already.\n\n**And a reconstruction is still softer than native on geometry that never moves.** A mover fixes motion, not that: on the ghost page a still edge at a reconstruction of 1.5 measures about 8 in edge error against a native frame's 3, which is the reconstruction's own resolution rather than anything a consumer passes."
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"version": "4.4.2",
|
|
50
|
+
"date": "2026-09-28",
|
|
51
|
+
"entries": [
|
|
52
|
+
{
|
|
53
|
+
"kind": "fixed",
|
|
54
|
+
"short": "A reconstructed frame no longer flickers or softens along the edges of still objects: the far side of every silhouette keeps its history.",
|
|
55
|
+
"text": "**The disocclusion test compared two different surfaces at every edge.** The reconstruction reprojects each output pixel by the nearest of its nine samples, the usual dilation, and then asked whether last frame held the same surface by reading last frame's depth under the output pixel rather than where the dilated sample had stood. At a silhouette those are the object and what is behind it, so the far side of every edge, every surface turned away from the eye and every part thinner than a sample dropped its history on a still frame: a paused picture flashed white along its outlines and read softer than a single frame of it.\n\nThe test now searches last frame's three by three around where the dilated sample stood, allows for how steeply the surface recedes, and weights the normal test by how planar the surface really is, so a thin rod no longer fails it. Measured on a consumer reconstructing at 1.5: a paused frame went from 3,269 flickering pixels to 338, and a still panel from up to 1,787 to 7, with no added ghosting in motion. The cost is 0.065 ms of GPU time at 2280 by 1291."
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"kind": "fixed",
|
|
59
|
+
"short": "Temporal antialiasing no longer flashes on detail finer than a pixel while the camera is still: a paused grille, lace or crack of light holds steady.",
|
|
60
|
+
"text": "**A still pixel's neighbourhood now widens by its own proven flicker.** A thread finer than a pixel is caught by the jitter in some phases and missed in others, and in a phase that misses it the nine taps round the pixel miss it too: the box collapses onto the background, the settled history is clipped away, and a paused frame flashed at every fine edge. A still camera over a still scene samples every pixel the same way in every period of the jitter, so each pixel now keeps a small record of its own samples, and once two periods running have repeated, its box widens by the spread it has shown and it keeps more of its history. A surface that moves, a flame, or anything arriving breaks the repetition, and a sample beyond what the pixel has shown disqualifies the frame it lands in.\n\nMeasured on a scene of fine ironwork and fabric: a held frame went from 839 flickering pixels to 3 on WebGPU and from 1,802 to 14 on WebGL2, and the device check's edge figures are unchanged. It costs two half-float record targets beside the history. A moving camera is resolved exactly as before, and so is WebGL2 without float colour targets."
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"kind": "fixed",
|
|
64
|
+
"short": "A point light's shadow no longer shows a straight-edged patch of wrong shadow while its map is redrawn: a map being sampled is re-baked whole or not at all.",
|
|
65
|
+
"text": "**A re-bake spread across frames was sampled half done.** Faces land in the layer the shader reads as they are drawn, and the origin they were drawn from is published only with the last one, so a map re-baked two faces a frame was read from its old origin with part of it drawn from the new one. A cube face is a 90 degree frustum, so the wrong part was a straight-edged quadrilateral of shadow on the ground under the lamp, and with the face budget spent elsewhere it could hold for over a second.\n\nA map that already holds an image is now re-baked whole or not at all, and a light being shaded may take one whole cube a frame outside `pointShadowFacesPerFrame`, the allowance a wandering light already had. A map with no image yet still fills a few faces a frame, since nothing samples it until it is complete. What it costs is six faces in the frame a shaded light goes stale, rather than two in each of three."
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"kind": "fixed",
|
|
69
|
+
"short": "A flame's shadow no longer switches its own fixture in and out as the flame sways: the default near plane clears what the fire burns from at every point of the sway.",
|
|
70
|
+
"text": "**The near plane moved with the flame, and the fixture under it did not.** `createFlame` puts the light a third of the way up the flame, 0.83 of its width above what it burns from, with a near plane of one width, and sways it by 0.15 of a width on each axis. At the top of the sway the cut sat 7 mm under a 40 cm brazier's coals and at the bottom 13 cm, so the bowl beneath went in and out of the shadow map depending on where the flame stood when the map was last drawn, and the floor under the brazier took a dark disc on some re-bakes and none on others.\n\nThe default `shadowNear` now adds the sway, so it clears the same margin under the fire wherever the flame has wandered. A fixture reaching further below the flame than a sixth of its width sets its own `shadowNear` from its own depth."
|
|
71
|
+
}
|
|
72
|
+
]
|
|
73
|
+
},
|
|
2
74
|
{
|
|
3
75
|
"version": "4.4.1",
|
|
4
76
|
"date": "2026-09-28",
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
The runtime everything needs: renderer, loop, camera, input, geometry. Collision and dynamics live in [`@driftengine/physics`](../physics/README.md), which this package depends on and re-exports whole, so reaching for them through this barrel works as it always did.
|
|
4
4
|
|
|
5
|
-
**Cost:
|
|
5
|
+
**Cost: 887.4 KB gzipped, importing `createRenderer`.** Measured by `scripts/size-gate.test.mjs`, which fails if it drifts more than
|
|
6
6
|
3% — the number is a fact about the build rather than a claim in a document.
|
|
7
7
|
|
|
8
8
|
Part of [DriftEngine](../../README.md). See [`docs/ARCHITECTURE.md`](../../docs/ARCHITECTURE.md)
|
package/dist/index.d.ts
CHANGED
|
@@ -71,6 +71,10 @@ export type { PassAttachmentOptions, PassTarget } from './render/passTarget.ts';
|
|
|
71
71
|
export { generateMipChain, mipLevelCount, type MipPipelines, } from './render/backend/webgpu/surfaceTexturePass.ts';
|
|
72
72
|
export { createPassAttachment } from './render/passTarget.ts';
|
|
73
73
|
export { jitterClip } from './render/recon/jitter.ts';
|
|
74
|
+
export { resolveGlass } from './render/glass.ts';
|
|
75
|
+
export type { GlassOptions, ResolvedGlass } from './render/glass.ts';
|
|
76
|
+
export { createMover } from './render/recon/mover.ts';
|
|
77
|
+
export type { Mover } from './render/recon/mover.ts';
|
|
74
78
|
export type { FrameResource } from './render/frame/index.ts';
|
|
75
79
|
export type { OcclusionOptions } from './render/occlusion.ts';
|
|
76
80
|
export { OcclusionBuffer } from './render/occlusion.ts';
|
|
@@ -193,7 +197,7 @@ export type { PrefilterQuality } from './render/prefilterEnvMap.ts';
|
|
|
193
197
|
* `ProbeBakeOptions`, which is the whole of the reasoning.
|
|
194
198
|
*/
|
|
195
199
|
export type { ProbeBakeOptions } from './render/reflectionProbe.ts';
|
|
196
|
-
export type { DirectionalShadowDepthLayers, OutputTransform, RenderQuality, RenderQualityOptions, ShadowFilterTaps, WaterReflectionFilterTaps, } from './render/renderQuality.ts';
|
|
200
|
+
export type { DirectionalShadowDepthLayers, GlassShadows, OutputTransform, RenderQuality, RenderQualityOptions, ShadowFilterTaps, WaterReflectionFilterTaps, } from './render/renderQuality.ts';
|
|
197
201
|
export { MAX_POINT_LIGHTS, SURFACE_TEXTURE_UNIT } from './render/lightBudget.ts';
|
|
198
202
|
export { MAX_CLUSTERED_LIGHTS } from './render/clusteredLights.ts';
|
|
199
203
|
export { SurfaceTexture } from './render/surfaceTexture.ts';
|
package/dist/index.js
CHANGED
|
@@ -86,6 +86,13 @@ export { createPassAttachment } from './render/passTarget.js';
|
|
|
86
86
|
* resolve finds its geometry where the renderer's own verbs put theirs.
|
|
87
87
|
*/
|
|
88
88
|
export { jitterClip } from './render/recon/jitter.js';
|
|
89
|
+
/*
|
|
90
|
+
* Which object a draw is, for a reconstruction that has to find where it was last frame. See
|
|
91
|
+
* `RendererApi.drawMesh`.
|
|
92
|
+
*/
|
|
93
|
+
/* Glass: a pane that shows what is behind it, clear or frosted. See `TranslucentMeshOptions.glass`. */
|
|
94
|
+
export { resolveGlass } from './render/glass.js';
|
|
95
|
+
export { createMover } from './render/recon/mover.js';
|
|
89
96
|
export { OcclusionBuffer } from './render/occlusion.js';
|
|
90
97
|
/*
|
|
91
98
|
* `Renderer` above stays exported and is not deprecated. `createRenderer` is the way to get
|
|
@@ -10,6 +10,7 @@ import type { TextStyle } from '../textLayout.ts';
|
|
|
10
10
|
import type { SdfFont } from '../sdfFont.ts';
|
|
11
11
|
import type { SdfTextStyle } from '../sdfTextLayout.ts';
|
|
12
12
|
import type { FrameTimer } from './timer.ts';
|
|
13
|
+
import type { Mover } from '../recon/mover.ts';
|
|
13
14
|
/**
|
|
14
15
|
* Geometry on the device, as something a consumer holds and hands back.
|
|
15
16
|
*
|
|
@@ -466,18 +467,23 @@ export type RendererApi = Omit<{
|
|
|
466
467
|
/** Draw a handle this renderer made. Passing one from the other backend is a caller error. */
|
|
467
468
|
drawMesh(mesh: MeshHandle, model: ReadonlyMat4, depthLayer?: number, tint?: Vec3 | null,
|
|
468
469
|
/**
|
|
469
|
-
* Where this mesh's surface was last frame, for a reconstruction's motion target
|
|
470
|
-
*
|
|
471
|
-
*
|
|
472
|
-
*
|
|
473
|
-
*
|
|
474
|
-
*
|
|
475
|
-
*
|
|
476
|
-
*
|
|
477
|
-
*
|
|
478
|
-
*
|
|
470
|
+
* Where this mesh's surface was last frame, for a reconstruction's motion target: a `Mover`,
|
|
471
|
+
* or last frame's model matrix.
|
|
472
|
+
*
|
|
473
|
+
* **A `Mover` is the ordinary answer.** Make one per moving object with `createMover()` and pass
|
|
474
|
+
* it with every draw of that object; the renderer keeps last frame's model and, for a skinned
|
|
475
|
+
* draw, last frame's palette. A matrix still works exactly as it always has: the *model* matrix
|
|
476
|
+
* this mesh was drawn with last frame, not a velocity, so a rotation and a scale are as correct
|
|
477
|
+
* as a translation. Null and omitted mean the same thing: the camera's motion, derived from the
|
|
478
|
+
* depth, which is exactly right for anything that did not move and wrong in proportion to how
|
|
479
|
+
* far a mover moved.
|
|
480
|
+
*
|
|
481
|
+
* **Only a reconstruction reads it**, and only on WebGPU. A mover drawn twice in one frame is
|
|
482
|
+
* two objects wearing one identity: the second draw is warned about once and records no motion.
|
|
483
|
+
* Instanced batches and meshes rewritten with `updateMesh` need none — the batch and the mesh
|
|
484
|
+
* are their own identity.
|
|
479
485
|
*/
|
|
480
|
-
previousModel?: ReadonlyMat4 | null): void;
|
|
486
|
+
previousModel?: ReadonlyMat4 | Mover | null): void;
|
|
481
487
|
/** Release the geometry behind a handle. */
|
|
482
488
|
disposeMesh(mesh: MeshHandle): void;
|
|
483
489
|
/**
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface GlassTintProgram {
|
|
2
|
+
readonly program: WebGLProgram;
|
|
3
|
+
readonly uniforms: Record<string, WebGLUniformLocation>;
|
|
4
|
+
}
|
|
5
|
+
export declare class GlassTintPrograms {
|
|
6
|
+
readonly rigid: GlassTintProgram;
|
|
7
|
+
readonly instanced: GlassTintProgram;
|
|
8
|
+
readonly skinned: GlassTintProgram;
|
|
9
|
+
readonly cutout: GlassTintProgram;
|
|
10
|
+
readonly instancedCutout: GlassTintProgram;
|
|
11
|
+
constructor(gl: WebGL2RenderingContext);
|
|
12
|
+
dispose(gl: WebGL2RenderingContext): void;
|
|
13
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The five programs a pane casts its colour through, one per way a caster is drawn, compiled the
|
|
3
|
+
* first time glass casts — so a scene with no glass compiles none of them.
|
|
4
|
+
*
|
|
5
|
+
* The vertex stages are the depth pass's with the world position handed on (`depth.ts`), so a
|
|
6
|
+
* pane's colour lands exactly where its depth does; the fragment is `paneTexel` for the device.
|
|
7
|
+
*/
|
|
8
|
+
import { compileProgram, uniformLocations } from '../../shader.js';
|
|
9
|
+
import { GLASS_TINT_CUTOUT_FRAG, GLASS_TINT_CUTOUT_VERT, GLASS_TINT_FRAG, GLASS_TINT_INSTANCED_CUTOUT_VERT, GLASS_TINT_INSTANCED_VERT, GLASS_TINT_SKINNED_VERT, GLASS_TINT_VERT, } from '../../shaders/depth.js';
|
|
10
|
+
export class GlassTintPrograms {
|
|
11
|
+
rigid;
|
|
12
|
+
instanced;
|
|
13
|
+
skinned;
|
|
14
|
+
cutout;
|
|
15
|
+
instancedCutout;
|
|
16
|
+
constructor(gl) {
|
|
17
|
+
const build = (vert, frag, label) => {
|
|
18
|
+
const program = compileProgram(gl, vert, frag, label);
|
|
19
|
+
return { program, uniforms: uniformLocations(gl, program, label) };
|
|
20
|
+
};
|
|
21
|
+
this.rigid = build(GLASS_TINT_VERT, GLASS_TINT_FRAG, 'glassTint');
|
|
22
|
+
this.instanced = build(GLASS_TINT_INSTANCED_VERT, GLASS_TINT_FRAG, 'glassTint.instanced');
|
|
23
|
+
this.skinned = build(GLASS_TINT_SKINNED_VERT, GLASS_TINT_FRAG, 'glassTint.skinned');
|
|
24
|
+
this.cutout = build(GLASS_TINT_CUTOUT_VERT, GLASS_TINT_CUTOUT_FRAG, 'glassTint.cutout');
|
|
25
|
+
this.instancedCutout = build(GLASS_TINT_INSTANCED_CUTOUT_VERT, GLASS_TINT_CUTOUT_FRAG, 'glassTint.instancedCutout');
|
|
26
|
+
}
|
|
27
|
+
dispose(gl) {
|
|
28
|
+
for (const { program } of [
|
|
29
|
+
this.rigid,
|
|
30
|
+
this.instanced,
|
|
31
|
+
this.skinned,
|
|
32
|
+
this.cutout,
|
|
33
|
+
this.instancedCutout,
|
|
34
|
+
]) {
|
|
35
|
+
gl.deleteProgram(program);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { FrameBudget } from '../budget.ts';
|
|
2
|
+
import type { Mover } from '../../recon/mover.ts';
|
|
3
|
+
import type { GlassOptions } from '../../glass.ts';
|
|
2
4
|
import type { ReadonlyMat4 } from 'gl-matrix';
|
|
3
5
|
import type { Camera } from '../../camera.ts';
|
|
4
6
|
import type { PickHit, PickableSource } from '../../pickable.ts';
|
|
@@ -521,6 +523,13 @@ export interface TranslucentMeshOptions {
|
|
|
521
523
|
* clear, and it is the whole difference between this and a flat tint.
|
|
522
524
|
*/
|
|
523
525
|
readonly thicknessM?: number;
|
|
526
|
+
/**
|
|
527
|
+
* Glass: the pane shows what is behind it, by how much it lets through and how little it reflects
|
|
528
|
+
* at the view angle, blurred by how frosted it is, tinted, and glowing with the lights behind it.
|
|
529
|
+
* It keeps its own lighting and highlight, which `refraction` alone replaces. Absent, or letting
|
|
530
|
+
* nothing through, is not glass. See `glass.ts`; `refraction` still bends what a pane shows.
|
|
531
|
+
*/
|
|
532
|
+
readonly glass?: GlassOptions;
|
|
524
533
|
/**
|
|
525
534
|
* Whether this draw writes depth. `true`, which is what it has always done, unless a caller
|
|
526
535
|
* says otherwise.
|
|
@@ -819,6 +828,8 @@ export declare class WebGL2Renderer implements RendererApi {
|
|
|
819
828
|
/** Whether a palette is currently chosen. Distinct from whether one was ever uploaded. */
|
|
820
829
|
private skinPaletteSet;
|
|
821
830
|
private readonly emptyTexture2D;
|
|
831
|
+
/** One glass resolution reused by every draw, so a pane allocates nothing. See `glass.ts`. */
|
|
832
|
+
private readonly glassScratch;
|
|
822
833
|
/** DriftLight's stand-ins while no field is whole: no brick anywhere, and no light. */
|
|
823
834
|
private readonly emptyDriftIndex;
|
|
824
835
|
private readonly emptyDriftAtlas;
|
|
@@ -947,6 +958,9 @@ export declare class WebGL2Renderer implements RendererApi {
|
|
|
947
958
|
* Scratch, filled in `endFrame`, which may not allocate.
|
|
948
959
|
*/
|
|
949
960
|
private frameProjection;
|
|
961
|
+
/** The temporal resolve's depth-to-metres row, from the inverse of `frameProjection`. */
|
|
962
|
+
private readonly taaInvProjection;
|
|
963
|
+
private readonly taaDepthToViewZ;
|
|
950
964
|
private readonly aoInvProjection;
|
|
951
965
|
private readonly aoProjScale;
|
|
952
966
|
/**
|
|
@@ -1005,9 +1019,8 @@ export declare class WebGL2Renderer implements RendererApi {
|
|
|
1005
1019
|
private readonly depthInstancedCutoutUniforms;
|
|
1006
1020
|
private readonly scatterDepthProgram;
|
|
1007
1021
|
private readonly scatterDepthUniforms;
|
|
1008
|
-
|
|
1009
|
-
private readonly
|
|
1010
|
-
private readonly dynamicShadowMap;
|
|
1022
|
+
/** The sun's static, moving and peeled maps, as layers of one array. See `shadowMap.ts`. */
|
|
1023
|
+
private readonly sunShadows;
|
|
1011
1024
|
private readonly pointShadows;
|
|
1012
1025
|
/**
|
|
1013
1026
|
* The layers a world's casting rectangles hold, above the point pool in the same array.
|
|
@@ -1178,7 +1191,7 @@ export declare class WebGL2Renderer implements RendererApi {
|
|
|
1178
1191
|
/** Non-zero while the drawing buffer is pinned; see `lockDrawingBuffer`. */
|
|
1179
1192
|
private lockedWidth;
|
|
1180
1193
|
private lockedHeight;
|
|
1181
|
-
private
|
|
1194
|
+
private activeSunLayer;
|
|
1182
1195
|
private reflectionPassActive;
|
|
1183
1196
|
private reflectionReadyThisFrame;
|
|
1184
1197
|
private reflectionAtmosphereY;
|
|
@@ -1200,7 +1213,7 @@ export declare class WebGL2Renderer implements RendererApi {
|
|
|
1200
1213
|
*
|
|
1201
1214
|
* **Not whether the map exists.** That was the test here, on the belief that a GL texture is
|
|
1202
1215
|
* born reading as the far plane; it is born zeroed, and a scene that built the layer and never
|
|
1203
|
-
* peeled it sampled an occluder at the light. `
|
|
1216
|
+
* peeled it sampled an occluder at the light. `SunShadowArray` clears itself at birth, so an
|
|
1204
1217
|
* unfilled layer would read as lit either way — this is what keeps the two backends one
|
|
1205
1218
|
* decision, and a frame that does not peel from paying a fetch per tap for nothing.
|
|
1206
1219
|
*/
|
|
@@ -1226,6 +1239,21 @@ export declare class WebGL2Renderer implements RendererApi {
|
|
|
1226
1239
|
* Built once at construction, arrow properties closing over `this`: a sink created
|
|
1227
1240
|
* per pass would allocate six objects per light per frame.
|
|
1228
1241
|
*/
|
|
1242
|
+
/** What the sun's light keeps through glass, made the first time glass casts: `sunGlassTint.ts`. */
|
|
1243
|
+
private sunGlassTint;
|
|
1244
|
+
/** The five programs a pane casts its colour through, compiled the first time glass casts. */
|
|
1245
|
+
private glassTintPrograms;
|
|
1246
|
+
/** True while the glass list is replayed into the glass depth layer through `casterSink`. */
|
|
1247
|
+
private drawingGlassDepth;
|
|
1248
|
+
/** How many times a shadow array grew its glass layers: once per family, and never again. */
|
|
1249
|
+
private sunGlassRebuilds;
|
|
1250
|
+
/** The light a tint pass is drawn for, and one pane's colour and clarity: uploaded per entry. */
|
|
1251
|
+
private readonly glassLight;
|
|
1252
|
+
private readonly glassPane;
|
|
1253
|
+
/** The glass the open shadow pass was offered, kept for its own passes: `glassCasters.ts`. */
|
|
1254
|
+
private readonly glassCasters;
|
|
1255
|
+
/** One resolution every glass caster is read through, so recording one allocates nothing. */
|
|
1256
|
+
private readonly glassCasterScratch;
|
|
1229
1257
|
private readonly casterSink;
|
|
1230
1258
|
/**
|
|
1231
1259
|
* What a cutout depth draw needs beyond the plain one: the pass's matrix and peel, the material's
|
|
@@ -1233,6 +1261,13 @@ export declare class WebGL2Renderer implements RendererApi {
|
|
|
1233
1261
|
*/
|
|
1234
1262
|
private bindCutoutDepth;
|
|
1235
1263
|
private readonly drawPointShadowFace;
|
|
1264
|
+
/**
|
|
1265
|
+
* A lamp's glass, after each face's opaque depth: `PointShadowMap.bake` asks and binds, this
|
|
1266
|
+
* draws, through the same sinks the sun's glass takes and in the face's own matrix.
|
|
1267
|
+
*/
|
|
1268
|
+
private readonly pointGlassDraw;
|
|
1269
|
+
/** The glass hook a bake is handed: none at all when glass shadows are off. */
|
|
1270
|
+
private get pointGlass();
|
|
1236
1271
|
/**
|
|
1237
1272
|
* Viewport in CSS pixels rather than device pixels.
|
|
1238
1273
|
*
|
|
@@ -1840,6 +1875,21 @@ export declare class WebGL2Renderer implements RendererApi {
|
|
|
1840
1875
|
* consumer's, which is also where the placements are.
|
|
1841
1876
|
*/
|
|
1842
1877
|
private submitInstanced;
|
|
1878
|
+
/**
|
|
1879
|
+
* Bind what a translucent draw shows through it: the frame's copy, refraction's bend and absorption,
|
|
1880
|
+
* and glass. Returns whether the copy is bound, and so whether `unbindSeeThrough` owes it back.
|
|
1881
|
+
*
|
|
1882
|
+
* **A glass draw takes the copy even when it does not bend**, since a pane shows what is behind it
|
|
1883
|
+
* either way, and asks for the copy's mip chain, which a frosted pane reads blurred. A null copy
|
|
1884
|
+
* leaves both off, so the pane shades as ordinary translucency rather than sampling black.
|
|
1885
|
+
*
|
|
1886
|
+
* **Refused inside a probe's face or a mirror**, as WebGPU's `takeRefractSnapshot` refuses: the
|
|
1887
|
+
* copy is of the frame drawn to the screen, so a pane there would show the wrong picture, and
|
|
1888
|
+
* taking it mid-bake is how a probe's next face came to be attached to the scene's framebuffer.
|
|
1889
|
+
*/
|
|
1890
|
+
private bindSeeThrough;
|
|
1891
|
+
/** Put back what `bindSeeThrough` bound: the binding outlives its frame (the 2026-08-27 rule). */
|
|
1892
|
+
private unbindSeeThrough;
|
|
1843
1893
|
disposeMesh(mesh: Mesh): void;
|
|
1844
1894
|
/**
|
|
1845
1895
|
* Release a resource this renderer created, for every kind that needs the context back.
|
|
@@ -2326,6 +2376,25 @@ export declare class WebGL2Renderer implements RendererApi {
|
|
|
2326
2376
|
*/
|
|
2327
2377
|
drawSceneCasters(casters: ShadowCasters): void;
|
|
2328
2378
|
drawShadowCasters(casters: ShadowCasters): void;
|
|
2379
|
+
/**
|
|
2380
|
+
* Draw the pass's glass twice: where the nearest pane is, and what the panes let through.
|
|
2381
|
+
*
|
|
2382
|
+
* After the opaque casters, in the pass's own light matrix. A layer that has held glass is
|
|
2383
|
+
* redrawn even when this pass offered none, so glass that has gone takes its colour with it. The
|
|
2384
|
+
* first glass grows the array (`SunShadowArray.growForGlass`) and makes the tint target.
|
|
2385
|
+
*/
|
|
2386
|
+
private flushSunGlass;
|
|
2387
|
+
/** The glass list into the glass depth layer: `casterSink` itself, with glass let through. */
|
|
2388
|
+
private readonly glassDepthSink;
|
|
2389
|
+
/** One pane's tint uniforms, and its cutout where it has one. */
|
|
2390
|
+
private bindGlassTint;
|
|
2391
|
+
/**
|
|
2392
|
+
* The glass list into the tint layer, through the tint programs, **culling nothing**: a light
|
|
2393
|
+
* crosses a pane whichever way the pane faces, and a closed glass object has two surfaces on a
|
|
2394
|
+
* ray, so every one counts. What that asks of a model is that a pane be one surface — two-sided
|
|
2395
|
+
* glass says so with `doubleSided`, and a second copy of its triangles is a second pane.
|
|
2396
|
+
*/
|
|
2397
|
+
private readonly glassTintSink;
|
|
2329
2398
|
endShadowPass(): void;
|
|
2330
2399
|
/**
|
|
2331
2400
|
* The lit program, built at the largest light budget this device will actually link.
|
|
@@ -2583,6 +2652,10 @@ export declare class WebGL2Renderer implements RendererApi {
|
|
|
2583
2652
|
*
|
|
2584
2653
|
* What it gives up is one frame of history: the frame after a cut has no blur and no temporal
|
|
2585
2654
|
* blend, as the first frame of a session has none. Nothing else is reset.
|
|
2655
|
+
*
|
|
2656
|
+
* **A reconstructing renderer depends on it**: its history is the last shot's, and without this
|
|
2657
|
+
* call a cut blends that shot into the first frames of the next. Nothing detects a cut on the
|
|
2658
|
+
* caller's behalf, deliberately — a fast pan and a cut look alike from here.
|
|
2586
2659
|
*/
|
|
2587
2660
|
cameraCut(): void;
|
|
2588
2661
|
/**
|
|
@@ -3047,13 +3120,14 @@ export declare class WebGL2Renderer implements RendererApi {
|
|
|
3047
3120
|
*/
|
|
3048
3121
|
tint?: Vec3 | null,
|
|
3049
3122
|
/**
|
|
3050
|
-
* Where the mesh was last frame
|
|
3123
|
+
* Where the mesh was last frame — a `Mover` or a matrix — which this backend takes and ignores.
|
|
3051
3124
|
*
|
|
3052
3125
|
* Accepted rather than absent so that one scene draws through both renderers unchanged — the
|
|
3053
3126
|
* parity rule this repository is built on. Reconstruction is WebGPU's, having no compute stage
|
|
3054
|
-
* here, so there is no motion target for this to be written into
|
|
3127
|
+
* here, so there is no motion target for this to be written into, and a mover passed here is
|
|
3128
|
+
* neither read nor advanced.
|
|
3055
3129
|
*/
|
|
3056
|
-
_previousModel?: ReadonlyMat4 | null): void;
|
|
3130
|
+
_previousModel?: ReadonlyMat4 | Mover | null): void;
|
|
3057
3131
|
/**
|
|
3058
3132
|
* Draw a mesh you can see through, in the same material as everything else by default.
|
|
3059
3133
|
*
|