@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
|
@@ -334,7 +334,8 @@ export function createScatterDepthBindGroupLayout(
|
|
|
334
334
|
{
|
|
335
335
|
binding: previous.texture,
|
|
336
336
|
visibility: VISIBILITY_FRAGMENT,
|
|
337
|
-
|
|
337
|
+
/* The depth program's peel read, an array since the sun's maps became one. */
|
|
338
|
+
texture: { sampleType: 'unfilterable-float', viewDimension: '2d-array' },
|
|
338
339
|
},
|
|
339
340
|
{
|
|
340
341
|
binding: previous.sampler,
|
|
@@ -142,7 +142,12 @@ export function createSdfTextBindGroupLayout(device: GPUDevice): GPUBindGroupLay
|
|
|
142
142
|
visibility: VISIBILITY_FRAGMENT,
|
|
143
143
|
buffer: { type: 'uniform', hasDynamicOffset: true, minBindingSize: SDF_TEXT_FRAG_SIZE },
|
|
144
144
|
},
|
|
145
|
-
|
|
145
|
+
/* The atlas is a surface texture, and every surface texture is a `2d-array` view. */
|
|
146
|
+
{
|
|
147
|
+
binding: ATLAS.texture,
|
|
148
|
+
visibility: VISIBILITY_FRAGMENT,
|
|
149
|
+
texture: { viewDimension: '2d-array' },
|
|
150
|
+
},
|
|
146
151
|
{ binding: ATLAS.sampler, visibility: VISIBILITY_FRAGMENT, sampler: {} },
|
|
147
152
|
],
|
|
148
153
|
});
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { INSTANCE_FLOATS } from '../../../instances.ts';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The instance cull, in WGSL, hand-authored under the compute exception `AGENTS.md` records
|
|
5
|
+
* (2026-08-24): a compute shader has no WebGL2 twin to generate from, and `npm run wgsl` neither
|
|
6
|
+
* writes nor polices this file.
|
|
7
|
+
*
|
|
8
|
+
* **It keeps exactly what `cullInstances` keeps**, and `gpu-parity.mjs` runs both on a device: an
|
|
9
|
+
* instance's world sphere is the mesh's sphere with its centre through the model matrix and its
|
|
10
|
+
* radius scaled by the largest column, and it is kept unless wholly beyond one of the six planes.
|
|
11
|
+
* The one difference is order — survivors are compacted by `atomicAdd`, so they arrive in whatever
|
|
12
|
+
* order the invocations reached it. That is invisible to an opaque draw and is why a blended draw
|
|
13
|
+
* is never culled here.
|
|
14
|
+
*
|
|
15
|
+
* `args` is a `drawIndexedIndirect` record, `(indexCount, instanceCount, firstIndex, baseVertex,
|
|
16
|
+
* firstInstance)`; the renderer writes it with a zero instance count before each dispatch and this
|
|
17
|
+
* counts the survivors into it.
|
|
18
|
+
*/
|
|
19
|
+
export const INSTANCE_CULL_WORKGROUP = 64;
|
|
20
|
+
|
|
21
|
+
export const INSTANCE_CULL_WGSL = /* wgsl */ `
|
|
22
|
+
struct Params {
|
|
23
|
+
planes: array<vec4<f32>, 6>,
|
|
24
|
+
sphere: vec4<f32>,
|
|
25
|
+
count: u32,
|
|
26
|
+
pad0: u32,
|
|
27
|
+
pad1: u32,
|
|
28
|
+
pad2: u32,
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@group(0) @binding(0) var<uniform> params: Params;
|
|
32
|
+
@group(0) @binding(1) var<storage, read> source: array<f32>;
|
|
33
|
+
@group(0) @binding(2) var<storage, read_write> kept: array<f32>;
|
|
34
|
+
@group(0) @binding(3) var<storage, read_write> args: array<atomic<u32>, 5>;
|
|
35
|
+
|
|
36
|
+
const STRIDE: u32 = ${INSTANCE_FLOATS}u;
|
|
37
|
+
|
|
38
|
+
@compute @workgroup_size(${INSTANCE_CULL_WORKGROUP})
|
|
39
|
+
fn main(@builtin(global_invocation_id) id: vec3<u32>) {
|
|
40
|
+
let i = id.x;
|
|
41
|
+
if (i >= params.count) { return; }
|
|
42
|
+
let at = i * STRIDE;
|
|
43
|
+
let c0 = vec3<f32>(source[at], source[at + 1u], source[at + 2u]);
|
|
44
|
+
let c1 = vec3<f32>(source[at + 4u], source[at + 5u], source[at + 6u]);
|
|
45
|
+
let c2 = vec3<f32>(source[at + 8u], source[at + 9u], source[at + 10u]);
|
|
46
|
+
let t = vec3<f32>(source[at + 12u], source[at + 13u], source[at + 14u]);
|
|
47
|
+
let local = params.sphere;
|
|
48
|
+
let centre = c0 * local.x + c1 * local.y + c2 * local.z + t;
|
|
49
|
+
let scale = sqrt(max(dot(c0, c0), max(dot(c1, c1), dot(c2, c2))));
|
|
50
|
+
let radius = local.w * scale;
|
|
51
|
+
for (var p = 0u; p < 6u; p = p + 1u) {
|
|
52
|
+
let plane = params.planes[p];
|
|
53
|
+
if (dot(plane.xyz, centre) + plane.w < -radius) { return; }
|
|
54
|
+
}
|
|
55
|
+
let slot = atomicAdd(&args[1], 1u);
|
|
56
|
+
let to = slot * STRIDE;
|
|
57
|
+
for (var k = 0u; k < STRIDE; k = k + 1u) {
|
|
58
|
+
kept[to + k] = source[at + k];
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
`;
|
|
@@ -15,6 +15,10 @@ import { SkinPaletteTexture } from './skinPaletteTexture.ts';
|
|
|
15
15
|
* **What would make it wrong** is a genuine crowd — a stadium, a swarm of rigged birds — and the
|
|
16
16
|
* fix is then the one `skinPalette.ts` names: one texture holding every palette with a per-draw
|
|
17
17
|
* row offset, which spends a uniform and a shader change to stop spending textures.
|
|
18
|
+
*
|
|
19
|
+
* **A reconstructing frame spends one more per skinned mover**: last frame's pose is uploaded into
|
|
20
|
+
* a slot of its own for the motion pass. So the same budget is about twelve such characters with a
|
|
21
|
+
* reflection and three shadow layers each.
|
|
18
22
|
*/
|
|
19
23
|
export const MAX_SKIN_PALETTES = 128;
|
|
20
24
|
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The mip chain of the frame's refraction copy, recorded into the frame's own encoder.
|
|
3
|
+
*
|
|
4
|
+
* **Frosted glass reads a blurrier level of what is behind it** (`glass.ts`), so on a frame that draws
|
|
5
|
+
* glass the copy needs every level filled from the one above. `generateMipChain` does that for an
|
|
6
|
+
* upload, on an encoder of its own that it submits at once — which here would run before the frame's
|
|
7
|
+
* encoder had even made the copy, and would build views and bind groups on every call. So this
|
|
8
|
+
* makes them once per copy texture and records one pass per level wherever the copy was taken.
|
|
9
|
+
*
|
|
10
|
+
* What it costs is a render pass per level on every frame that takes the copy — about a dozen for a
|
|
11
|
+
* 1080p copy, each a quarter of the one before, together about a third of the copy itself — and
|
|
12
|
+
* nothing on a frame that shows nothing through anything. **A frame that refracts and draws no glass
|
|
13
|
+
* pays it too**, and that is the trade: the copy is taken at the first draw that asks and shared by
|
|
14
|
+
* every later one, so a glass pane drawn after a refracting one would otherwise read levels nothing
|
|
15
|
+
* filled. WebGL2 fills its chain on the first glass draw instead, because a `generateMipmap` there
|
|
16
|
+
* ends no pass. What would change it is knowing at the copy whether glass follows in the frame.
|
|
17
|
+
*/
|
|
18
|
+
import type { MipPipelines } from './surfaceTexturePass.ts';
|
|
19
|
+
import { mipBlitPipeline } from './surfaceTexturePass.ts';
|
|
20
|
+
|
|
21
|
+
export class SnapshotMips {
|
|
22
|
+
private readonly pipeline: GPURenderPipeline;
|
|
23
|
+
private readonly targets: GPUTextureView[] = [];
|
|
24
|
+
private readonly groups: GPUBindGroup[] = [];
|
|
25
|
+
|
|
26
|
+
constructor(
|
|
27
|
+
device: GPUDevice,
|
|
28
|
+
pipelines: MipPipelines,
|
|
29
|
+
texture: GPUTexture,
|
|
30
|
+
format: GPUTextureFormat,
|
|
31
|
+
/** One layer of an array texture, where the chain is a layer's rather than the texture's. */
|
|
32
|
+
layer: number | null = null,
|
|
33
|
+
private readonly label = 'refract.mips',
|
|
34
|
+
) {
|
|
35
|
+
this.pipeline = mipBlitPipeline(device, pipelines, format);
|
|
36
|
+
const sampler = device.createSampler({
|
|
37
|
+
label: 'refract.mips.sampler',
|
|
38
|
+
magFilter: 'linear',
|
|
39
|
+
minFilter: 'linear',
|
|
40
|
+
});
|
|
41
|
+
const layout = this.pipeline.getBindGroupLayout(0);
|
|
42
|
+
const at =
|
|
43
|
+
layer === null ? {} : { dimension: '2d' as const, baseArrayLayer: layer, arrayLayerCount: 1 };
|
|
44
|
+
for (let level = 1; level < texture.mipLevelCount; level++) {
|
|
45
|
+
const source = texture.createView({ ...at, baseMipLevel: level - 1, mipLevelCount: 1 });
|
|
46
|
+
this.targets.push(texture.createView({ ...at, baseMipLevel: level, mipLevelCount: 1 }));
|
|
47
|
+
this.groups.push(
|
|
48
|
+
device.createBindGroup({
|
|
49
|
+
label: `refract.mips.${String(level)}`,
|
|
50
|
+
layout,
|
|
51
|
+
entries: [
|
|
52
|
+
{ binding: 0, resource: source },
|
|
53
|
+
{ binding: 1, resource: sampler },
|
|
54
|
+
],
|
|
55
|
+
}),
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Fill every level from level 0, in `encoder`, after whatever wrote level 0 there. */
|
|
61
|
+
record(encoder: GPUCommandEncoder): void {
|
|
62
|
+
for (let i = 0; i < this.targets.length; i++) {
|
|
63
|
+
const pass = encoder.beginRenderPass({
|
|
64
|
+
label: this.label,
|
|
65
|
+
colorAttachments: [
|
|
66
|
+
{
|
|
67
|
+
view: this.targets[i] as GPUTextureView,
|
|
68
|
+
loadOp: 'clear',
|
|
69
|
+
storeOp: 'store',
|
|
70
|
+
clearValue: [0, 0, 0, 0],
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
});
|
|
74
|
+
pass.setPipeline(this.pipeline);
|
|
75
|
+
pass.setBindGroup(0, this.groups[i] as GPUBindGroup);
|
|
76
|
+
pass.draw(3);
|
|
77
|
+
pass.end();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import type { SurfaceTextureOptions } from '../../surfaceTexture.ts';
|
|
2
|
+
import { SURFACE_EFFECT_TEXELS, packSurfaceEffects } from '../../surfaceEffects.ts';
|
|
3
|
+
import { toHalfFloats } from '../../halfFloat.ts';
|
|
4
|
+
import { isSourceList, layerSize, refuseArrayUpdate, sourceSize } from '../../textureSource.ts';
|
|
2
5
|
import type { PipelineCache } from './pipelineCache.ts';
|
|
3
6
|
import { shaderModule } from './shaderModules.ts';
|
|
4
7
|
|
|
@@ -89,6 +92,8 @@ export function generateMipChain(
|
|
|
89
92
|
texture: GPUTexture,
|
|
90
93
|
format: GPUTextureFormat,
|
|
91
94
|
levels: number,
|
|
95
|
+
/** How many array layers to fill, each its own chain. One for a plain texture. */
|
|
96
|
+
layers = 1,
|
|
92
97
|
): void {
|
|
93
98
|
if (levels < 2) return;
|
|
94
99
|
const pipeline = mipBlitPipeline(device, pipelines, format);
|
|
@@ -98,29 +103,33 @@ export function generateMipChain(
|
|
|
98
103
|
minFilter: 'linear',
|
|
99
104
|
});
|
|
100
105
|
const encoder = device.createCommandEncoder({ label: 'mip.chain' });
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
0,
|
|
113
|
-
device.createBindGroup({
|
|
114
|
-
layout: pipeline.getBindGroupLayout(0),
|
|
115
|
-
entries: [
|
|
116
|
-
{ binding: 0, resource: source },
|
|
117
|
-
{ binding: 1, resource: sampler },
|
|
106
|
+
/* One level of one layer at a time: a render target is a single 2D subresource, and the source
|
|
107
|
+
view is one level of the same layer, so no pass reads what it writes. */
|
|
108
|
+
for (let layer = 0; layer < layers; layer++)
|
|
109
|
+
for (let level = 1; level < levels; level++) {
|
|
110
|
+
const one = { dimension: '2d' as const, baseArrayLayer: layer, arrayLayerCount: 1 };
|
|
111
|
+
const source = texture.createView({ ...one, baseMipLevel: level - 1, mipLevelCount: 1 });
|
|
112
|
+
const target = texture.createView({ ...one, baseMipLevel: level, mipLevelCount: 1 });
|
|
113
|
+
const pass = encoder.beginRenderPass({
|
|
114
|
+
label: `mip.level${level}`,
|
|
115
|
+
colorAttachments: [
|
|
116
|
+
{ view: target, loadOp: 'clear', storeOp: 'store', clearValue: [0, 0, 0, 0] },
|
|
118
117
|
],
|
|
119
|
-
})
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
118
|
+
});
|
|
119
|
+
pass.setPipeline(pipeline);
|
|
120
|
+
pass.setBindGroup(
|
|
121
|
+
0,
|
|
122
|
+
device.createBindGroup({
|
|
123
|
+
layout: pipeline.getBindGroupLayout(0),
|
|
124
|
+
entries: [
|
|
125
|
+
{ binding: 0, resource: source },
|
|
126
|
+
{ binding: 1, resource: sampler },
|
|
127
|
+
],
|
|
128
|
+
}),
|
|
129
|
+
);
|
|
130
|
+
pass.draw(3);
|
|
131
|
+
pass.end();
|
|
132
|
+
}
|
|
124
133
|
device.queue.submit([encoder.finish()]);
|
|
125
134
|
}
|
|
126
135
|
|
|
@@ -128,7 +137,7 @@ export function generateMipChain(
|
|
|
128
137
|
* Cached per format, because the two differ: an `-srgb` target encodes on write, and blitting a
|
|
129
138
|
* linear chain through a pipeline declared for the other one is a gamma error per level.
|
|
130
139
|
*/
|
|
131
|
-
function mipBlitPipeline(
|
|
140
|
+
export function mipBlitPipeline(
|
|
132
141
|
device: GPUDevice,
|
|
133
142
|
pipelines: MipPipelines,
|
|
134
143
|
format: GPUTextureFormat,
|
|
@@ -149,19 +158,11 @@ function mipBlitPipeline(
|
|
|
149
158
|
}));
|
|
150
159
|
}
|
|
151
160
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
videoHeight?: number;
|
|
158
|
-
};
|
|
159
|
-
const width = candidate.videoWidth ?? candidate.width ?? 0;
|
|
160
|
-
const height = candidate.videoHeight ?? candidate.height ?? 0;
|
|
161
|
-
return { width: Math.max(1, width), height: Math.max(1, height) };
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
/** An image uploaded once and bound per material. */
|
|
161
|
+
/**
|
|
162
|
+
* An image uploaded once and bound per material — or several of one size, as an array's layers.
|
|
163
|
+
* Every surface texture is a `2d-array` view, a plain image an array of one; `surfaceTexture.ts`
|
|
164
|
+
* says why.
|
|
165
|
+
*/
|
|
165
166
|
export class GpuSurfaceTexture {
|
|
166
167
|
readonly sampler: GPUSampler;
|
|
167
168
|
|
|
@@ -172,14 +173,22 @@ export class GpuSurfaceTexture {
|
|
|
172
173
|
private levels: number;
|
|
173
174
|
private width: number;
|
|
174
175
|
private height: number;
|
|
176
|
+
/** How many images the array holds. */
|
|
177
|
+
readonly layers: number;
|
|
178
|
+
/** The per-layer effects table, or null for a texture given none. See `surfaceEffects.ts`. */
|
|
179
|
+
private effectsTable: GPUTexture | null = null;
|
|
180
|
+
/** Its view, which the flat group binds beside this image when it is a material's albedo. */
|
|
181
|
+
effectsView: GPUTextureView | null = null;
|
|
175
182
|
|
|
176
183
|
constructor(
|
|
177
184
|
private readonly device: GPUDevice,
|
|
178
185
|
private readonly pipelines: PipelineCache,
|
|
179
|
-
source: TexImageSource,
|
|
186
|
+
source: TexImageSource | readonly TexImageSource[],
|
|
180
187
|
options: SurfaceTextureOptions = {},
|
|
181
188
|
) {
|
|
182
|
-
const
|
|
189
|
+
const sources: readonly TexImageSource[] = isSourceList(source) ? source : [source];
|
|
190
|
+
const { width, height } = layerSize(sources);
|
|
191
|
+
this.layers = sources.length;
|
|
183
192
|
this.mipmapped = options.mipmap ?? true;
|
|
184
193
|
/* `SRGB8_ALPHA8`'s equivalent. Decoded in the sampler, before filtering, which is the only
|
|
185
194
|
place it is correct — `surfaceTexture.ts` makes the argument in full. */
|
|
@@ -188,7 +197,7 @@ export class GpuSurfaceTexture {
|
|
|
188
197
|
this.height = height;
|
|
189
198
|
this.levels = this.mipmapped ? mipLevelCount(width, height) : 1;
|
|
190
199
|
this.texture = this.allocate();
|
|
191
|
-
this.current = this.texture
|
|
200
|
+
this.current = this.arrayView(this.texture);
|
|
192
201
|
|
|
193
202
|
const wrap: GPUAddressMode =
|
|
194
203
|
(options.wrap ?? 'repeat') === 'repeat' ? 'repeat' : 'clamp-to-edge';
|
|
@@ -223,7 +232,32 @@ export class GpuSurfaceTexture {
|
|
|
223
232
|
: 1,
|
|
224
233
|
});
|
|
225
234
|
|
|
226
|
-
this.upload(
|
|
235
|
+
this.upload(sources);
|
|
236
|
+
|
|
237
|
+
/* Half floats, as `renderer.ts` uploads it: filterable, so the ordinary float layout takes it,
|
|
238
|
+
and read by `textureLoad` alone, so the filter never runs. */
|
|
239
|
+
const effects = options.effects ?? [];
|
|
240
|
+
if (effects.length > 0) {
|
|
241
|
+
const table = device.createTexture({
|
|
242
|
+
label: 'surface.effects',
|
|
243
|
+
size: [SURFACE_EFFECT_TEXELS, effects.length],
|
|
244
|
+
format: 'rgba16float',
|
|
245
|
+
usage: 0x4 | 0x2, // TEXTURE_BINDING | COPY_DST
|
|
246
|
+
});
|
|
247
|
+
device.queue.writeTexture(
|
|
248
|
+
{ texture: table },
|
|
249
|
+
toHalfFloats(packSurfaceEffects(effects)),
|
|
250
|
+
{ bytesPerRow: SURFACE_EFFECT_TEXELS * 8, rowsPerImage: effects.length },
|
|
251
|
+
{ width: SURFACE_EFFECT_TEXELS, height: effects.length, depthOrArrayLayers: 1 },
|
|
252
|
+
);
|
|
253
|
+
this.effectsTable = table;
|
|
254
|
+
this.effectsView = table.createView();
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/** A view of every layer, as the shaders' `texture_2d_array` bindings read it. */
|
|
259
|
+
private arrayView(texture: GPUTexture): GPUTextureView {
|
|
260
|
+
return texture.createView({ dimension: '2d-array', arrayLayerCount: this.layers });
|
|
227
261
|
}
|
|
228
262
|
|
|
229
263
|
/** The view every binding of this image holds. A new one when `update` changes the size. */
|
|
@@ -248,24 +282,25 @@ export class GpuSurfaceTexture {
|
|
|
248
282
|
update(source: TexImageSource): GPUTexture | null {
|
|
249
283
|
const replaced = this.texture;
|
|
250
284
|
if (replaced === null) return null;
|
|
285
|
+
refuseArrayUpdate(this.layers);
|
|
251
286
|
const { width, height } = sourceSize(source);
|
|
252
287
|
if (width === this.width && height === this.height) {
|
|
253
|
-
this.upload(source);
|
|
288
|
+
this.upload([source]);
|
|
254
289
|
return null;
|
|
255
290
|
}
|
|
256
291
|
this.width = width;
|
|
257
292
|
this.height = height;
|
|
258
293
|
this.levels = this.mipmapped ? mipLevelCount(width, height) : 1;
|
|
259
294
|
this.texture = this.allocate();
|
|
260
|
-
this.current = this.texture
|
|
261
|
-
this.upload(source);
|
|
295
|
+
this.current = this.arrayView(this.texture);
|
|
296
|
+
this.upload([source]);
|
|
262
297
|
return replaced;
|
|
263
298
|
}
|
|
264
299
|
|
|
265
300
|
private allocate(): GPUTexture {
|
|
266
301
|
return this.device.createTexture({
|
|
267
302
|
label: 'surface.texture',
|
|
268
|
-
size: [this.width, this.height],
|
|
303
|
+
size: [this.width, this.height, this.layers],
|
|
269
304
|
format: this.format,
|
|
270
305
|
mipLevelCount: this.levels,
|
|
271
306
|
/*
|
|
@@ -290,9 +325,12 @@ export class GpuSurfaceTexture {
|
|
|
290
325
|
if (this.texture === null) return;
|
|
291
326
|
this.texture.destroy();
|
|
292
327
|
this.texture = null;
|
|
328
|
+
this.effectsTable?.destroy();
|
|
329
|
+
this.effectsTable = null;
|
|
330
|
+
this.effectsView = null;
|
|
293
331
|
}
|
|
294
332
|
|
|
295
|
-
private upload(
|
|
333
|
+
private upload(sources: readonly TexImageSource[]): void {
|
|
296
334
|
const texture = this.texture;
|
|
297
335
|
if (texture === null) return;
|
|
298
336
|
/*
|
|
@@ -306,11 +344,13 @@ export class GpuSurfaceTexture {
|
|
|
306
344
|
* The orientation check that passed this backend was run on a canvas alone, where the two
|
|
307
345
|
* agreed. Measure both source types, or a texture pipeline is half tested.
|
|
308
346
|
*/
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
347
|
+
for (let layer = 0; layer < sources.length; layer++) {
|
|
348
|
+
this.device.queue.copyExternalImageToTexture(
|
|
349
|
+
{ source: sources[layer] as GPUCopyExternalImageSource, flipY: false },
|
|
350
|
+
{ texture, origin: [0, 0, layer] },
|
|
351
|
+
[this.width, this.height],
|
|
352
|
+
);
|
|
353
|
+
}
|
|
314
354
|
if (this.levels > 1) this.generateMips(texture);
|
|
315
355
|
}
|
|
316
356
|
|
|
@@ -322,6 +362,6 @@ export class GpuSurfaceTexture {
|
|
|
322
362
|
* an attachment and a resource at once — rejected, and rejected silently enough to matter.
|
|
323
363
|
*/
|
|
324
364
|
private generateMips(texture: GPUTexture): void {
|
|
325
|
-
generateMipChain(this.device, this.pipelines, texture, this.format, this.levels);
|
|
365
|
+
generateMipChain(this.device, this.pipelines, texture, this.format, this.levels, this.layers);
|
|
326
366
|
}
|
|
327
367
|
}
|
|
@@ -57,69 +57,92 @@ export function bakeBrick(
|
|
|
57
57
|
for (let k = 0; k < BRICK_SAMPLES; k++) {
|
|
58
58
|
for (let j = 0; j < BRICK_SAMPLES; j++) {
|
|
59
59
|
for (let i = 0; i < BRICK_SAMPLES; i++) {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
let weight = 0;
|
|
75
|
-
for (let listed = first; listed < last; listed++) {
|
|
76
|
-
const source = lights[layout.lights[listed] as number];
|
|
77
|
-
if (source === undefined) continue;
|
|
78
|
-
const dx = source.x - px;
|
|
79
|
-
const dy = source.y - py;
|
|
80
|
-
const dz = source.z - pz;
|
|
81
|
-
const dist = Math.hypot(dx, dy, dz);
|
|
82
|
-
if (dist >= source.radius) continue;
|
|
83
|
-
const shape = pointLightShape(dist, source.radius, falloff);
|
|
84
|
-
if (shape <= 0) continue;
|
|
85
|
-
const seen =
|
|
86
|
-
distance === null
|
|
87
|
-
? 1
|
|
88
|
-
: softVisibility(
|
|
89
|
-
distance,
|
|
90
|
-
px,
|
|
91
|
-
py,
|
|
92
|
-
pz,
|
|
93
|
-
source.x,
|
|
94
|
-
source.y,
|
|
95
|
-
source.z,
|
|
96
|
-
source.sourceRadius,
|
|
97
|
-
);
|
|
98
|
-
if (seen <= 0) continue;
|
|
99
|
-
const lr = source.r * shape * seen;
|
|
100
|
-
const lg = source.g * shape * seen;
|
|
101
|
-
const lb = source.b * shape * seen;
|
|
102
|
-
r += lr;
|
|
103
|
-
g += lg;
|
|
104
|
-
b += lb;
|
|
105
|
-
const bright = 0.2126 * lr + 0.7152 * lg + 0.0722 * lb;
|
|
106
|
-
if (dist > 1e-6 && bright > 0) {
|
|
107
|
-
towardX += (bright * dx) / dist;
|
|
108
|
-
towardY += (bright * dy) / dist;
|
|
109
|
-
towardZ += (bright * dz) / dist;
|
|
110
|
-
weight += bright;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
light[texel] = r;
|
|
114
|
-
light[texel + 1] = g;
|
|
115
|
-
light[texel + 2] = b;
|
|
116
|
-
light[texel + 3] = 1;
|
|
117
|
-
if (weight > 0) {
|
|
118
|
-
direction[texel] = towardX / weight;
|
|
119
|
-
direction[texel + 1] = towardY / weight;
|
|
120
|
-
direction[texel + 2] = towardZ / weight;
|
|
121
|
-
}
|
|
60
|
+
sampleFieldLight(
|
|
61
|
+
bx + i * spacing,
|
|
62
|
+
by + j * spacing,
|
|
63
|
+
bz + k * spacing,
|
|
64
|
+
lights,
|
|
65
|
+
layout.lights,
|
|
66
|
+
first,
|
|
67
|
+
last,
|
|
68
|
+
falloff,
|
|
69
|
+
distance,
|
|
70
|
+
light,
|
|
71
|
+
direction,
|
|
72
|
+
(i + BRICK_SAMPLES * (j + BRICK_SAMPLES * k)) * 4,
|
|
73
|
+
);
|
|
122
74
|
}
|
|
123
75
|
}
|
|
124
76
|
}
|
|
125
77
|
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* One sample: the light arriving at (px, py, pz) from `lights[candidates[first..last)]`, written at
|
|
81
|
+
* `texel` in `light` (colour, then 1 for a sample and 0 for one inside solid geometry) and in
|
|
82
|
+
* `direction` (the brightness-weighted way it arrives from). Shared by every bake, so a brick and a
|
|
83
|
+
* dense volume cannot come to disagree about what a sample is.
|
|
84
|
+
*/
|
|
85
|
+
export function sampleFieldLight(
|
|
86
|
+
px: number,
|
|
87
|
+
py: number,
|
|
88
|
+
pz: number,
|
|
89
|
+
lights: readonly FieldLight[],
|
|
90
|
+
candidates: ArrayLike<number>,
|
|
91
|
+
first: number,
|
|
92
|
+
last: number,
|
|
93
|
+
falloff: PointLightFalloff,
|
|
94
|
+
distance: DistanceAt | null,
|
|
95
|
+
light: Float32Array,
|
|
96
|
+
direction: Float32Array,
|
|
97
|
+
texel: number,
|
|
98
|
+
): void {
|
|
99
|
+
light.fill(0, texel, texel + 4);
|
|
100
|
+
direction.fill(0, texel, texel + 4);
|
|
101
|
+
if (distance !== null && distance(px, py, pz) < 0) return;
|
|
102
|
+
|
|
103
|
+
let r = 0;
|
|
104
|
+
let g = 0;
|
|
105
|
+
let b = 0;
|
|
106
|
+
let towardX = 0;
|
|
107
|
+
let towardY = 0;
|
|
108
|
+
let towardZ = 0;
|
|
109
|
+
let weight = 0;
|
|
110
|
+
for (let listed = first; listed < last; listed++) {
|
|
111
|
+
const source = lights[candidates[listed] as number];
|
|
112
|
+
if (source === undefined) continue;
|
|
113
|
+
const dx = source.x - px;
|
|
114
|
+
const dy = source.y - py;
|
|
115
|
+
const dz = source.z - pz;
|
|
116
|
+
const dist = Math.hypot(dx, dy, dz);
|
|
117
|
+
if (dist >= source.radius) continue;
|
|
118
|
+
const shape = pointLightShape(dist, source.radius, falloff);
|
|
119
|
+
if (shape <= 0) continue;
|
|
120
|
+
const seen =
|
|
121
|
+
distance === null
|
|
122
|
+
? 1
|
|
123
|
+
: softVisibility(distance, px, py, pz, source.x, source.y, source.z, source.sourceRadius);
|
|
124
|
+
if (seen <= 0) continue;
|
|
125
|
+
const lr = source.r * shape * seen;
|
|
126
|
+
const lg = source.g * shape * seen;
|
|
127
|
+
const lb = source.b * shape * seen;
|
|
128
|
+
r += lr;
|
|
129
|
+
g += lg;
|
|
130
|
+
b += lb;
|
|
131
|
+
const bright = 0.2126 * lr + 0.7152 * lg + 0.0722 * lb;
|
|
132
|
+
if (dist > 1e-6 && bright > 0) {
|
|
133
|
+
towardX += (bright * dx) / dist;
|
|
134
|
+
towardY += (bright * dy) / dist;
|
|
135
|
+
towardZ += (bright * dz) / dist;
|
|
136
|
+
weight += bright;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
light[texel] = r;
|
|
140
|
+
light[texel + 1] = g;
|
|
141
|
+
light[texel + 2] = b;
|
|
142
|
+
light[texel + 3] = 1;
|
|
143
|
+
if (weight > 0) {
|
|
144
|
+
direction[texel] = towardX / weight;
|
|
145
|
+
direction[texel + 1] = towardY / weight;
|
|
146
|
+
direction[texel + 2] = towardZ / weight;
|
|
147
|
+
}
|
|
148
|
+
}
|