@driftengine/core 4.4.2 → 4.6.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 +97 -0
- package/README.md +1 -1
- package/dist/geometry/boxCsg.d.ts +28 -0
- package/dist/geometry/boxCsg.js +139 -0
- package/dist/geometry/csg.d.ts +36 -0
- package/dist/geometry/csg.js +329 -0
- package/dist/geometry/meshBuilder.js +13 -0
- package/dist/geometry/meshConcat.js +1 -0
- package/dist/geometry/pixelFont.js +2 -0
- package/dist/geometry/solid.d.ts +61 -0
- package/dist/geometry/solid.js +152 -0
- package/dist/geometry/solidFlat.d.ts +35 -0
- package/dist/geometry/solidFlat.js +428 -0
- package/dist/geometry/solidHarness.d.ts +19 -0
- package/dist/geometry/solidHarness.js +66 -0
- package/dist/geometry/solidNormals.d.ts +17 -0
- package/dist/geometry/solidNormals.js +86 -0
- package/dist/geometry/solidRound.d.ts +41 -0
- package/dist/geometry/solidRound.js +323 -0
- package/dist/geometry/solidWriter.d.ts +16 -0
- package/dist/geometry/solidWriter.js +42 -0
- package/dist/index.d.ts +28 -3
- package/dist/index.js +20 -1
- package/dist/render/backend/api.d.ts +34 -14
- package/dist/render/backend/drawFog.d.ts +26 -0
- package/dist/render/backend/drawFog.js +30 -0
- package/dist/render/backend/materialChanges.d.ts +2 -1
- package/dist/render/backend/materialChanges.js +6 -1
- package/dist/render/backend/webgl2/glassTintPrograms.d.ts +13 -0
- package/dist/render/backend/webgl2/glassTintPrograms.js +38 -0
- package/dist/render/backend/webgl2/instanced.d.ts +24 -5
- package/dist/render/backend/webgl2/instanced.js +72 -15
- package/dist/render/backend/webgl2/renderer.d.ts +201 -16
- package/dist/render/backend/webgl2/renderer.js +596 -224
- package/dist/render/backend/webgpu/buffers.d.ts +29 -1
- package/dist/render/backend/webgpu/buffers.js +61 -4
- package/dist/render/backend/webgpu/depthPass.d.ts +1 -1
- package/dist/render/backend/webgpu/depthPass.js +7 -2
- package/dist/render/backend/webgpu/drawCommand.d.ts +5 -0
- package/dist/render/backend/webgpu/drawCommand.js +1 -0
- package/dist/render/backend/webgpu/flatPass.d.ts +6 -1
- package/dist/render/backend/webgpu/flatPass.js +57 -9
- package/dist/render/backend/webgpu/glassTintPass.d.ts +28 -0
- package/dist/render/backend/webgpu/glassTintPass.js +206 -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/instanceCullPass.d.ts +34 -0
- package/dist/render/backend/webgpu/instanceCullPass.js +144 -0
- package/dist/render/backend/webgpu/instanced.d.ts +23 -2
- package/dist/render/backend/webgpu/instanced.js +41 -4
- package/dist/render/backend/webgpu/latePass.d.ts +30 -0
- package/dist/render/backend/webgpu/latePass.js +140 -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 +3 -13
- package/dist/render/backend/webgpu/renderer.d.ts +271 -64
- package/dist/render/backend/webgpu/renderer.js +1395 -580
- package/dist/render/backend/webgpu/scatterPass.js +2 -1
- package/dist/render/backend/webgpu/sdfTextPass.js +6 -1
- package/dist/render/backend/webgpu/shaders/instanceCull.wgsl.d.ts +18 -0
- package/dist/render/backend/webgpu/shaders/instanceCull.wgsl.js +59 -0
- 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 +22 -3
- package/dist/render/backend/webgpu/surfaceTexturePass.js +78 -39
- package/dist/render/driftLight/bake.d.ts +7 -0
- package/dist/render/driftLight/bake.js +61 -56
- package/dist/render/driftLight/denseField.d.ts +46 -0
- package/dist/render/driftLight/denseField.js +109 -0
- package/dist/render/driftLight/lightField.d.ts +10 -5
- package/dist/render/driftLight/lightField.js +25 -19
- package/dist/render/driftLight/presence.d.ts +50 -0
- package/dist/render/driftLight/presence.js +43 -0
- package/dist/render/driftLight/uniforms.d.ts +3 -3
- package/dist/render/driftLight/uniforms.js +5 -6
- package/dist/render/driftLight/worldLightField.d.ts +41 -0
- package/dist/render/driftLight/worldLightField.js +66 -0
- package/dist/render/fixtureAtlas.d.ts +20 -0
- package/dist/render/fixtureAtlas.js +49 -0
- 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/instanceCull.d.ts +63 -0
- package/dist/render/instanceCull.js +160 -0
- package/dist/render/instances.d.ts +15 -0
- package/dist/render/lightBudget.d.ts +36 -35
- package/dist/render/lightBudget.js +38 -37
- package/dist/render/lightGrid.d.ts +42 -0
- package/dist/render/lightGrid.js +87 -0
- package/dist/render/mesh.d.ts +18 -24
- package/dist/render/mesh.js +51 -68
- package/dist/render/occlusion.d.ts +10 -0
- package/dist/render/occlusion.js +36 -7
- package/dist/render/pointGlassTint.d.ts +59 -0
- package/dist/render/pointGlassTint.js +198 -0
- package/dist/render/pointLightSelection.d.ts +7 -0
- package/dist/render/pointLightSelection.js +29 -4
- package/dist/render/pointShadowArray.d.ts +56 -3
- package/dist/render/pointShadowArray.js +127 -16
- package/dist/render/pointShadowMap.d.ts +23 -1
- package/dist/render/pointShadowMap.js +27 -1
- package/dist/render/rainField.d.ts +13 -0
- package/dist/render/rainField.js +27 -5
- package/dist/render/recon/changeFrames.d.ts +15 -0
- package/dist/render/recon/changeFrames.js +21 -0
- package/dist/render/recon/lateDepth.d.ts +11 -0
- package/dist/render/recon/lateDepth.js +70 -0
- 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.d.ts +34 -4
- package/dist/render/recon/resolve.js +161 -20
- package/dist/render/renderQuality.d.ts +35 -0
- package/dist/render/renderQuality.js +7 -0
- package/dist/render/rendererHarness.js +16 -0
- package/dist/render/sceneTarget.d.ts +9 -1
- package/dist/render/sceneTarget.js +60 -12
- package/dist/render/shaders/depth.d.ts +16 -1
- package/dist/render/shaders/depth.js +94 -15
- package/dist/render/shaders/flat/directionalShadow.js +91 -6
- package/dist/render/shaders/flat/driftLight.d.ts +1 -1
- package/dist/render/shaders/flat/driftLight.js +32 -7
- 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 +9 -3
- 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 +190 -38
- 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 +96 -26
- package/dist/render/shaders/flat/surfaceEffects.d.ts +29 -0
- package/dist/render/shaders/flat/surfaceEffects.js +152 -0
- package/dist/render/shaders/generated/depth.wgsl.d.ts +230 -7
- package/dist/render/shaders/generated/depth.wgsl.js +230 -7
- package/dist/render/shaders/generated/flat.wgsl.d.ts +1644 -1596
- package/dist/render/shaders/generated/flat.wgsl.js +1683 -1621
- 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 +21 -17
- 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/rush.wgsl.d.ts +21 -16
- package/dist/render/shaders/generated/rush.wgsl.js +21 -16
- package/dist/render/shaders/generated/sdfText.wgsl.d.ts +2 -2
- package/dist/render/shaders/generated/sdfText.wgsl.js +2 -2
- package/dist/render/shaders/generated/text.wgsl.d.ts +1 -1
- package/dist/render/shaders/generated/text.wgsl.js +1 -1
- package/dist/render/shaders/gi/driftLight.wgsl.d.ts +1 -1
- package/dist/render/shaders/gi/driftLight.wgsl.js +27 -4
- 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 +69 -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 +8 -7
- package/dist/render/shaders/recon/resolve.wgsl.js +161 -27
- package/dist/render/shaders/rush.js +11 -1
- package/dist/render/shaders/sdfText.d.ts +1 -1
- package/dist/render/shaders/sdfText.js +3 -2
- package/dist/render/shaders/text.d.ts +1 -1
- package/dist/render/shaders/text.js +18 -9
- 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/surfaceEffects.d.ts +83 -0
- package/dist/render/surfaceEffects.js +75 -0
- package/dist/render/surfaceScene.d.ts +8 -0
- package/dist/render/surfaceScene.js +8 -0
- package/dist/render/surfaceTexture.d.ts +18 -2
- package/dist/render/surfaceTexture.js +68 -15
- package/dist/render/temporalAa.d.ts +25 -6
- package/dist/render/temporalAa.js +45 -15
- package/dist/render/textureSource.d.ts +30 -0
- package/dist/render/textureSource.js +53 -0
- package/dist/render/translucentQueue.d.ts +6 -0
- package/dist/render/translucentQueue.js +15 -1
- package/dist/render/vertexDefaults.js +2 -0
- package/dist/world/hlod.d.ts +104 -0
- package/dist/world/hlod.js +214 -0
- package/package.json +6 -6
- package/src/geometry/boxCsg.ts +186 -0
- package/src/geometry/csg.ts +384 -0
- package/src/geometry/meshBuilder.ts +15 -0
- package/src/geometry/meshConcat.ts +1 -0
- package/src/geometry/pixelFont.ts +2 -0
- package/src/geometry/solid.ts +189 -0
- package/src/geometry/solidFlat.ts +522 -0
- package/src/geometry/solidHarness.ts +83 -0
- package/src/geometry/solidNormals.ts +103 -0
- package/src/geometry/solidRound.ts +443 -0
- package/src/geometry/solidWriter.ts +58 -0
- package/src/index.ts +61 -1
- package/src/render/backend/api.ts +36 -11
- package/src/render/backend/drawFog.ts +31 -0
- package/src/render/backend/materialChanges.ts +9 -2
- package/src/render/backend/webgl2/glassTintPrograms.ts +58 -0
- package/src/render/backend/webgl2/instanced.ts +80 -14
- package/src/render/backend/webgl2/renderer.ts +700 -250
- package/src/render/backend/webgpu/buffers.ts +92 -5
- package/src/render/backend/webgpu/depthPass.ts +7 -2
- package/src/render/backend/webgpu/drawCommand.ts +6 -0
- package/src/render/backend/webgpu/flatPass.ts +62 -11
- package/src/render/backend/webgpu/glassTintPass.ts +245 -0
- package/src/render/backend/webgpu/gpuDrivenPass.ts +349 -5
- package/src/render/backend/webgpu/instanceCullPass.ts +165 -0
- package/src/render/backend/webgpu/instanced.ts +42 -4
- package/src/render/backend/webgpu/latePass.ts +161 -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/renderer.ts +1671 -670
- package/src/render/backend/webgpu/scatterPass.ts +2 -1
- package/src/render/backend/webgpu/sdfTextPass.ts +6 -1
- package/src/render/backend/webgpu/shaders/instanceCull.wgsl.ts +61 -0
- 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 +91 -51
- package/src/render/driftLight/bake.ts +85 -62
- package/src/render/driftLight/denseField.ts +149 -0
- package/src/render/driftLight/lightField.ts +33 -18
- package/src/render/driftLight/presence.ts +69 -0
- package/src/render/driftLight/uniforms.ts +8 -9
- package/src/render/driftLight/worldLightField.ts +83 -0
- package/src/render/fixtureAtlas.ts +63 -0
- 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/instanceCull.ts +205 -0
- package/src/render/instances.ts +16 -0
- package/src/render/lightBudget.ts +41 -38
- package/src/render/lightGrid.ts +130 -0
- package/src/render/mesh.ts +59 -72
- package/src/render/occlusion.ts +51 -7
- package/src/render/pointGlassTint.ts +250 -0
- package/src/render/pointLightSelection.ts +72 -4
- package/src/render/pointShadowArray.ts +188 -22
- package/src/render/pointShadowMap.ts +41 -0
- package/src/render/rainField.ts +39 -5
- package/src/render/recon/changeFrames.ts +24 -0
- package/src/render/recon/lateDepth.ts +83 -0
- package/src/render/recon/lateRouting.ts +29 -0
- package/src/render/recon/mover.ts +118 -0
- package/src/render/recon/resolve.ts +206 -20
- package/src/render/renderQuality.ts +47 -0
- package/src/render/rendererHarness.ts +16 -0
- package/src/render/sceneTarget.ts +62 -11
- package/src/render/shaders/depth.ts +118 -15
- package/src/render/shaders/flat/directionalShadow.ts +97 -6
- package/src/render/shaders/flat/driftLight.ts +32 -7
- package/src/render/shaders/flat/glassTint.ts +25 -0
- package/src/render/shaders/flat/index.ts +22 -3
- package/src/render/shaders/flat/lampGlass.ts +185 -0
- package/src/render/shaders/flat/main.ts +190 -38
- package/src/render/shaders/flat/pointShadow.ts +2 -0
- package/src/render/shaders/flat/preamble.ts +96 -26
- package/src/render/shaders/flat/surfaceEffects.ts +152 -0
- package/src/render/shaders/generated/depth.wgsl.ts +237 -7
- package/src/render/shaders/generated/flat.wgsl.ts +1685 -1621
- package/src/render/shaders/generated/globalMedium.wgsl.ts +3 -13
- package/src/render/shaders/generated/lightVolume.wgsl.ts +23 -17
- package/src/render/shaders/generated/octahedralResolve.wgsl.ts +30 -0
- package/src/render/shaders/generated/rush.wgsl.ts +21 -16
- package/src/render/shaders/generated/sdfText.wgsl.ts +2 -2
- package/src/render/shaders/generated/text.wgsl.ts +1 -1
- package/src/render/shaders/gi/driftLight.wgsl.ts +27 -4
- 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 +72 -0
- package/src/render/shaders/recon/motion.wgsl.ts +84 -0
- package/src/render/shaders/recon/resolve.wgsl.ts +161 -27
- package/src/render/shaders/rush.ts +11 -1
- package/src/render/shaders/sdfText.ts +3 -2
- package/src/render/shaders/text.ts +18 -9
- package/src/render/shadowCasters.ts +28 -1
- package/src/render/shadowMap.ts +231 -37
- package/src/render/sunGlassTint.ts +86 -0
- package/src/render/surfaceEffects.ts +132 -0
- package/src/render/surfaceScene.ts +16 -0
- package/src/render/surfaceTexture.ts +110 -19
- package/src/render/temporalAa.ts +78 -14
- package/src/render/textureSource.ts +72 -0
- package/src/render/translucentQueue.ts +20 -1
- package/src/render/vertexDefaults.ts +2 -0
- package/src/world/hlod.ts +290 -0
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/** The most cells a grid may span, which keeps a stray light far away from costing a gigabyte. */
|
|
2
|
+
export const LIGHT_GRID_MAX_CELLS = 1 << 22;
|
|
3
|
+
/** Bucket `sources` into cells of `cell` metres. Built once; not a frame path. */
|
|
4
|
+
export function createLightGrid(sources, cell) {
|
|
5
|
+
if (!(cell > 0))
|
|
6
|
+
throw new Error(`createLightGrid: a cell of ${String(cell)} metres`);
|
|
7
|
+
let minX = Infinity;
|
|
8
|
+
let minY = Infinity;
|
|
9
|
+
let minZ = Infinity;
|
|
10
|
+
let maxX = -Infinity;
|
|
11
|
+
let maxY = -Infinity;
|
|
12
|
+
let maxZ = -Infinity;
|
|
13
|
+
let maxRadius = 0;
|
|
14
|
+
for (const light of sources) {
|
|
15
|
+
minX = Math.min(minX, light.x);
|
|
16
|
+
minY = Math.min(minY, light.y);
|
|
17
|
+
minZ = Math.min(minZ, light.z);
|
|
18
|
+
maxX = Math.max(maxX, light.x);
|
|
19
|
+
maxY = Math.max(maxY, light.y);
|
|
20
|
+
maxZ = Math.max(maxZ, light.z);
|
|
21
|
+
maxRadius = Math.max(maxRadius, light.radius);
|
|
22
|
+
}
|
|
23
|
+
if (sources.length === 0)
|
|
24
|
+
minX = minY = minZ = maxX = maxY = maxZ = 0;
|
|
25
|
+
const dims = [
|
|
26
|
+
Math.floor((maxX - minX) / cell) + 1,
|
|
27
|
+
Math.floor((maxY - minY) / cell) + 1,
|
|
28
|
+
Math.floor((maxZ - minZ) / cell) + 1,
|
|
29
|
+
];
|
|
30
|
+
const cells = dims[0] * dims[1] * dims[2];
|
|
31
|
+
if (cells > LIGHT_GRID_MAX_CELLS) {
|
|
32
|
+
throw new Error(`createLightGrid: these lights span ${dims.join(' × ')} cells of ${cell} m, past ` +
|
|
33
|
+
`${LIGHT_GRID_MAX_CELLS}; a larger cell fits them.`);
|
|
34
|
+
}
|
|
35
|
+
const cellOf = (light) => Math.floor((light.x - minX) / cell) +
|
|
36
|
+
dims[0] * (Math.floor((light.y - minY) / cell) + dims[1] * Math.floor((light.z - minZ) / cell));
|
|
37
|
+
const start = new Uint32Array(cells + 1);
|
|
38
|
+
for (const light of sources) {
|
|
39
|
+
const c = cellOf(light);
|
|
40
|
+
start[c + 1] = start[c + 1] + 1;
|
|
41
|
+
}
|
|
42
|
+
for (let c = 0; c < cells; c++)
|
|
43
|
+
start[c + 1] = start[c + 1] + start[c];
|
|
44
|
+
const lights = new Uint32Array(sources.length);
|
|
45
|
+
const cursor = start.slice(0, cells);
|
|
46
|
+
for (let index = 0; index < sources.length; index++) {
|
|
47
|
+
const c = cellOf(sources[index]);
|
|
48
|
+
lights[cursor[c]] = index;
|
|
49
|
+
cursor[c] = cursor[c] + 1;
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
sources,
|
|
53
|
+
cell,
|
|
54
|
+
origin: [minX, minY, minZ],
|
|
55
|
+
dims,
|
|
56
|
+
start,
|
|
57
|
+
lights,
|
|
58
|
+
maxRadius,
|
|
59
|
+
gathered: new Int32Array(sources.length),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Gather into `grid.gathered`, cell by cell, every light whose cell lies within `reach` metres of
|
|
64
|
+
* (x, y, z) on each axis, and answer how many.
|
|
65
|
+
*/
|
|
66
|
+
export function gatherLights(grid, x, y, z, reach) {
|
|
67
|
+
const { cell, origin, dims, start, lights, gathered } = grid;
|
|
68
|
+
const x0 = Math.max(0, Math.floor((x - reach - origin[0]) / cell));
|
|
69
|
+
const x1 = Math.min(dims[0] - 1, Math.floor((x + reach - origin[0]) / cell));
|
|
70
|
+
const y0 = Math.max(0, Math.floor((y - reach - origin[1]) / cell));
|
|
71
|
+
const y1 = Math.min(dims[1] - 1, Math.floor((y + reach - origin[1]) / cell));
|
|
72
|
+
const z0 = Math.max(0, Math.floor((z - reach - origin[2]) / cell));
|
|
73
|
+
const z1 = Math.min(dims[2] - 1, Math.floor((z + reach - origin[2]) / cell));
|
|
74
|
+
let count = 0;
|
|
75
|
+
for (let cz = z0; cz <= z1; cz++) {
|
|
76
|
+
for (let cy = y0; cy <= y1; cy++) {
|
|
77
|
+
const row = dims[0] * (cy + dims[1] * cz);
|
|
78
|
+
for (let cx = x0; cx <= x1; cx++) {
|
|
79
|
+
const c = row + cx;
|
|
80
|
+
for (let at = start[c]; at < start[c + 1]; at++) {
|
|
81
|
+
gathered[count++] = lights[at];
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return count;
|
|
87
|
+
}
|
package/dist/render/mesh.d.ts
CHANGED
|
@@ -7,6 +7,9 @@ import type { MeshData } from '@driftengine/drft';
|
|
|
7
7
|
export declare class Mesh {
|
|
8
8
|
private readonly vao;
|
|
9
9
|
private readonly buffers;
|
|
10
|
+
/** Every attribute bound from a buffer, so a batch can build a vertex array of its own. */
|
|
11
|
+
private readonly layout;
|
|
12
|
+
private indexBuffer;
|
|
10
13
|
/**
|
|
11
14
|
* The position and normal buffers, kept so `update` can rewrite them.
|
|
12
15
|
*
|
|
@@ -16,7 +19,8 @@ export declare class Mesh {
|
|
|
16
19
|
private readonly deformable;
|
|
17
20
|
/** How many floats the position buffer holds, so an update of the wrong size is refused. */
|
|
18
21
|
private readonly positionFloats;
|
|
19
|
-
|
|
22
|
+
/** Indices one draw of it issues; the batch-size rule reads it (`cullsInstances`). */
|
|
23
|
+
readonly indexCount: number;
|
|
20
24
|
/**
|
|
21
25
|
* The constant values this mesh's *absent* attributes are shaded with, re-applied on
|
|
22
26
|
* every draw.
|
|
@@ -94,30 +98,18 @@ export declare class Mesh {
|
|
|
94
98
|
/** Caller is responsible for having the flat program + uniforms bound. */
|
|
95
99
|
draw(gl: WebGL2RenderingContext): void;
|
|
96
100
|
/**
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
* batch
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
* which wants a vertex array per batch rather than a flag here.
|
|
106
|
-
*/
|
|
107
|
-
attachInstances(gl: WebGL2RenderingContext, buffer: WebGLBuffer, stride: number): void;
|
|
108
|
-
/** The instance columns, bound. Called at attach and again after a plain draw disabled them. */
|
|
109
|
-
private bindInstanceColumns;
|
|
110
|
-
private instanceBuffer;
|
|
111
|
-
private instanceStride;
|
|
112
|
-
/** Whether `attachInstances` has already claimed locations 11 to 15 on this mesh's array. */
|
|
113
|
-
private instanced;
|
|
114
|
-
/**
|
|
115
|
-
* Draw `count` instances through the attributes `attachInstances` bound.
|
|
116
|
-
*
|
|
117
|
-
* The constants are re-applied exactly as `draw` does — a vertex array restores the arrays and
|
|
118
|
-
* not the constant attributes, and an absent optional attribute is a constant here.
|
|
101
|
+
* A vertex array for one instanced batch: every attribute this mesh binds from a buffer, its index
|
|
102
|
+
* buffer, and the batch's instance columns — the model matrix at 11 to 14, the tint at 15.
|
|
103
|
+
*
|
|
104
|
+
* **A batch owns its own array**, which is what lets a mesh have more than one batch: a prop drawn
|
|
105
|
+
* once per region is one mesh and a batch per region. With one array a mesh had one batch, since a
|
|
106
|
+
* second would rebind the columns the first draws through and place one batch's instances by the
|
|
107
|
+
* other's matrices. The arrays share every buffer, so a batch costs its instances and nothing of
|
|
108
|
+
* the geometry. The caller deletes what this returns.
|
|
119
109
|
*/
|
|
120
|
-
|
|
110
|
+
createInstanceArray(gl: WebGL2RenderingContext, instances: WebGLBuffer, stride: number): WebGLVertexArrayObject;
|
|
111
|
+
/** Draw `count` instances through a batch's own vertex array. See `createInstanceArray`. */
|
|
112
|
+
drawInstancesThrough(gl: WebGL2RenderingContext, vao: WebGLVertexArrayObject, count: number): void;
|
|
121
113
|
dispose(gl: WebGL2RenderingContext): void;
|
|
122
114
|
/**
|
|
123
115
|
* Rewrite this mesh's positions, and its normals where the caller has them.
|
|
@@ -179,3 +171,5 @@ export interface IncrementalMesh {
|
|
|
179
171
|
* them before a byte of it has landed.
|
|
180
172
|
*/
|
|
181
173
|
export declare function createMeshIncremental(gl: WebGL2RenderingContext, data: MeshData, dynamic?: boolean): IncrementalMesh;
|
|
174
|
+
/** Texture coordinates and layers interleaved as (u, v, layer), one row a vertex. */
|
|
175
|
+
export declare function packUvLayers(uvs: Float32Array, layers: Float32Array): Float32Array;
|
package/dist/render/mesh.js
CHANGED
|
@@ -49,14 +49,6 @@ const ATTR_JOINTS = 11;
|
|
|
49
49
|
* setting sway, watching nothing move, and having nothing to read about why.
|
|
50
50
|
*/
|
|
51
51
|
const ATTR_CHANNEL = 13;
|
|
52
|
-
/**
|
|
53
|
-
* The locations `attachInstances` claims, which a plain draw through the same array must not read.
|
|
54
|
-
*
|
|
55
|
-
* Eleven to fourteen are the model matrix's columns and fifteen is the tint. **Thirteen is also
|
|
56
|
-
* the channel**, and eleven and twelve are the skinning pair — which cannot collide, because
|
|
57
|
-
* `flatVert` refuses skinning with instancing. See `draw`.
|
|
58
|
-
*/
|
|
59
|
-
const INSTANCE_COLUMNS = [11, 12, 13, 14, 15];
|
|
60
52
|
const ATTR_WEIGHTS = 12;
|
|
61
53
|
/**
|
|
62
54
|
* One absent attribute's constant, at the width the table gave it.
|
|
@@ -84,6 +76,9 @@ function applyConstant(gl, location, value) {
|
|
|
84
76
|
export class Mesh {
|
|
85
77
|
vao;
|
|
86
78
|
buffers = [];
|
|
79
|
+
/** Every attribute bound from a buffer, so a batch can build a vertex array of its own. */
|
|
80
|
+
layout = [];
|
|
81
|
+
indexBuffer = null;
|
|
87
82
|
/**
|
|
88
83
|
* The position and normal buffers, kept so `update` can rewrite them.
|
|
89
84
|
*
|
|
@@ -93,6 +88,7 @@ export class Mesh {
|
|
|
93
88
|
deformable = null;
|
|
94
89
|
/** How many floats the position buffer holds, so an update of the wrong size is refused. */
|
|
95
90
|
positionFloats;
|
|
91
|
+
/** Indices one draw of it issues; the batch-size rule reads it (`cullsInstances`). */
|
|
96
92
|
indexCount;
|
|
97
93
|
/**
|
|
98
94
|
* The constant values this mesh's *absent* attributes are shaded with, re-applied on
|
|
@@ -211,7 +207,14 @@ export class Mesh {
|
|
|
211
207
|
gl.disableVertexAttribArray(ATTR_UV);
|
|
212
208
|
this.constants.push({ location: ATTR_UV, value: ABSENT_ATTRIBUTE['uvs'] });
|
|
213
209
|
}
|
|
210
|
+
else if (data.layers !== undefined) {
|
|
211
|
+
/* The texture-array layer rides as the third coordinate — every vertex location is spent —
|
|
212
|
+
so a layered mesh uploads (u, v, layer) packed. See `MeshData.layers`. */
|
|
213
|
+
this.attachAttribute(gl, ATTR_UV, packUvLayers(data.uvs, data.layers), 3);
|
|
214
|
+
}
|
|
214
215
|
else {
|
|
216
|
+
/* Two components; the shader's vec3 reads z as 0 by the GL rule for a missing component,
|
|
217
|
+
which is layer 0 — the only layer a plain texture has. */
|
|
215
218
|
this.attachAttribute(gl, ATTR_UV, data.uvs, 2);
|
|
216
219
|
}
|
|
217
220
|
/* Absent means "inherit albedo", supplied as the constant the shader tests for. */
|
|
@@ -297,6 +300,7 @@ export class Mesh {
|
|
|
297
300
|
throw new Error('createBuffer failed');
|
|
298
301
|
this.buffers.push(indexBuffer);
|
|
299
302
|
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
|
|
303
|
+
this.indexBuffer = indexBuffer;
|
|
300
304
|
this.allocate(gl, gl.ELEMENT_ARRAY_BUFFER, indexBuffer, data.indices, gl.STATIC_DRAW);
|
|
301
305
|
gl.bindVertexArray(null);
|
|
302
306
|
}
|
|
@@ -304,29 +308,11 @@ export class Mesh {
|
|
|
304
308
|
draw(gl) {
|
|
305
309
|
gl.bindVertexArray(this.vao);
|
|
306
310
|
/*
|
|
307
|
-
*
|
|
308
|
-
*
|
|
309
|
-
*
|
|
310
|
-
*
|
|
311
|
-
* of the absent-attribute constant. For a placement with no rotation that column is
|
|
312
|
-
* `(0, 0, 1, 0)`, so `aChannel.y` is zero, `vSkyDirect = aChannel.y` scales the directional
|
|
313
|
-
* term to nothing, and the mesh renders lit by the hemispheric ambient alone — correct
|
|
314
|
-
* normals, correct albedo, no error, no warning.
|
|
315
|
-
*
|
|
316
|
-
* Found on `demo/instancing.ts`, which exists to draw two ranks of one box the two ways and
|
|
317
|
-
* compare them: the `drawMesh` rank's top face read (51, 30, 21) against the `drawInstanced`
|
|
318
|
-
* rank's (218, 110, 59), and 51 is exactly the ambient. WebGPU has no array to share and drew
|
|
319
|
-
* them alike, which is what made it visible at all.
|
|
320
|
-
*
|
|
321
|
-
* Disabled here and put back by `drawInstances`, rather than given the batch an array of its
|
|
322
|
-
* own: that is the larger change this class's own note about two batches already contemplates,
|
|
323
|
-
* and it wants one for a different reason. Three calls on a mesh that has a batch and none on
|
|
324
|
-
* a mesh that does not.
|
|
311
|
+
* No instance columns to disable: a batch draws through a vertex array of its own
|
|
312
|
+
* (`createInstanceArray`), so this array never carries them. It used to, and location 13 — the
|
|
313
|
+
* channel — then read the third column of instance zero's matrix on a plain draw, which lit a
|
|
314
|
+
* mesh by ambient alone on this backend and not the other.
|
|
325
315
|
*/
|
|
326
|
-
if (this.instanced) {
|
|
327
|
-
for (const location of INSTANCE_COLUMNS)
|
|
328
|
-
gl.disableVertexAttribArray(location);
|
|
329
|
-
}
|
|
330
316
|
// The VAO restores the arrays; these it cannot. See `constants`.
|
|
331
317
|
for (const constant of this.constants) {
|
|
332
318
|
const value = constant.value;
|
|
@@ -335,32 +321,27 @@ export class Mesh {
|
|
|
335
321
|
gl.drawElements(gl.TRIANGLES, this.indexCount, gl.UNSIGNED_INT, 0);
|
|
336
322
|
}
|
|
337
323
|
/**
|
|
338
|
-
*
|
|
339
|
-
*
|
|
340
|
-
* **One batch per mesh, and the vertex array is why.** A `Mesh` owns exactly one, so a second
|
|
341
|
-
* batch would rebind locations 11 to 15 on the array the first still draws through — and what
|
|
342
|
-
* comes out is one batch's instances placed by the other's matrices, which reads as a transform
|
|
343
|
-
* bug in the consumer's own code rather than as a misuse of this.
|
|
324
|
+
* A vertex array for one instanced batch: every attribute this mesh binds from a buffer, its index
|
|
325
|
+
* buffer, and the batch's instance columns — the model matrix at 11 to 14, the tint at 15.
|
|
344
326
|
*
|
|
345
|
-
* **
|
|
346
|
-
*
|
|
327
|
+
* **A batch owns its own array**, which is what lets a mesh have more than one batch: a prop drawn
|
|
328
|
+
* once per region is one mesh and a batch per region. With one array a mesh had one batch, since a
|
|
329
|
+
* second would rebind the columns the first draws through and place one batch's instances by the
|
|
330
|
+
* other's matrices. The arrays share every buffer, so a batch costs its instances and nothing of
|
|
331
|
+
* the geometry. The caller deletes what this returns.
|
|
347
332
|
*/
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
333
|
+
createInstanceArray(gl, instances, stride) {
|
|
334
|
+
const vao = gl.createVertexArray();
|
|
335
|
+
if (vao === null)
|
|
336
|
+
throw new Error('createVertexArray failed');
|
|
337
|
+
gl.bindVertexArray(vao);
|
|
338
|
+
for (const attribute of this.layout) {
|
|
339
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, attribute.buffer);
|
|
340
|
+
gl.enableVertexAttribArray(attribute.location);
|
|
341
|
+
gl.vertexAttribPointer(attribute.location, attribute.size, gl.FLOAT, false, 0, 0);
|
|
352
342
|
}
|
|
353
|
-
this.
|
|
354
|
-
|
|
355
|
-
this.instanceStride = stride;
|
|
356
|
-
gl.bindVertexArray(this.vao);
|
|
357
|
-
this.bindInstanceColumns(gl, buffer);
|
|
358
|
-
gl.bindVertexArray(null);
|
|
359
|
-
}
|
|
360
|
-
/** The instance columns, bound. Called at attach and again after a plain draw disabled them. */
|
|
361
|
-
bindInstanceColumns(gl, buffer) {
|
|
362
|
-
const stride = this.instanceStride;
|
|
363
|
-
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
343
|
+
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
|
|
344
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, instances);
|
|
364
345
|
/* Four vec4 columns then a vec3 tint: a mat4 is not a vertex attribute in GLSL ES 300. */
|
|
365
346
|
for (let column = 0; column < 4; column += 1) {
|
|
366
347
|
const location = 11 + column;
|
|
@@ -371,22 +352,12 @@ export class Mesh {
|
|
|
371
352
|
gl.enableVertexAttribArray(15);
|
|
372
353
|
gl.vertexAttribPointer(15, 3, gl.FLOAT, false, stride, 64);
|
|
373
354
|
gl.vertexAttribDivisor(15, 1);
|
|
355
|
+
gl.bindVertexArray(null);
|
|
356
|
+
return vao;
|
|
374
357
|
}
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
instanced = false;
|
|
379
|
-
/**
|
|
380
|
-
* Draw `count` instances through the attributes `attachInstances` bound.
|
|
381
|
-
*
|
|
382
|
-
* The constants are re-applied exactly as `draw` does — a vertex array restores the arrays and
|
|
383
|
-
* not the constant attributes, and an absent optional attribute is a constant here.
|
|
384
|
-
*/
|
|
385
|
-
drawInstances(gl, count) {
|
|
386
|
-
gl.bindVertexArray(this.vao);
|
|
387
|
-
/* Put back what `draw` disabled, if a plain draw of this mesh came first. See its note. */
|
|
388
|
-
if (this.instanceBuffer !== null)
|
|
389
|
-
this.bindInstanceColumns(gl, this.instanceBuffer);
|
|
358
|
+
/** Draw `count` instances through a batch's own vertex array. See `createInstanceArray`. */
|
|
359
|
+
drawInstancesThrough(gl, vao, count) {
|
|
360
|
+
gl.bindVertexArray(vao);
|
|
390
361
|
for (const constant of this.constants) {
|
|
391
362
|
const value = constant.value;
|
|
392
363
|
applyConstant(gl, constant.location, value);
|
|
@@ -438,6 +409,7 @@ export class Mesh {
|
|
|
438
409
|
this.allocate(gl, gl.ARRAY_BUFFER, buffer, data, usage);
|
|
439
410
|
gl.enableVertexAttribArray(location);
|
|
440
411
|
gl.vertexAttribPointer(location, size, gl.FLOAT, false, 0, 0);
|
|
412
|
+
this.layout.push({ location, buffer, size });
|
|
441
413
|
return buffer;
|
|
442
414
|
}
|
|
443
415
|
/**
|
|
@@ -508,3 +480,14 @@ export function createMeshIncremental(gl, data, dynamic = false) {
|
|
|
508
480
|
const mesh = new Mesh(gl, data, dynamic, true);
|
|
509
481
|
return { mesh, upload: mesh.uploads(gl) };
|
|
510
482
|
}
|
|
483
|
+
/** Texture coordinates and layers interleaved as (u, v, layer), one row a vertex. */
|
|
484
|
+
export function packUvLayers(uvs, layers) {
|
|
485
|
+
const count = layers.length;
|
|
486
|
+
const packed = new Float32Array(count * 3);
|
|
487
|
+
for (let v = 0; v < count; v++) {
|
|
488
|
+
packed[v * 3] = uvs[v * 2];
|
|
489
|
+
packed[v * 3 + 1] = uvs[v * 2 + 1];
|
|
490
|
+
packed[v * 3 + 2] = layers[v];
|
|
491
|
+
}
|
|
492
|
+
return packed;
|
|
493
|
+
}
|
|
@@ -51,6 +51,16 @@ export declare class OcclusionBuffer {
|
|
|
51
51
|
* something hidden costs a draw call; culling something visible is a hole.
|
|
52
52
|
*/
|
|
53
53
|
occluded(bounds: Bounds, model: ReadonlyMat4): boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Whether a world-space box is entirely behind the declared occluders — the tighter question for
|
|
56
|
+
* something that is a box, where the cube around its sphere reaches far past it. **A flat region
|
|
57
|
+
* is the case it exists for**: a city block's sphere is half as deep underground as it is wide,
|
|
58
|
+
* nothing there occludes it, and the sphere test abstains for every block in the city. False
|
|
59
|
+
* whenever anything is uncertain, exactly as `occluded`.
|
|
60
|
+
*/
|
|
61
|
+
occludedBox(min: ArrayLike<number>, max: ArrayLike<number>): boolean;
|
|
62
|
+
/** The shared test: a world box's corners projected, its rectangle tested against the pyramid. */
|
|
63
|
+
private boxBehind;
|
|
54
64
|
/**
|
|
55
65
|
* A world point into buffer coordinates and depth, written into `CORNERS` at `slot`.
|
|
56
66
|
*
|
package/dist/render/occlusion.js
CHANGED
|
@@ -33,6 +33,8 @@
|
|
|
33
33
|
*/
|
|
34
34
|
/** What an unwritten texel holds: the far plane, which occludes nothing. */
|
|
35
35
|
const FAR = 1;
|
|
36
|
+
/** Texels a tested rectangle may span at the level it is read from. See `boxBehind`. */
|
|
37
|
+
const TEXELS_ACROSS = 8;
|
|
36
38
|
export class OcclusionBuffer {
|
|
37
39
|
/**
|
|
38
40
|
* The pyramid, level 0 first, each level a quarter of the one before.
|
|
@@ -169,15 +171,33 @@ export class OcclusionBuffer {
|
|
|
169
171
|
const sz = Math.sqrt(m8 * m8 + m9 * m9 + m10 * m10);
|
|
170
172
|
const radius = bounds.radius * Math.max(sx, sy, sz);
|
|
171
173
|
/* The cube that contains the sphere, which contains the object. Conservative twice over. */
|
|
174
|
+
return this.boxBehind(x - radius, y - radius, z - radius, x + radius, y + radius, z + radius);
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Whether a world-space box is entirely behind the declared occluders — the tighter question for
|
|
178
|
+
* something that is a box, where the cube around its sphere reaches far past it. **A flat region
|
|
179
|
+
* is the case it exists for**: a city block's sphere is half as deep underground as it is wide,
|
|
180
|
+
* nothing there occludes it, and the sphere test abstains for every block in the city. False
|
|
181
|
+
* whenever anything is uncertain, exactly as `occluded`.
|
|
182
|
+
*/
|
|
183
|
+
occludedBox(min, max) {
|
|
184
|
+
if (this.occluders === 0)
|
|
185
|
+
return false;
|
|
186
|
+
if (!this.built)
|
|
187
|
+
this.buildPyramid();
|
|
188
|
+
return this.boxBehind(min[0] ?? 0, min[1] ?? 0, min[2] ?? 0, max[0] ?? 0, max[1] ?? 0, max[2] ?? 0);
|
|
189
|
+
}
|
|
190
|
+
/** The shared test: a world box's corners projected, its rectangle tested against the pyramid. */
|
|
191
|
+
boxBehind(loX, loY, loZ, hiX, hiY, hiZ) {
|
|
172
192
|
let minX = Infinity;
|
|
173
193
|
let minY = Infinity;
|
|
174
194
|
let minZ = Infinity;
|
|
175
195
|
let maxX = -Infinity;
|
|
176
196
|
let maxY = -Infinity;
|
|
177
197
|
for (let corner = 0; corner < 8; corner++) {
|
|
178
|
-
const px = corner & 1 ?
|
|
179
|
-
const py = corner & 2 ?
|
|
180
|
-
const pz = corner & 4 ?
|
|
198
|
+
const px = corner & 1 ? hiX : loX;
|
|
199
|
+
const py = corner & 2 ? hiY : loY;
|
|
200
|
+
const pz = corner & 4 ? hiZ : loZ;
|
|
181
201
|
if (!this.project(px, py, pz, 0))
|
|
182
202
|
return false;
|
|
183
203
|
minX = Math.min(minX, CORNERS[0] ?? 0);
|
|
@@ -192,13 +212,22 @@ export class OcclusionBuffer {
|
|
|
192
212
|
if (minX < 0 || minY < 0 || maxX > width || maxY > height)
|
|
193
213
|
return false;
|
|
194
214
|
/*
|
|
195
|
-
* The coarsest level
|
|
196
|
-
* most
|
|
197
|
-
* repository's determinism gate refuses elsewhere; a shift loop says it in integers.
|
|
215
|
+
* The coarsest level at which the rectangle spans at most `TEXELS_ACROSS` texels, so the test
|
|
216
|
+
* reads at most that many plus one each way. `Math.log2` would say the same thing and is one of
|
|
217
|
+
* the calls this repository's determinism gate refuses elsewhere; a shift loop says it in integers.
|
|
218
|
+
*
|
|
219
|
+
* **Eight, not one, since 2026-09-30.** At one the level's texel was as wide as the rectangle, and
|
|
220
|
+
* two such texels aligned to the grid span up to twice it — so anything whose rectangle came near
|
|
221
|
+
* an occluder's edge, or the buffer's own unwritten border row, read unwritten texels and
|
|
222
|
+
* abstained. That was every city region behind a row of buildings, whose rectangle sits just
|
|
223
|
+
* under the skyline; measured on a box seven metres wide behind a wall filling the view, which
|
|
224
|
+
* one abstained at and eight culls. Reading up to 81 texels instead of 4 costs a few dozen
|
|
225
|
+
* compares and keeps the answer exactly as conservative: the maximum over every texel the
|
|
226
|
+
* rectangle touches.
|
|
198
227
|
*/
|
|
199
228
|
let level = 0;
|
|
200
229
|
let span = Math.max(maxX - minX, maxY - minY);
|
|
201
|
-
while (span >
|
|
230
|
+
while (span > TEXELS_ACROSS && level + 1 < this.levels.length) {
|
|
202
231
|
span *= 0.5;
|
|
203
232
|
level++;
|
|
204
233
|
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a lamp's light keeps through glass: an RGBA8 array of one layer a light, parallel to the
|
|
3
|
+
* point shadow array and indexed by the light, not by the interleaved depth layer. RGB is the
|
|
4
|
+
* product of every pane's `transmission × (1 − F) × tint`, A the product of their clarities
|
|
5
|
+
* (`glassShadow.ts`).
|
|
6
|
+
*
|
|
7
|
+
* **Drawn a face at a time, as the depth is**: into a face-sized colour scratch cleared to white,
|
|
8
|
+
* with a multiplying blend and no depth test, then resolved into the face's region of the layer by
|
|
9
|
+
* `OCTAHEDRAL_RESOLVE_TINT_FRAG`. One scratch for the whole engine, for the reason
|
|
10
|
+
* `PointShadowArray` gives for its own.
|
|
11
|
+
*
|
|
12
|
+
* **Which faces hold glass is remembered, six bits a layer**, so a face with no glass and none to
|
|
13
|
+
* forget costs nothing, and a face that inherited a previous owner's glass is cleared. **The chain
|
|
14
|
+
* frost reads is rebuilt once a round**, for the layers the round touched, through a 2D staging
|
|
15
|
+
* chain: `generateMipmap` on an array rebuilds every layer, which is the whole pool's texels for one
|
|
16
|
+
* lamp's glass. What that costs is one layer of memory with its chain — 5.6 MB at 1024, 1.4 MB at
|
|
17
|
+
* `'half'` — and a copy out and back per touched layer.
|
|
18
|
+
*/
|
|
19
|
+
export declare class PointGlassTint {
|
|
20
|
+
readonly texture: WebGLTexture;
|
|
21
|
+
readonly edge: number;
|
|
22
|
+
private readonly layers;
|
|
23
|
+
private readonly levels;
|
|
24
|
+
private readonly faceSize;
|
|
25
|
+
private readonly scratch;
|
|
26
|
+
private readonly scratchFramebuffer;
|
|
27
|
+
private readonly staging;
|
|
28
|
+
private readonly framebuffer;
|
|
29
|
+
private readonly readFramebuffer;
|
|
30
|
+
/** Parked on the resolve's unit while the scratch is a render target; see `beginFace`. */
|
|
31
|
+
private readonly parked;
|
|
32
|
+
private readonly program;
|
|
33
|
+
private readonly uniforms;
|
|
34
|
+
private readonly vao;
|
|
35
|
+
/** Six bits a layer: which faces' regions hold glass. */
|
|
36
|
+
private readonly heldFaces;
|
|
37
|
+
/** Layers whose level 0 changed since the chain was last rebuilt. */
|
|
38
|
+
private readonly dirty;
|
|
39
|
+
constructor(gl: WebGL2RenderingContext, faceSize: number, edge: number, layers: number);
|
|
40
|
+
/** Whether `face` of `layer` holds glass: a face that does must be cleared before it is reused. */
|
|
41
|
+
held(layer: number, face: number): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Bind the colour scratch, clear it to white, and set the multiplying state.
|
|
44
|
+
*
|
|
45
|
+
* The previous resolve left the scratch bound for sampling on unit 0, and it is about to be the
|
|
46
|
+
* target: parked first, for the reason `PointShadowArray.beginFace` gives.
|
|
47
|
+
*/
|
|
48
|
+
beginFace(gl: WebGL2RenderingContext): void;
|
|
49
|
+
/**
|
|
50
|
+
* Copy the scratch into `face`'s region of `layer`, and remember whether it held glass.
|
|
51
|
+
*
|
|
52
|
+
* Leaves depth testing and writing on, which is what the next face's casters expect: the depth
|
|
53
|
+
* resolve that runs before them turns both on, and this one ran after it and turned them off.
|
|
54
|
+
*/
|
|
55
|
+
resolveFace(gl: WebGL2RenderingContext, layer: number, face: number, drawn: boolean): void;
|
|
56
|
+
/** Rebuild the chain of every layer touched since the last call, one layer at a time. */
|
|
57
|
+
fillMips(gl: WebGL2RenderingContext): void;
|
|
58
|
+
dispose(gl: WebGL2RenderingContext): void;
|
|
59
|
+
}
|