@meimu/mutracer 0.1.5 → 0.3.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/LICENSES/Classroom-CC0.txt +121 -0
- package/README.md +10 -7
- package/THIRD_PARTY_NOTICES.md +13 -8
- package/dist/assets/bvh.worker.js +1 -1
- package/dist/mutracer.umd.js +12316 -9228
- package/docs/api.md +232 -21
- package/docs/caustics.md +80 -0
- package/docs/denoising.md +30 -15
- package/docs/materials.md +6 -5
- package/docs/performance.md +5 -2
- package/docs/progressive-rendering.md +73 -1
- package/docs/technical/continuous-spectrum.md +93 -0
- package/docs/threejs.md +14 -5
- package/docs/updates.md +46 -2
- package/docs/viewer-checklist.md +65 -0
- package/docs/viewer.md +15 -8
- package/lib/Display.d.ts +13 -2
- package/lib/Display.js +28 -7
- package/lib/Display.js.map +1 -1
- package/lib/Engine.d.ts +4 -0
- package/lib/Engine.js +99 -37
- package/lib/Engine.js.map +1 -1
- package/lib/Render.d.ts +98 -15
- package/lib/Render.js +275 -27
- package/lib/Render.js.map +1 -1
- package/lib/RenderLoop.d.ts +11 -1
- package/lib/RenderLoop.js +120 -15
- package/lib/RenderLoop.js.map +1 -1
- package/lib/main.d.ts +6 -3
- package/lib/main.js +1 -0
- package/lib/main.js.map +1 -1
- package/lib/math/access.d.ts +4 -0
- package/lib/math/access.js +10 -0
- package/lib/math/access.js.map +1 -0
- package/lib/math/mat3.d.ts +4 -0
- package/lib/math/mat3.js +54 -0
- package/lib/math/mat3.js.map +1 -0
- package/lib/math/mat4.d.ts +19 -0
- package/lib/math/mat4.js +413 -0
- package/lib/math/mat4.js.map +1 -0
- package/lib/math/storage.d.ts +6 -0
- package/lib/math/storage.js +22 -0
- package/lib/math/storage.js.map +1 -0
- package/lib/math/types.d.ts +3 -0
- package/lib/math/types.js +2 -0
- package/lib/math/types.js.map +1 -0
- package/lib/math/vec2.d.ts +13 -0
- package/lib/math/vec2.js +52 -0
- package/lib/math/vec2.js.map +1 -0
- package/lib/math/vec3.d.ts +23 -0
- package/lib/math/vec3.js +139 -0
- package/lib/math/vec3.js.map +1 -0
- package/lib/math.d.ts +5 -17
- package/lib/math.js +5 -55
- package/lib/math.js.map +1 -1
- package/lib/oidn.d.ts +1 -1
- package/lib/oidn.js +4 -2
- package/lib/oidn.js.map +1 -1
- package/lib/oidnBundledWeights.cdn.d.ts +2 -2
- package/lib/renderer/AovPrimitiveCache.d.ts +10 -0
- package/lib/renderer/AovPrimitiveCache.js +48 -0
- package/lib/renderer/AovPrimitiveCache.js.map +1 -0
- package/lib/renderer/Box3.d.ts +5 -0
- package/lib/renderer/Box3.js +9 -0
- package/lib/renderer/Box3.js.map +1 -0
- package/lib/renderer/GPUTraceQueue.d.ts +11 -0
- package/lib/renderer/GPUTraceQueue.js +33 -0
- package/lib/renderer/GPUTraceQueue.js.map +1 -0
- package/lib/renderer/MaterialData.d.ts +15 -0
- package/lib/renderer/MaterialData.js +61 -0
- package/lib/renderer/MaterialData.js.map +1 -0
- package/lib/renderer/MaterialTable.d.ts +11 -98
- package/lib/renderer/MaterialTable.js +34 -412
- package/lib/renderer/MaterialTable.js.map +1 -1
- package/lib/renderer/RenderingPipeline.d.ts +36 -13
- package/lib/renderer/RenderingPipeline.js +1 -17
- package/lib/renderer/RenderingPipeline.js.map +1 -1
- package/lib/renderer/TileRender.d.ts +0 -1
- package/lib/renderer/TileRender.js +14 -1
- package/lib/renderer/TileRender.js.map +1 -1
- package/lib/renderer/WGPUAov.d.ts +39 -0
- package/lib/renderer/WGPUAov.js +239 -0
- package/lib/renderer/WGPUAov.js.map +1 -0
- package/lib/renderer/WGPUBindlessMaterialData.d.ts +17 -0
- package/lib/renderer/WGPUBindlessMaterialData.js +48 -0
- package/lib/renderer/WGPUBindlessMaterialData.js.map +1 -0
- package/lib/renderer/WGPUBindlessTextures.d.ts +47 -0
- package/lib/renderer/WGPUBindlessTextures.js +180 -0
- package/lib/renderer/WGPUBindlessTextures.js.map +1 -0
- package/lib/renderer/WGPUBloomPass.js +17 -97
- package/lib/renderer/WGPUBloomPass.js.map +1 -1
- package/lib/renderer/WGPUCausticLightPass.d.ts +48 -0
- package/lib/renderer/WGPUCausticLightPass.js +217 -0
- package/lib/renderer/WGPUCausticLightPass.js.map +1 -0
- package/lib/renderer/WGPUComputePass.d.ts +1 -1
- package/lib/renderer/WGPUComputePass.js.map +1 -1
- package/lib/renderer/WGPUEnvMapDistribution.d.ts +12 -0
- package/lib/renderer/WGPUEnvMapDistribution.js +150 -0
- package/lib/renderer/WGPUEnvMapDistribution.js.map +1 -0
- package/lib/renderer/WGPUFullQuadPass.js +10 -9
- package/lib/renderer/WGPUFullQuadPass.js.map +1 -1
- package/lib/renderer/WGPUJNLMDenoiser.d.ts +1 -20
- package/lib/renderer/WGPUJNLMDenoiser.js +4 -267
- package/lib/renderer/WGPUJNLMDenoiser.js.map +1 -1
- package/lib/renderer/WGPUPhotonMap.d.ts +37 -0
- package/lib/renderer/WGPUPhotonMap.js +191 -0
- package/lib/renderer/WGPUPhotonMap.js.map +1 -0
- package/lib/renderer/WGPURayTraceOutput.d.ts +13 -1
- package/lib/renderer/WGPURayTraceOutput.js +132 -29
- package/lib/renderer/WGPURayTraceOutput.js.map +1 -1
- package/lib/renderer/WGPURayTracePass.d.ts +83 -56
- package/lib/renderer/WGPURayTracePass.js +884 -837
- package/lib/renderer/WGPURayTracePass.js.map +1 -1
- package/lib/renderer/WGPURenderingPipeline.d.ts +5 -3
- package/lib/renderer/WGPURenderingPipeline.js +297 -82
- package/lib/renderer/WGPURenderingPipeline.js.map +1 -1
- package/lib/renderer/WGPUShaderCache.d.ts +2 -2
- package/lib/renderer/WGPUShaderCache.js +10 -5
- package/lib/renderer/WGPUShaderCache.js.map +1 -1
- package/lib/renderer/WGPUShaderCapabilities.d.ts +10 -0
- package/lib/renderer/WGPUShaderCapabilities.js +54 -0
- package/lib/renderer/WGPUShaderCapabilities.js.map +1 -0
- package/lib/renderer/WGPUSkyBaker.d.ts +13 -0
- package/lib/renderer/WGPUSkyBaker.js +85 -0
- package/lib/renderer/WGPUSkyBaker.js.map +1 -0
- package/lib/renderer/WebGLAov.d.ts +41 -0
- package/lib/renderer/WebGLAov.js +106 -0
- package/lib/renderer/WebGLAov.js.map +1 -0
- package/lib/renderer/WebGLFullQuadPass.d.ts +7 -4
- package/lib/renderer/WebGLFullQuadPass.js +22 -2
- package/lib/renderer/WebGLFullQuadPass.js.map +1 -1
- package/lib/renderer/WebGLJNLMDenoiser.d.ts +1 -1
- package/lib/renderer/WebGLJNLMDenoiser.js +83 -74
- package/lib/renderer/WebGLJNLMDenoiser.js.map +1 -1
- package/lib/renderer/WebGLRayTraceOutputPass.js +7 -4
- package/lib/renderer/WebGLRayTraceOutputPass.js.map +1 -1
- package/lib/renderer/WebGLRayTracePass.d.ts +18 -3
- package/lib/renderer/WebGLRayTracePass.js +121 -9
- package/lib/renderer/WebGLRayTracePass.js.map +1 -1
- package/lib/renderer/WebGLRenderingPipeline.js +126 -22
- package/lib/renderer/WebGLRenderingPipeline.js.map +1 -1
- package/lib/renderer/WebGLSkyBaker.d.ts +39 -0
- package/lib/renderer/WebGLSkyBaker.js +422 -0
- package/lib/renderer/WebGLSkyBaker.js.map +1 -0
- package/lib/renderer/WebGLSkySource.d.ts +9 -0
- package/lib/renderer/WebGLSkySource.js +28 -0
- package/lib/renderer/WebGLSkySource.js.map +1 -0
- package/lib/renderer/accumulationTarget.d.ts +6 -0
- package/lib/renderer/accumulationTarget.js.map +1 -1
- package/lib/renderer/aov.d.ts +42 -0
- package/lib/renderer/aov.js +50 -0
- package/lib/renderer/aov.js.map +1 -0
- package/lib/renderer/aovDisplay.d.ts +14 -0
- package/lib/renderer/aovDisplay.js +32 -0
- package/lib/renderer/aovDisplay.js.map +1 -0
- package/lib/renderer/aovScene.d.ts +21 -0
- package/lib/renderer/aovScene.js +139 -0
- package/lib/renderer/aovScene.js.map +1 -0
- package/lib/renderer/binnedSahBvh.js +2 -1
- package/lib/renderer/binnedSahBvh.js.map +1 -1
- package/lib/renderer/bvhAccel.d.ts +20 -10
- package/lib/renderer/bvhAccel.js +168 -58
- package/lib/renderer/bvhAccel.js.map +1 -1
- package/lib/renderer/bvhWorkerBuild.d.ts +1 -0
- package/lib/renderer/cameraSnapshot.js +2 -1
- package/lib/renderer/cameraSnapshot.js.map +1 -1
- package/lib/renderer/cameraUniform.d.ts +2 -0
- package/lib/renderer/cameraUniform.js +12 -0
- package/lib/renderer/cameraUniform.js.map +1 -0
- package/lib/renderer/causticDiagnostics.d.ts +31 -0
- package/lib/renderer/causticDiagnostics.js +5 -0
- package/lib/renderer/causticDiagnostics.js.map +1 -0
- package/lib/renderer/causticEmission.d.ts +10 -0
- package/lib/renderer/causticEmission.js +40 -0
- package/lib/renderer/causticEmission.js.map +1 -0
- package/lib/renderer/causticUniform.d.ts +12 -0
- package/lib/renderer/causticUniform.js +22 -0
- package/lib/renderer/causticUniform.js.map +1 -0
- package/lib/renderer/caustics.d.ts +16 -0
- package/lib/renderer/caustics.js +93 -0
- package/lib/renderer/caustics.js.map +1 -0
- package/lib/renderer/committedScene.js +4 -0
- package/lib/renderer/committedScene.js.map +1 -1
- package/lib/renderer/denoiser.d.ts +3 -11
- package/lib/renderer/denoiser.js.map +1 -1
- package/lib/renderer/depthQuery.js +4 -1
- package/lib/renderer/depthQuery.js.map +1 -1
- package/lib/renderer/displacementPreparation.d.ts +11 -0
- package/lib/renderer/displacementPreparation.js +351 -0
- package/lib/renderer/displacementPreparation.js.map +1 -0
- package/lib/renderer/displacementRange.d.ts +1 -0
- package/lib/renderer/displacementRange.js +9 -0
- package/lib/renderer/displacementRange.js.map +1 -0
- package/lib/renderer/displayParityDiagnostics.d.ts +11 -0
- package/lib/renderer/displayParityDiagnostics.js +2 -0
- package/lib/renderer/displayParityDiagnostics.js.map +1 -0
- package/lib/renderer/envMapCreation.d.ts +9 -8
- package/lib/renderer/envMapCreation.js +36 -12
- package/lib/renderer/envMapCreation.js.map +1 -1
- package/lib/renderer/envMapDistribution.d.ts +12 -2
- package/lib/renderer/envMapDistribution.js +43 -34
- package/lib/renderer/envMapDistribution.js.map +1 -1
- package/lib/renderer/geometryBvhBounds.d.ts +4 -0
- package/lib/renderer/geometryBvhBounds.js +82 -0
- package/lib/renderer/geometryBvhBounds.js.map +1 -0
- package/lib/renderer/geometryUpdateState.d.ts +32 -0
- package/lib/renderer/geometryUpdateState.js +2 -0
- package/lib/renderer/geometryUpdateState.js.map +1 -0
- package/lib/renderer/geometryUpdates.d.ts +17 -9
- package/lib/renderer/geometryUpdates.js +92 -33
- package/lib/renderer/geometryUpdates.js.map +1 -1
- package/lib/renderer/glsl/aovDisplay.frag.d.ts +3 -0
- package/lib/renderer/glsl/aovDisplay.frag.js +54 -0
- package/lib/renderer/glsl/aovDisplay.frag.js.map +1 -0
- package/lib/renderer/glsl/aovReflectance.glsl.d.ts +2 -0
- package/lib/renderer/glsl/aovReflectance.glsl.js +87 -0
- package/lib/renderer/glsl/aovReflectance.glsl.js.map +1 -0
- package/lib/renderer/glsl/aovReflectanceSamples.glsl.d.ts +2 -0
- package/lib/renderer/glsl/aovReflectanceSamples.glsl.js +135 -0
- package/lib/renderer/glsl/aovReflectanceSamples.glsl.js.map +1 -0
- package/lib/renderer/glsl/aovTrace.frag.d.ts +2 -0
- package/lib/renderer/glsl/aovTrace.frag.js +121 -0
- package/lib/renderer/glsl/aovTrace.frag.js.map +1 -0
- package/lib/renderer/glsl/chunks/cameraRay.glsl.js +12 -12
- package/lib/renderer/glsl/chunks/emissiveLight.glsl.d.ts +2 -0
- package/lib/renderer/glsl/chunks/emissiveLight.glsl.js +35 -0
- package/lib/renderer/glsl/chunks/emissiveLight.glsl.js.map +1 -0
- package/lib/renderer/glsl/chunks/envMap.glsl.js +73 -67
- package/lib/renderer/glsl/chunks/envMap.glsl.js.map +1 -1
- package/lib/renderer/glsl/chunks/intersect.glsl.js +432 -434
- package/lib/renderer/glsl/chunks/intersect.glsl.js.map +1 -1
- package/lib/renderer/glsl/chunks/materialBuffer.glsl.d.ts +1 -0
- package/lib/renderer/glsl/chunks/materialBuffer.glsl.js +160 -157
- package/lib/renderer/glsl/chunks/materialBuffer.glsl.js.map +1 -1
- package/lib/renderer/glsl/chunks/openPbrBsdf.glsl.js +802 -802
- package/lib/renderer/glsl/chunks/rand.glsl.js +3 -3
- package/lib/renderer/glsl/chunks/random.glsl.js +6 -6
- package/lib/renderer/glsl/chunks/rayTraceCore.glsl.d.ts +1 -0
- package/lib/renderer/glsl/chunks/rayTraceCore.glsl.js +72 -67
- package/lib/renderer/glsl/chunks/rayTraceCore.glsl.js.map +1 -1
- package/lib/renderer/glsl/chunks/sampleLight.glsl.js +94 -76
- package/lib/renderer/glsl/chunks/sampleLight.glsl.js.map +1 -1
- package/lib/renderer/glsl/chunks/sampleMaterial.glsl.d.ts +1 -0
- package/lib/renderer/glsl/chunks/sampleMaterial.glsl.js +143 -120
- package/lib/renderer/glsl/chunks/sampleMaterial.glsl.js.map +1 -1
- package/lib/renderer/glsl/chunks/sampleShadowCatcher.glsl.js +21 -18
- package/lib/renderer/glsl/chunks/sampleShadowCatcher.glsl.js.map +1 -1
- package/lib/renderer/glsl/chunks/sampling.glsl.js +91 -94
- package/lib/renderer/glsl/chunks/sampling.glsl.js.map +1 -1
- package/lib/renderer/glsl/chunks/sobol.glsl.js +79 -79
- package/lib/renderer/glsl/chunks/textureLinear.glsl.js +5 -5
- package/lib/renderer/glsl/chunks/uvProjection.glsl.js +12 -12
- package/lib/renderer/glsl/chunks/uvProjection.glsl.js.map +1 -1
- package/lib/renderer/glsl/depthQuery.frag.js +7 -7
- package/lib/renderer/glsl/normalizeRayTraceOutput.frag.js +17 -9
- package/lib/renderer/glsl/normalizeRayTraceOutput.frag.js.map +1 -1
- package/lib/renderer/glsl/rayTrace.frag.d.ts +1 -1
- package/lib/renderer/glsl/rayTrace.frag.js +271 -248
- package/lib/renderer/glsl/rayTrace.frag.js.map +1 -1
- package/lib/renderer/glsl/shadowCatcher.frag.js +37 -32
- package/lib/renderer/glsl/shadowCatcher.frag.js.map +1 -1
- package/lib/renderer/glsl/webglPipeline.frag.js +65 -60
- package/lib/renderer/glsl/webglPipeline.frag.js.map +1 -1
- package/lib/renderer/lightConstants.d.ts +10 -0
- package/lib/renderer/lightConstants.js +11 -0
- package/lib/renderer/lightConstants.js.map +1 -0
- package/lib/renderer/lightCore.d.ts +12 -0
- package/lib/renderer/lightCore.js +13 -0
- package/lib/renderer/lightCore.js.map +1 -0
- package/lib/renderer/lightSampling.d.ts +22 -18
- package/lib/renderer/lightSampling.js +135 -62
- package/lib/renderer/lightSampling.js.map +1 -1
- package/lib/renderer/lightsData.d.ts +21 -0
- package/lib/renderer/lightsData.js +192 -0
- package/lib/renderer/lightsData.js.map +1 -0
- package/lib/renderer/lightsUtil.d.ts +3 -26
- package/lib/renderer/lightsUtil.js +3 -153
- package/lib/renderer/lightsUtil.js.map +1 -1
- package/lib/renderer/materialBufferData.d.ts +70 -0
- package/lib/renderer/materialBufferData.js +2 -0
- package/lib/renderer/materialBufferData.js.map +1 -0
- package/lib/renderer/materialConstants.d.ts +11 -0
- package/lib/renderer/materialConstants.js +11 -0
- package/lib/renderer/materialConstants.js.map +1 -1
- package/lib/renderer/materialCore.d.ts +8 -0
- package/lib/renderer/materialCore.js +9 -0
- package/lib/renderer/materialCore.js.map +1 -0
- package/lib/renderer/materialEmission.d.ts +2 -2
- package/lib/renderer/materialEmission.js +3 -3
- package/lib/renderer/materialEmission.js.map +1 -1
- package/lib/renderer/materialLayout.d.ts +2 -101
- package/lib/renderer/materialLayout.js +110 -172
- package/lib/renderer/materialLayout.js.map +1 -1
- package/lib/renderer/materialLayoutSchema.d.ts +26 -0
- package/lib/renderer/materialLayoutSchema.js +172 -0
- package/lib/renderer/materialLayoutSchema.js.map +1 -0
- package/lib/renderer/materialParams.d.ts +69 -0
- package/lib/renderer/materialParams.js +272 -0
- package/lib/renderer/materialParams.js.map +1 -0
- package/lib/renderer/materialTextureSlots.d.ts +14 -324
- package/lib/renderer/materialTextureSlots.js +21 -8
- package/lib/renderer/materialTextureSlots.js.map +1 -1
- package/lib/renderer/materialTextures.d.ts +6 -0
- package/lib/renderer/{texturesFromMaterials.js → materialTextures.js} +1 -2
- package/lib/renderer/materialTextures.js.map +1 -0
- package/lib/renderer/mergeMeshesToGeometry.js +6 -147
- package/lib/renderer/mergeMeshesToGeometry.js.map +1 -1
- package/lib/renderer/meshInstances.d.ts +4 -21
- package/lib/renderer/meshInstances.js +10 -56
- package/lib/renderer/meshInstances.js.map +1 -1
- package/lib/renderer/oidnNetwork.d.ts +2 -2
- package/lib/renderer/oidnNetwork.js +1 -1
- package/lib/renderer/oidnNetwork.js.map +1 -1
- package/lib/renderer/openPbrEnergyLut.js +850 -846
- package/lib/renderer/openPbrEnergyLut.js.map +1 -1
- package/lib/renderer/ownedDenoiser.d.ts +9 -0
- package/lib/renderer/ownedDenoiser.js +2 -0
- package/lib/renderer/ownedDenoiser.js.map +1 -0
- package/lib/renderer/packedMeshInstances.d.ts +23 -0
- package/lib/renderer/packedMeshInstances.js +80 -0
- package/lib/renderer/packedMeshInstances.js.map +1 -0
- package/lib/renderer/prepareMeshBVH.d.ts +12 -47
- package/lib/renderer/prepareMeshBVH.js +21 -642
- package/lib/renderer/prepareMeshBVH.js.map +1 -1
- package/lib/renderer/proceduralEnvironmentPower.d.ts +3 -0
- package/lib/renderer/proceduralEnvironmentPower.js +8 -0
- package/lib/renderer/proceduralEnvironmentPower.js.map +1 -0
- package/lib/renderer/progressiveScheduler.d.ts +1 -0
- package/lib/renderer/progressiveScheduler.js +7 -3
- package/lib/renderer/progressiveScheduler.js.map +1 -1
- package/lib/renderer/renderPipeline.d.ts +4 -1
- package/lib/renderer/renderPipeline.js.map +1 -1
- package/lib/renderer/renderingLimits.d.ts +9 -0
- package/lib/renderer/renderingLimits.js +18 -0
- package/lib/renderer/renderingLimits.js.map +1 -0
- package/lib/renderer/researchTransport.d.ts +31 -0
- package/lib/renderer/researchTransport.js +5 -0
- package/lib/renderer/researchTransport.js.map +1 -0
- package/lib/renderer/sceneAssembly.d.ts +73 -0
- package/lib/renderer/sceneAssembly.js +109 -0
- package/lib/renderer/sceneAssembly.js.map +1 -0
- package/lib/renderer/sceneChangeCore.d.ts +39 -0
- package/lib/renderer/sceneChangeCore.js +307 -0
- package/lib/renderer/sceneChangeCore.js.map +1 -0
- package/lib/renderer/sceneChangeDetector.d.ts +3 -6
- package/lib/renderer/sceneChangeDetector.js +24 -150
- package/lib/renderer/sceneChangeDetector.js.map +1 -1
- package/lib/renderer/sceneLayoutSchema.d.ts +119 -0
- package/lib/renderer/sceneLayoutSchema.js +111 -0
- package/lib/renderer/sceneLayoutSchema.js.map +1 -0
- package/lib/renderer/sceneLightChanges.d.ts +3 -3
- package/lib/renderer/sceneLightChanges.js.map +1 -1
- package/lib/renderer/scenePreparation.d.ts +55 -0
- package/lib/renderer/scenePreparation.js +360 -0
- package/lib/renderer/scenePreparation.js.map +1 -0
- package/lib/renderer/scratchSampling.js +18 -18
- package/lib/renderer/scratchSampling.js.map +1 -1
- package/lib/renderer/shader.d.ts +2 -0
- package/lib/renderer/shader.js +2 -0
- package/lib/renderer/shader.js.map +1 -1
- package/lib/renderer/shaderCapabilities.d.ts +23 -0
- package/lib/renderer/shaderCapabilities.js +55 -0
- package/lib/renderer/shaderCapabilities.js.map +1 -0
- package/lib/renderer/shaderCapacity.d.ts +2 -0
- package/lib/renderer/shaderCapacity.js +5 -0
- package/lib/renderer/shaderCapacity.js.map +1 -0
- package/lib/renderer/skyModel.d.ts +9 -0
- package/lib/renderer/skyModel.js +10 -0
- package/lib/renderer/skyModel.js.map +1 -0
- package/lib/renderer/spectrum.d.ts +21 -0
- package/lib/renderer/spectrum.js +154 -0
- package/lib/renderer/spectrum.js.map +1 -0
- package/lib/renderer/textureAtlas.d.ts +60 -0
- package/lib/renderer/textureAtlas.js +145 -0
- package/lib/renderer/textureAtlas.js.map +1 -0
- package/lib/renderer/textureAtlasPixels.d.ts +7 -0
- package/lib/renderer/textureAtlasPixels.js +68 -0
- package/lib/renderer/textureAtlasPixels.js.map +1 -0
- package/lib/renderer/util.d.ts +1 -1
- package/lib/renderer/util.js.map +1 -1
- package/lib/renderer/webgl.d.ts +9 -2
- package/lib/renderer/webgl.js +54 -9
- package/lib/renderer/webgl.js.map +1 -1
- package/lib/renderer/webglLightSampling.d.ts +39 -0
- package/lib/renderer/webglLightSampling.js +15 -0
- package/lib/renderer/webglLightSampling.js.map +1 -0
- package/lib/renderer/wgpuBindless.d.ts +26 -0
- package/lib/renderer/wgpuBindless.js +95 -0
- package/lib/renderer/wgpuBindless.js.map +1 -0
- package/lib/renderer/wgpuBindlessSource.d.ts +2 -0
- package/lib/renderer/wgpuBindlessSource.js +51 -0
- package/lib/renderer/wgpuBindlessSource.js.map +1 -0
- package/lib/renderer/wgpuMaterialConstants.d.ts +4 -0
- package/lib/renderer/wgpuMaterialConstants.js +52 -0
- package/lib/renderer/wgpuMaterialConstants.js.map +1 -0
- package/lib/renderer/wgpuSceneUniform.d.ts +42 -0
- package/lib/renderer/wgpuSceneUniform.js +125 -0
- package/lib/renderer/wgpuSceneUniform.js.map +1 -0
- package/lib/renderer/wgpuShaderSource.d.ts +22 -0
- package/lib/renderer/wgpuShaderSource.js +33 -0
- package/lib/renderer/wgpuShaderSource.js.map +1 -0
- package/lib/renderer/wgsl/aovDisplay.wgsl.d.ts +1 -0
- package/lib/renderer/wgsl/aovDisplay.wgsl.js +70 -0
- package/lib/renderer/wgsl/aovDisplay.wgsl.js.map +1 -0
- package/lib/renderer/wgsl/aovReflectance.wgsl.d.ts +2 -0
- package/lib/renderer/wgsl/aovReflectance.wgsl.js +98 -0
- package/lib/renderer/wgsl/aovReflectance.wgsl.js.map +1 -0
- package/lib/renderer/wgsl/aovReflectanceSamples.wgsl.d.ts +2 -0
- package/lib/renderer/wgsl/aovReflectanceSamples.wgsl.js +135 -0
- package/lib/renderer/wgsl/aovReflectanceSamples.wgsl.js.map +1 -0
- package/lib/renderer/wgsl/aovResolve.wgsl.d.ts +5 -0
- package/lib/renderer/wgsl/aovResolve.wgsl.js +38 -0
- package/lib/renderer/wgsl/aovResolve.wgsl.js.map +1 -0
- package/lib/renderer/wgsl/aovSnapshot.wgsl.d.ts +4 -0
- package/lib/renderer/wgsl/aovSnapshot.wgsl.js +21 -0
- package/lib/renderer/wgsl/aovSnapshot.wgsl.js.map +1 -0
- package/lib/renderer/wgsl/aovTrace.wgsl.d.ts +2 -0
- package/lib/renderer/wgsl/aovTrace.wgsl.js +115 -0
- package/lib/renderer/wgsl/aovTrace.wgsl.js.map +1 -0
- package/lib/renderer/wgsl/bloom.wgsl.d.ts +13 -0
- package/lib/renderer/wgsl/bloom.wgsl.js +92 -0
- package/lib/renderer/wgsl/bloom.wgsl.js.map +1 -0
- package/lib/renderer/wgsl/causticLight.compute.d.ts +6 -0
- package/lib/renderer/wgsl/causticLight.compute.js +537 -0
- package/lib/renderer/wgsl/causticLight.compute.js.map +1 -0
- package/lib/renderer/wgsl/chunks/background.wgsl.d.ts +2 -0
- package/lib/renderer/wgsl/chunks/background.wgsl.js +102 -0
- package/lib/renderer/wgsl/chunks/background.wgsl.js.map +1 -0
- package/lib/renderer/wgsl/chunks/causticAdjoint.wgsl.d.ts +2 -0
- package/lib/renderer/wgsl/chunks/causticAdjoint.wgsl.js +12 -0
- package/lib/renderer/wgsl/chunks/causticAdjoint.wgsl.js.map +1 -0
- package/lib/renderer/wgsl/chunks/causticAtomic.wgsl.d.ts +2 -0
- package/lib/renderer/wgsl/chunks/causticAtomic.wgsl.js +16 -0
- package/lib/renderer/wgsl/chunks/causticAtomic.wgsl.js.map +1 -0
- package/lib/renderer/wgsl/chunks/caustics.wgsl.d.ts +1 -0
- package/lib/renderer/wgsl/chunks/caustics.wgsl.js +62 -0
- package/lib/renderer/wgsl/chunks/caustics.wgsl.js.map +1 -0
- package/lib/renderer/wgsl/chunks/common.wgsl.js +4 -4
- package/lib/renderer/wgsl/chunks/envMap.wgsl.d.ts +1 -1
- package/lib/renderer/wgsl/chunks/envMap.wgsl.js +41 -35
- package/lib/renderer/wgsl/chunks/envMap.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/chunks/intersect.wgsl.d.ts +13 -1
- package/lib/renderer/wgsl/chunks/intersect.wgsl.js +747 -704
- package/lib/renderer/wgsl/chunks/intersect.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/chunks/intersectionAlpha.wgsl.js +16 -16
- package/lib/renderer/wgsl/chunks/intersectionAlpha.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.d.ts +4 -1
- package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.js +83 -79
- package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/chunks/openPbrBsdf.wgsl.js +855 -857
- package/lib/renderer/wgsl/chunks/openPbrBsdf.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/chunks/pdm_displacement.wgsl.js +137 -137
- package/lib/renderer/wgsl/chunks/rand.wgsl.js +3 -3
- package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.d.ts +3 -1
- package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.js +52 -32
- package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/chunks/sampleLight.wgsl.d.ts +1 -1
- package/lib/renderer/wgsl/chunks/sampleLight.wgsl.js +152 -144
- package/lib/renderer/wgsl/chunks/sampleLight.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/chunks/sampleMaterial.wgsl.d.ts +1 -1
- package/lib/renderer/wgsl/chunks/sampleMaterial.wgsl.js +269 -245
- package/lib/renderer/wgsl/chunks/sampleMaterial.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/chunks/sampleShadowCatcher.wgsl.d.ts +1 -1
- package/lib/renderer/wgsl/chunks/sampleShadowCatcher.wgsl.js +27 -14
- package/lib/renderer/wgsl/chunks/sampleShadowCatcher.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/chunks/sampling.wgsl.d.ts +1 -1
- package/lib/renderer/wgsl/chunks/sampling.wgsl.js +91 -95
- package/lib/renderer/wgsl/chunks/sampling.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/chunks/shadowCatcherAccumulation.wgsl.d.ts +1 -1
- package/lib/renderer/wgsl/chunks/shadowCatcherAccumulation.wgsl.js +1 -0
- package/lib/renderer/wgsl/chunks/shadowCatcherAccumulation.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/chunks/sobol.wgsl.js +83 -83
- package/lib/renderer/wgsl/chunks/uvProjection.wgsl.js +12 -12
- package/lib/renderer/wgsl/chunks/uvProjection.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/compose.frag.wgsl.d.ts +8 -3
- package/lib/renderer/wgsl/compose.frag.wgsl.js +143 -118
- package/lib/renderer/wgsl/compose.frag.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/customDenoise.wgsl.js +10 -10
- package/lib/renderer/wgsl/depthQuery.wgsl.js +7 -7
- package/lib/renderer/wgsl/jnlm.compute.d.ts +25 -0
- package/lib/renderer/wgsl/jnlm.compute.js +315 -0
- package/lib/renderer/wgsl/jnlm.compute.js.map +1 -0
- package/lib/renderer/wgsl/offlineAdaptive.compute.js +28 -28
- package/lib/renderer/wgsl/oidnAuxiliary.wgsl.d.ts +1 -0
- package/lib/renderer/wgsl/oidnAuxiliary.wgsl.js +17 -0
- package/lib/renderer/wgsl/oidnAuxiliary.wgsl.js.map +1 -0
- package/lib/renderer/wgsl/photonMap.compute.d.ts +29 -0
- package/lib/renderer/wgsl/photonMap.compute.js +352 -0
- package/lib/renderer/wgsl/photonMap.compute.js.map +1 -0
- package/lib/renderer/wgsl/proceduralSky.compute.d.ts +1 -0
- package/lib/renderer/wgsl/proceduralSky.compute.js +198 -0
- package/lib/renderer/wgsl/proceduralSky.compute.js.map +1 -0
- package/lib/renderer/wgsl/rayTrace.compute.d.ts +25 -1
- package/lib/renderer/wgsl/rayTrace.compute.js +645 -500
- package/lib/renderer/wgsl/rayTrace.compute.js.map +1 -1
- package/lib/scene/Camera.js +7 -3
- package/lib/scene/Camera.js.map +1 -1
- package/lib/scene/EnvironmentLight.d.ts +5 -9
- package/lib/scene/EnvironmentLight.js +4 -14
- package/lib/scene/EnvironmentLight.js.map +1 -1
- package/lib/scene/EnvironmentLightState.d.ts +18 -0
- package/lib/scene/EnvironmentLightState.js +19 -0
- package/lib/scene/EnvironmentLightState.js.map +1 -0
- package/lib/scene/Geometry.d.ts +12 -6
- package/lib/scene/Geometry.js +37 -13
- package/lib/scene/Geometry.js.map +1 -1
- package/lib/scene/InstanceState.d.ts +39 -0
- package/lib/scene/InstanceState.js +77 -0
- package/lib/scene/InstanceState.js.map +1 -0
- package/lib/scene/InstancedMesh.d.ts +1 -1
- package/lib/scene/InstancedMesh.js +3 -0
- package/lib/scene/InstancedMesh.js.map +1 -1
- package/lib/scene/MaterialState.d.ts +209 -0
- package/lib/scene/MaterialState.js +231 -0
- package/lib/scene/MaterialState.js.map +1 -0
- package/lib/scene/Mesh.d.ts +4 -6
- package/lib/scene/Mesh.js +3 -11
- package/lib/scene/Mesh.js.map +1 -1
- package/lib/scene/MeshState.d.ts +20 -0
- package/lib/scene/MeshState.js +35 -0
- package/lib/scene/MeshState.js.map +1 -0
- package/lib/scene/OpenPBRMaterial.d.ts +6 -168
- package/lib/scene/OpenPBRMaterial.js +5 -223
- package/lib/scene/OpenPBRMaterial.js.map +1 -1
- package/lib/scene/PixelTexture.d.ts +6 -0
- package/lib/scene/PixelTexture.js +10 -0
- package/lib/scene/PixelTexture.js.map +1 -0
- package/lib/scene/ProceduralSky.d.ts +24 -0
- package/lib/scene/ProceduralSky.js +40 -0
- package/lib/scene/ProceduralSky.js.map +1 -0
- package/lib/scene/RectLight.d.ts +2 -13
- package/lib/scene/RectLight.js +3 -21
- package/lib/scene/RectLight.js.map +1 -1
- package/lib/scene/RectLightState.d.ts +31 -0
- package/lib/scene/RectLightState.js +26 -0
- package/lib/scene/RectLightState.js.map +1 -0
- package/lib/scene/Scene.d.ts +15 -4
- package/lib/scene/Scene.js.map +1 -1
- package/lib/scene/SceneNode.js +7 -6
- package/lib/scene/SceneNode.js.map +1 -1
- package/lib/scene/Texture.d.ts +10 -41
- package/lib/scene/Texture.js +4 -33
- package/lib/scene/Texture.js.map +1 -1
- package/lib/scene/TextureState.d.ts +35 -0
- package/lib/scene/TextureState.js +35 -0
- package/lib/scene/TextureState.js.map +1 -0
- package/lib/scene/attributeData.d.ts +4 -0
- package/lib/scene/attributeData.js +10 -0
- package/lib/scene/attributeData.js.map +1 -0
- package/lib/scene/lightState.d.ts +8 -0
- package/lib/scene/lightState.js +2 -0
- package/lib/scene/lightState.js.map +1 -0
- package/lib/scene/openPbrSchema.d.ts +7 -12
- package/lib/scene/openPbrSchema.js +273 -28
- package/lib/scene/openPbrSchema.js.map +1 -1
- package/lib/scene/skyParameters.d.ts +20 -0
- package/lib/scene/skyParameters.js +28 -0
- package/lib/scene/skyParameters.js.map +1 -0
- package/lib/scene/textureData.d.ts +9 -0
- package/lib/scene/textureData.js +2 -0
- package/lib/scene/textureData.js.map +1 -0
- package/lib/scene/texturePixels.d.ts +6 -0
- package/lib/scene/texturePixels.js +10 -0
- package/lib/scene/texturePixels.js.map +1 -0
- package/lib/settings/display.d.ts +33 -0
- package/lib/settings/display.js +7 -0
- package/lib/settings/display.js.map +1 -1
- package/lib/settings/render.d.ts +36 -3
- package/lib/settings/render.js +4 -1
- package/lib/settings/render.js.map +1 -1
- package/lib/tinybvh/tinybvh.wasm +0 -0
- package/lib/util/commonGeometry.js +7 -7
- package/lib/util/commonGeometry.js.map +1 -1
- package/lib/util/fromTHREE.d.ts +4 -1
- package/lib/util/fromTHREE.js +20 -7
- package/lib/util/fromTHREE.js.map +1 -1
- package/lib/util/geometry.js +42 -29
- package/lib/util/geometry.js.map +1 -1
- package/lib/util/loadRGBE.js +3 -4
- package/lib/util/loadRGBE.js.map +1 -1
- package/lib/util/studioLighting.d.ts +18 -0
- package/lib/util/studioLighting.js +36 -0
- package/lib/util/studioLighting.js.map +1 -0
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/lib/version.js.map +1 -1
- package/llms.txt +5 -0
- package/package.json +33 -7
- package/lib/renderer/texturesFromMaterials.d.ts +0 -6
- package/lib/renderer/texturesFromMaterials.js.map +0 -1
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export declare const MATERIAL_SHADER_CAPABILITIES: {
|
|
2
|
+
readonly transmission: 1;
|
|
3
|
+
readonly metal: 2;
|
|
4
|
+
};
|
|
5
|
+
export declare const LIGHT_SHADER_CAPABILITIES: {
|
|
6
|
+
readonly SphereLight: 1;
|
|
7
|
+
readonly RectLight: 2;
|
|
8
|
+
readonly SpotLight: 4;
|
|
9
|
+
readonly DirectionalLight: 8;
|
|
10
|
+
readonly emissive: 16;
|
|
11
|
+
};
|
|
12
|
+
export declare const ALL_MATERIAL_SHADER_CAPABILITIES = 3;
|
|
13
|
+
export declare const ALL_LIGHT_SHADER_CAPABILITIES = 31;
|
|
14
|
+
export declare function lightShaderCapabilities(types: readonly string[], emissiveCount: number): number;
|
|
15
|
+
export declare function updateSceneShaderCapabilities(constants: Record<string, boolean | number>): void;
|
|
16
|
+
export interface ShaderCapabilities {
|
|
17
|
+
SCENE_CAPABILITIES: number;
|
|
18
|
+
MATERIAL_CAPABILITIES: number;
|
|
19
|
+
LIGHT_CAPABILITIES: number;
|
|
20
|
+
}
|
|
21
|
+
export declare function shaderCapabilitiesInclude(supported: ShaderCapabilities, required: ShaderCapabilities): boolean;
|
|
22
|
+
/** Retain support, not the scene's active flags. Commit only after compilation succeeds. */
|
|
23
|
+
export declare function retainedShaderCapabilities(constants: Record<string, boolean | number>, previous?: ShaderCapabilities): ShaderCapabilities;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { wgpuSceneFeatureFlags, WGPU_SCENE_FEATURE_BITS } from './WGPUSceneFeatures.js';
|
|
2
|
+
export const MATERIAL_SHADER_CAPABILITIES = { transmission: 1, metal: 2 };
|
|
3
|
+
export const LIGHT_SHADER_CAPABILITIES = {
|
|
4
|
+
SphereLight: 1, RectLight: 2, SpotLight: 4, DirectionalLight: 8, emissive: 16
|
|
5
|
+
};
|
|
6
|
+
export const ALL_MATERIAL_SHADER_CAPABILITIES = 3;
|
|
7
|
+
export const ALL_LIGHT_SHADER_CAPABILITIES = 31;
|
|
8
|
+
export function lightShaderCapabilities(types, emissiveCount) {
|
|
9
|
+
let mask = emissiveCount > 0 ? LIGHT_SHADER_CAPABILITIES.emissive : 0;
|
|
10
|
+
for (const type of types) {
|
|
11
|
+
switch (type) {
|
|
12
|
+
case 'SphereLight':
|
|
13
|
+
mask |= LIGHT_SHADER_CAPABILITIES.SphereLight;
|
|
14
|
+
break;
|
|
15
|
+
case 'RectLight':
|
|
16
|
+
mask |= LIGHT_SHADER_CAPABILITIES.RectLight;
|
|
17
|
+
break;
|
|
18
|
+
case 'SpotLight':
|
|
19
|
+
mask |= LIGHT_SHADER_CAPABILITIES.SpotLight;
|
|
20
|
+
break;
|
|
21
|
+
case 'DirectionalLight':
|
|
22
|
+
mask |= LIGHT_SHADER_CAPABILITIES.DirectionalLight;
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return mask;
|
|
27
|
+
}
|
|
28
|
+
export function updateSceneShaderCapabilities(constants) {
|
|
29
|
+
constants.SCENE_CAPABILITIES = wgpuSceneFeatureFlags(constants);
|
|
30
|
+
}
|
|
31
|
+
export function shaderCapabilitiesInclude(supported, required) {
|
|
32
|
+
return (supported.SCENE_CAPABILITIES & required.SCENE_CAPABILITIES) === required.SCENE_CAPABILITIES &&
|
|
33
|
+
(supported.MATERIAL_CAPABILITIES & required.MATERIAL_CAPABILITIES) === required.MATERIAL_CAPABILITIES &&
|
|
34
|
+
(supported.LIGHT_CAPABILITIES & required.LIGHT_CAPABILITIES) === required.LIGHT_CAPABILITIES;
|
|
35
|
+
}
|
|
36
|
+
/** Retain support, not the scene's active flags. Commit only after compilation succeeds. */
|
|
37
|
+
export function retainedShaderCapabilities(constants, previous) {
|
|
38
|
+
let scene = wgpuSceneFeatureFlags(constants) | (previous?.SCENE_CAPABILITIES ?? 0);
|
|
39
|
+
// Metalness is a continuous base-material edit, including the first change
|
|
40
|
+
// from a dielectric to a metal. Keep that support in every base variant.
|
|
41
|
+
const material = MATERIAL_SHADER_CAPABILITIES.metal |
|
|
42
|
+
Number(constants.MATERIAL_CAPABILITIES ?? 0) | (previous?.MATERIAL_CAPABILITIES ?? 0);
|
|
43
|
+
const commonSurface = WGPU_SCENE_FEATURE_BITS.HAS_COAT | WGPU_SCENE_FEATURE_BITS.HAS_FUZZ;
|
|
44
|
+
// Activate this small group on first use, keeping a plain scene's initial
|
|
45
|
+
// pipeline lean. Thin film, media, dispersion and alpha remain independent.
|
|
46
|
+
if ((scene & commonSurface) !== 0) {
|
|
47
|
+
scene |= commonSurface;
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
SCENE_CAPABILITIES: scene,
|
|
51
|
+
MATERIAL_CAPABILITIES: material,
|
|
52
|
+
LIGHT_CAPABILITIES: Number(constants.LIGHT_CAPABILITIES ?? 0) | (previous?.LIGHT_CAPABILITIES ?? 0)
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=shaderCapabilities.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shaderCapabilities.js","sourceRoot":"","sources":["../../src/renderer/shaderCapabilities.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,qBAAqB,EAAE,uBAAuB,EAAC,MAAM,wBAAwB,CAAC;AAEtF,MAAM,CAAC,MAAM,4BAA4B,GAAG,EAAC,YAAY,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAU,CAAC;AACjF,MAAM,CAAC,MAAM,yBAAyB,GAAG;IACvC,WAAW,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,gBAAgB,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE;CACrE,CAAC;AACX,MAAM,CAAC,MAAM,gCAAgC,GAAG,CAAC,CAAC;AAClD,MAAM,CAAC,MAAM,6BAA6B,GAAG,EAAE,CAAC;AAEhD,MAAM,UAAU,uBAAuB,CAAC,KAAwB,EAAE,aAAqB;IACrF,IAAI,IAAI,GAAG,aAAa,GAAG,CAAC,CAAC,CAAC,CAAC,yBAAyB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IACtE,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,QAAQ,IAAI,EAAE,CAAC;YACb,KAAK,aAAa;gBAAE,IAAI,IAAI,yBAAyB,CAAC,WAAW,CAAC;gBAAC,MAAM;YACzE,KAAK,WAAW;gBAAE,IAAI,IAAI,yBAAyB,CAAC,SAAS,CAAC;gBAAC,MAAM;YACrE,KAAK,WAAW;gBAAE,IAAI,IAAI,yBAAyB,CAAC,SAAS,CAAC;gBAAC,MAAM;YACrE,KAAK,kBAAkB;gBAAE,IAAI,IAAI,yBAAyB,CAAC,gBAAgB,CAAC;gBAAC,MAAM;QACrF,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,6BAA6B,CAAC,SAA2C;IACvF,SAAS,CAAC,kBAAkB,GAAG,qBAAqB,CAAC,SAAS,CAAC,CAAC;AAClE,CAAC;AAQD,MAAM,UAAU,yBAAyB,CAAC,SAA6B,EAAE,QAA4B;IACnG,OAAO,CAAC,SAAS,CAAC,kBAAkB,GAAG,QAAQ,CAAC,kBAAkB,CAAC,KAAK,QAAQ,CAAC,kBAAkB;QACjG,CAAC,SAAS,CAAC,qBAAqB,GAAG,QAAQ,CAAC,qBAAqB,CAAC,KAAK,QAAQ,CAAC,qBAAqB;QACrG,CAAC,SAAS,CAAC,kBAAkB,GAAG,QAAQ,CAAC,kBAAkB,CAAC,KAAK,QAAQ,CAAC,kBAAkB,CAAC;AACjG,CAAC;AAED,4FAA4F;AAC5F,MAAM,UAAU,0BAA0B,CAAC,SAA2C,EAAE,QAA6B;IACnH,IAAI,KAAK,GAAG,qBAAqB,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,EAAE,kBAAkB,IAAI,CAAC,CAAC,CAAC;IACnF,2EAA2E;IAC3E,yEAAyE;IACzE,MAAM,QAAQ,GAAG,4BAA4B,CAAC,KAAK;QACjD,MAAM,CAAC,SAAS,CAAC,qBAAqB,IAAI,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,qBAAqB,IAAI,CAAC,CAAC,CAAC;IACxF,MAAM,aAAa,GAAG,uBAAuB,CAAC,QAAQ,GAAG,uBAAuB,CAAC,QAAQ,CAAC;IAC1F,0EAA0E;IAC1E,4EAA4E;IAC5E,IAAI,CAAC,KAAK,GAAG,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;QAClC,KAAK,IAAI,aAAa,CAAC;IACzB,CAAC;IACD,OAAO;QACL,kBAAkB,EAAE,KAAK;QACzB,qBAAqB,EAAE,QAAQ;QAC/B,kBAAkB,EAAE,MAAM,CAAC,SAAS,CAAC,kBAAkB,IAAI,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,kBAAkB,IAAI,CAAC,CAAC;KACpG,CAAC;AACJ,CAAC","sourcesContent":["import {wgpuSceneFeatureFlags, WGPU_SCENE_FEATURE_BITS} from './WGPUSceneFeatures.js';\n\nexport const MATERIAL_SHADER_CAPABILITIES = {transmission: 1, metal: 2} as const;\nexport const LIGHT_SHADER_CAPABILITIES = {\n SphereLight: 1, RectLight: 2, SpotLight: 4, DirectionalLight: 8, emissive: 16\n} as const;\nexport const ALL_MATERIAL_SHADER_CAPABILITIES = 3;\nexport const ALL_LIGHT_SHADER_CAPABILITIES = 31;\n\nexport function lightShaderCapabilities(types: readonly string[], emissiveCount: number) {\n let mask = emissiveCount > 0 ? LIGHT_SHADER_CAPABILITIES.emissive : 0;\n for (const type of types) {\n switch (type) {\n case 'SphereLight': mask |= LIGHT_SHADER_CAPABILITIES.SphereLight; break;\n case 'RectLight': mask |= LIGHT_SHADER_CAPABILITIES.RectLight; break;\n case 'SpotLight': mask |= LIGHT_SHADER_CAPABILITIES.SpotLight; break;\n case 'DirectionalLight': mask |= LIGHT_SHADER_CAPABILITIES.DirectionalLight; break;\n }\n }\n return mask;\n}\n\nexport function updateSceneShaderCapabilities(constants: Record<string, boolean | number>) {\n constants.SCENE_CAPABILITIES = wgpuSceneFeatureFlags(constants);\n}\n\nexport interface ShaderCapabilities {\n SCENE_CAPABILITIES: number;\n MATERIAL_CAPABILITIES: number;\n LIGHT_CAPABILITIES: number;\n}\n\nexport function shaderCapabilitiesInclude(supported: ShaderCapabilities, required: ShaderCapabilities) {\n return (supported.SCENE_CAPABILITIES & required.SCENE_CAPABILITIES) === required.SCENE_CAPABILITIES &&\n (supported.MATERIAL_CAPABILITIES & required.MATERIAL_CAPABILITIES) === required.MATERIAL_CAPABILITIES &&\n (supported.LIGHT_CAPABILITIES & required.LIGHT_CAPABILITIES) === required.LIGHT_CAPABILITIES;\n}\n\n/** Retain support, not the scene's active flags. Commit only after compilation succeeds. */\nexport function retainedShaderCapabilities(constants: Record<string, boolean | number>, previous?: ShaderCapabilities): ShaderCapabilities {\n let scene = wgpuSceneFeatureFlags(constants) | (previous?.SCENE_CAPABILITIES ?? 0);\n // Metalness is a continuous base-material edit, including the first change\n // from a dielectric to a metal. Keep that support in every base variant.\n const material = MATERIAL_SHADER_CAPABILITIES.metal |\n Number(constants.MATERIAL_CAPABILITIES ?? 0) | (previous?.MATERIAL_CAPABILITIES ?? 0);\n const commonSurface = WGPU_SCENE_FEATURE_BITS.HAS_COAT | WGPU_SCENE_FEATURE_BITS.HAS_FUZZ;\n // Activate this small group on first use, keeping a plain scene's initial\n // pipeline lean. Thin film, media, dispersion and alpha remain independent.\n if ((scene & commonSurface) !== 0) {\n scene |= commonSurface;\n }\n return {\n SCENE_CAPABILITIES: scene,\n MATERIAL_CAPABILITIES: material,\n LIGHT_CAPABILITIES: Number(constants.LIGHT_CAPABILITIES ?? 0) | (previous?.LIGHT_CAPABILITIES ?? 0)\n };\n}\n"]}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Grow in coarse buckets; scene edits must not shrink a compiled stack. */
|
|
2
|
+
export function retainedShaderCapacity(required, previous = 0, minimum = 8) {
|
|
3
|
+
return Math.max(previous, minimum, 2 ** Math.ceil(Math.log2(Math.max(1, required))));
|
|
4
|
+
}
|
|
5
|
+
//# sourceMappingURL=shaderCapacity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shaderCapacity.js","sourceRoot":"","sources":["../../src/renderer/shaderCapacity.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,MAAM,UAAU,sBAAsB,CAAC,QAAgB,EAAE,QAAQ,GAAG,CAAC,EAAE,OAAO,GAAG,CAAC;IAChF,OAAO,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;AACvF,CAAC","sourcesContent":["/** Grow in coarse buckets; scene edits must not shrink a compiled stack. */\nexport function retainedShaderCapacity(required: number, previous = 0, minimum = 8) {\n return Math.max(previous, minimum, 2 ** Math.ceil(Math.log2(Math.max(1, required))));\n}\n\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Apparent sun radius in degrees; larger than the real 0.27° so the disk reads at map resolution. */
|
|
2
|
+
export declare const SUN_RADIUS = 0.4;
|
|
3
|
+
/** Aerosol density relative to a very clean atmosphere (optical depth about 0.005). */
|
|
4
|
+
export declare const TURBIDITY = 5;
|
|
5
|
+
export declare const GROUND_ALBEDO: number[];
|
|
6
|
+
/** Sun plus sky irradiance on a horizontal plane with the sun at 33°. */
|
|
7
|
+
export declare const ILLUMINANCE: number;
|
|
8
|
+
/** Horizontal illuminance of this atmosphere for unit solar irradiance and a 33° sun. */
|
|
9
|
+
export declare const REFERENCE_ILLUMINANCE = 0.488;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Apparent sun radius in degrees; larger than the real 0.27° so the disk reads at map resolution. */
|
|
2
|
+
export const SUN_RADIUS = 0.4;
|
|
3
|
+
/** Aerosol density relative to a very clean atmosphere (optical depth about 0.005). */
|
|
4
|
+
export const TURBIDITY = 5;
|
|
5
|
+
export const GROUND_ALBEDO = [0.2, 0.18, 0.15];
|
|
6
|
+
/** Sun plus sky irradiance on a horizontal plane with the sun at 33°. */
|
|
7
|
+
export const ILLUMINANCE = Math.PI;
|
|
8
|
+
/** Horizontal illuminance of this atmosphere for unit solar irradiance and a 33° sun. */
|
|
9
|
+
export const REFERENCE_ILLUMINANCE = 0.488;
|
|
10
|
+
//# sourceMappingURL=skyModel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skyModel.js","sourceRoot":"","sources":["../../src/renderer/skyModel.ts"],"names":[],"mappings":"AAAA,sGAAsG;AACtG,MAAM,CAAC,MAAM,UAAU,GAAG,GAAG,CAAC;AAC9B,uFAAuF;AACvF,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC;AAC3B,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AAC/C,yEAAyE;AACzE,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,CAAC,EAAE,CAAC;AACnC,yFAAyF;AACzF,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,CAAC","sourcesContent":["/** Apparent sun radius in degrees; larger than the real 0.27° so the disk reads at map resolution. */\nexport const SUN_RADIUS = 0.4;\n/** Aerosol density relative to a very clean atmosphere (optical depth about 0.005). */\nexport const TURBIDITY = 5;\nexport const GROUND_ALBEDO = [0.2, 0.18, 0.15];\n/** Sun plus sky irradiance on a horizontal plane with the sun at 33°. */\nexport const ILLUMINANCE = Math.PI;\n/** Horizontal illuminance of this atmosphere for unit solar irradiance and a 33° sun. */\nexport const REFERENCE_ILLUMINANCE = 0.488;\n\n"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Continuous wavelength sampling shared by camera paths and caustic photons.
|
|
3
|
+
*
|
|
4
|
+
* CIE 1931 matching functions use the multi-lobe fit from Wyman, Sloan and
|
|
5
|
+
* Shirley, "Simple Analytic Approximations to the CIE XYZ Color Matching
|
|
6
|
+
* Functions", JCGT 2(2), 2013. Only the published formula and coefficients are
|
|
7
|
+
* used. Out-of-gamut negatives clamp to zero, and each channel is normalized so
|
|
8
|
+
* that a uniform wavelength keeps white light white.
|
|
9
|
+
*/
|
|
10
|
+
export declare const SPECTRUM_WAVELENGTH_MIN = 400;
|
|
11
|
+
export declare const SPECTRUM_WAVELENGTH_RANGE = 300;
|
|
12
|
+
export declare function spectrumRgb(wavelength: number): number[];
|
|
13
|
+
export declare const SPECTRUM_PHOTON_DISTRIBUTION = 3;
|
|
14
|
+
/** Maps a unit random number to a wavelength and its probability density. */
|
|
15
|
+
export declare function spectrumSample(distribution: number, u: number): {
|
|
16
|
+
wavelength: number;
|
|
17
|
+
pdf: number;
|
|
18
|
+
};
|
|
19
|
+
export declare function spectrumIorWavelength(wavelength: number): number;
|
|
20
|
+
export declare const spectrumWgsl: string;
|
|
21
|
+
export declare const spectrumGlsl: string;
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Continuous wavelength sampling shared by camera paths and caustic photons.
|
|
3
|
+
*
|
|
4
|
+
* CIE 1931 matching functions use the multi-lobe fit from Wyman, Sloan and
|
|
5
|
+
* Shirley, "Simple Analytic Approximations to the CIE XYZ Color Matching
|
|
6
|
+
* Functions", JCGT 2(2), 2013. Only the published formula and coefficients are
|
|
7
|
+
* used. Out-of-gamut negatives clamp to zero, and each channel is normalized so
|
|
8
|
+
* that a uniform wavelength keeps white light white.
|
|
9
|
+
*/
|
|
10
|
+
export const SPECTRUM_WAVELENGTH_MIN = 400;
|
|
11
|
+
export const SPECTRUM_WAVELENGTH_RANGE = 300;
|
|
12
|
+
// Amplitude, mean, sigma below the mean and sigma above it.
|
|
13
|
+
const XYZ_LOBES = [
|
|
14
|
+
[[1.056, 599.8, 37.9, 31.0], [0.362, 442.0, 16.0, 26.7], [-0.065, 501.1, 20.4, 26.2]],
|
|
15
|
+
[[0.821, 568.8, 46.9, 40.5], [0.286, 530.9, 16.3, 31.1]],
|
|
16
|
+
[[1.217, 437.0, 11.8, 36.0], [0.681, 459.0, 26.0, 13.8]]
|
|
17
|
+
];
|
|
18
|
+
// Linear sRGB primaries, D65.
|
|
19
|
+
const XYZ_TO_RGB = [
|
|
20
|
+
[3.2406, -1.5372, -0.4986],
|
|
21
|
+
[-0.9689, 1.8758, 0.0415],
|
|
22
|
+
[0.0557, -0.204, 1.057]
|
|
23
|
+
];
|
|
24
|
+
function unnormalizedRgb(wavelength) {
|
|
25
|
+
const xyz = XYZ_LOBES.map((lobes) => {
|
|
26
|
+
let sum = 0;
|
|
27
|
+
for (const lobe of lobes) {
|
|
28
|
+
const t = (wavelength - lobe[1]) / (wavelength < lobe[1] ? lobe[2] : lobe[3]);
|
|
29
|
+
sum += lobe[0] * Math.exp(-0.5 * t * t);
|
|
30
|
+
}
|
|
31
|
+
return sum;
|
|
32
|
+
});
|
|
33
|
+
return XYZ_TO_RGB.map((row) => Math.max(0, row[0] * xyz[0] + row[1] * xyz[1] + row[2] * xyz[2]));
|
|
34
|
+
}
|
|
35
|
+
function channelScale() {
|
|
36
|
+
const steps = 3000;
|
|
37
|
+
const sum = [0, 0, 0];
|
|
38
|
+
for (let i = 0; i < steps; i++) {
|
|
39
|
+
const rgb = unnormalizedRgb(SPECTRUM_WAVELENGTH_MIN + (SPECTRUM_WAVELENGTH_RANGE * (i + 0.5)) / steps);
|
|
40
|
+
for (let c = 0; c < 3; c++)
|
|
41
|
+
sum[c] += rgb[c] / steps;
|
|
42
|
+
}
|
|
43
|
+
// Rounded so JavaScript and native builds generate identical shader text.
|
|
44
|
+
return sum.map((mean) => Number((1 / mean).toFixed(6)));
|
|
45
|
+
}
|
|
46
|
+
const SCALE = channelScale();
|
|
47
|
+
export function spectrumRgb(wavelength) {
|
|
48
|
+
return unnormalizedRgb(wavelength).map((value, c) => value * SCALE[c]);
|
|
49
|
+
}
|
|
50
|
+
// Inverse CDFs in 5 nm bins: one per RGB channel for camera paths, and r+g+b for
|
|
51
|
+
// photons. Narrow bins keep each sampled response close to the fit.
|
|
52
|
+
const SAMPLE_BINS = 60;
|
|
53
|
+
const SAMPLE_BIN_WIDTH = SPECTRUM_WAVELENGTH_RANGE / SAMPLE_BINS;
|
|
54
|
+
export const SPECTRUM_PHOTON_DISTRIBUTION = 3;
|
|
55
|
+
function sampleCdfs() {
|
|
56
|
+
const substeps = 20;
|
|
57
|
+
const cdfs = [];
|
|
58
|
+
for (let distribution = 0; distribution <= SPECTRUM_PHOTON_DISTRIBUTION; distribution++) {
|
|
59
|
+
const cdf = [0];
|
|
60
|
+
for (let bin = 0; bin < SAMPLE_BINS; bin++) {
|
|
61
|
+
let mass = 0;
|
|
62
|
+
for (let i = 0; i < substeps; i++) {
|
|
63
|
+
const rgb = spectrumRgb(SPECTRUM_WAVELENGTH_MIN + (bin + (i + 0.5) / substeps) * SAMPLE_BIN_WIDTH);
|
|
64
|
+
mass += distribution === SPECTRUM_PHOTON_DISTRIBUTION ? rgb[0] + rgb[1] + rgb[2] : rgb[distribution];
|
|
65
|
+
}
|
|
66
|
+
cdf.push(cdf[bin] + mass);
|
|
67
|
+
}
|
|
68
|
+
for (const value of cdf)
|
|
69
|
+
cdfs.push(Number((value / cdf[SAMPLE_BINS]).toFixed(7)));
|
|
70
|
+
}
|
|
71
|
+
return cdfs;
|
|
72
|
+
}
|
|
73
|
+
const SAMPLE_CDFS = sampleCdfs();
|
|
74
|
+
/** Maps a unit random number to a wavelength and its probability density. */
|
|
75
|
+
export function spectrumSample(distribution, u) {
|
|
76
|
+
const first = distribution * (SAMPLE_BINS + 1);
|
|
77
|
+
let low = 0;
|
|
78
|
+
let high = SAMPLE_BINS;
|
|
79
|
+
while (high - low > 1) {
|
|
80
|
+
const middle = (low + high) >> 1;
|
|
81
|
+
if (SAMPLE_CDFS[first + middle] <= u)
|
|
82
|
+
low = middle;
|
|
83
|
+
else
|
|
84
|
+
high = middle;
|
|
85
|
+
}
|
|
86
|
+
const mass = SAMPLE_CDFS[first + low + 1] - SAMPLE_CDFS[first + low];
|
|
87
|
+
return {
|
|
88
|
+
wavelength: SPECTRUM_WAVELENGTH_MIN + SAMPLE_BIN_WIDTH * (low + (u - SAMPLE_CDFS[first + low]) / mass),
|
|
89
|
+
pdf: mass / SAMPLE_BIN_WIDTH
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
// Cauchy IOR grows quickly at short wavelengths and strong dispersion scales turn
|
|
93
|
+
// violet light into total internal reflection. Below 500 nm the refracting
|
|
94
|
+
// wavelength eases toward 475 nm, while color still follows the sampled wavelength.
|
|
95
|
+
const IOR_KNEE = 500;
|
|
96
|
+
const IOR_KNEE_WIDTH = 25;
|
|
97
|
+
export function spectrumIorWavelength(wavelength) {
|
|
98
|
+
if (wavelength >= IOR_KNEE)
|
|
99
|
+
return wavelength;
|
|
100
|
+
return IOR_KNEE - IOR_KNEE_WIDTH * (1 - Math.exp((wavelength - IOR_KNEE) / IOR_KNEE_WIDTH));
|
|
101
|
+
}
|
|
102
|
+
const CDF_LITERALS = SAMPLE_CDFS.map((value) => value.toFixed(7)).join(',');
|
|
103
|
+
const lobeSum = (lobes) => lobes.map((lobe) => `${lobe[0]}f*spectrumLobe(wavelength,${lobe[1]}f,${lobe[2]}f,${lobe[3]}f)`).join('+');
|
|
104
|
+
export const spectrumWgsl = /* wgsl */ `
|
|
105
|
+
fn spectrumLobe(wavelength:f32,mean:f32,below:f32,above:f32)->f32 {
|
|
106
|
+
let t=(wavelength-mean)/select(above,below,wavelength<mean);
|
|
107
|
+
return exp(-0.5*t*t);
|
|
108
|
+
}
|
|
109
|
+
fn spectrumRgb(wavelength:f32)->vec3f {
|
|
110
|
+
let xyz=vec3f(${XYZ_LOBES.map(lobeSum).join(',')});
|
|
111
|
+
let rgb=mat3x3f(${[0, 1, 2].map((c) => XYZ_TO_RGB.map((row) => `${row[c]}f`).join(',')).join(',')})*xyz;
|
|
112
|
+
return max(rgb,vec3f(0.0))*vec3f(${SCALE.map((s) => `${s}f`).join(',')});
|
|
113
|
+
}
|
|
114
|
+
fn spectrumIorWavelength(wavelength:f32)->f32 {
|
|
115
|
+
if(wavelength>=${IOR_KNEE}.0) { return wavelength; }
|
|
116
|
+
return ${IOR_KNEE}.0-${IOR_KNEE_WIDTH}.0*(1.0-exp((wavelength-${IOR_KNEE}.0)/${IOR_KNEE_WIDTH}.0));
|
|
117
|
+
}
|
|
118
|
+
const SPECTRUM_CDF=array<f32,${(SAMPLE_BINS + 1) * 4}>(${CDF_LITERALS});
|
|
119
|
+
fn spectrumSample(distribution:u32,u:f32,pdf:ptr<function,f32>)->f32 {
|
|
120
|
+
let first=distribution*${SAMPLE_BINS + 1}u;
|
|
121
|
+
var low=0u;
|
|
122
|
+
var high=${SAMPLE_BINS}u;
|
|
123
|
+
while(high-low>1u) {
|
|
124
|
+
let middle=(low+high)/2u;
|
|
125
|
+
if(SPECTRUM_CDF[first+middle]<=u) { low=middle; } else { high=middle; }
|
|
126
|
+
}
|
|
127
|
+
let mass=SPECTRUM_CDF[first+low+1u]-SPECTRUM_CDF[first+low];
|
|
128
|
+
*pdf=mass/${SAMPLE_BIN_WIDTH}.0;
|
|
129
|
+
return ${SPECTRUM_WAVELENGTH_MIN}.0+${SAMPLE_BIN_WIDTH}.0*(f32(low)+(u-SPECTRUM_CDF[first+low])/mass);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
fn cU(channel:u32,u:f32)->f32 {
|
|
133
|
+
var pdf=0.0;
|
|
134
|
+
return spectrumIorWavelength(spectrumSample(channel,u,&pdf));
|
|
135
|
+
}
|
|
136
|
+
`;
|
|
137
|
+
export const spectrumGlsl = /* glsl */ `
|
|
138
|
+
const float SPECTRUM_CDF[${(SAMPLE_BINS + 1) * 4}]=float[${(SAMPLE_BINS + 1) * 4}](${CDF_LITERALS});
|
|
139
|
+
|
|
140
|
+
float cU(int channel,float u) {
|
|
141
|
+
int first=channel*${SAMPLE_BINS + 1};
|
|
142
|
+
int low=0;
|
|
143
|
+
int high=${SAMPLE_BINS};
|
|
144
|
+
while(high-low>1) {
|
|
145
|
+
int middle=(low+high)/2;
|
|
146
|
+
if(SPECTRUM_CDF[first+middle]<=u) { low=middle; } else { high=middle; }
|
|
147
|
+
}
|
|
148
|
+
float start=SPECTRUM_CDF[first+low];
|
|
149
|
+
float wavelength=${SPECTRUM_WAVELENGTH_MIN}.0+${SAMPLE_BIN_WIDTH}.0*(float(low)+(u-start)/(SPECTRUM_CDF[first+low+1]-start));
|
|
150
|
+
if(wavelength>=${IOR_KNEE}.0) { return wavelength; }
|
|
151
|
+
return ${IOR_KNEE}.0-${IOR_KNEE_WIDTH}.0*(1.0-exp((wavelength-${IOR_KNEE}.0)/${IOR_KNEE_WIDTH}.0));
|
|
152
|
+
}
|
|
153
|
+
`;
|
|
154
|
+
//# sourceMappingURL=spectrum.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spectrum.js","sourceRoot":"","sources":["../../src/renderer/spectrum.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Continuous wavelength sampling shared by camera paths and caustic photons.\n *\n * CIE 1931 matching functions use the multi-lobe fit from Wyman, Sloan and\n * Shirley, \"Simple Analytic Approximations to the CIE XYZ Color Matching\n * Functions\", JCGT 2(2), 2013. Only the published formula and coefficients are\n * used. Out-of-gamut negatives clamp to zero, and each channel is normalized so\n * that a uniform wavelength keeps white light white.\n */\nexport const SPECTRUM_WAVELENGTH_MIN = 400;\nexport const SPECTRUM_WAVELENGTH_RANGE = 300;\n\n// Amplitude, mean, sigma below the mean and sigma above it.\nconst XYZ_LOBES: number[][][] = [\n [[1.056, 599.8, 37.9, 31.0], [0.362, 442.0, 16.0, 26.7], [-0.065, 501.1, 20.4, 26.2]],\n [[0.821, 568.8, 46.9, 40.5], [0.286, 530.9, 16.3, 31.1]],\n [[1.217, 437.0, 11.8, 36.0], [0.681, 459.0, 26.0, 13.8]]\n];\n// Linear sRGB primaries, D65.\nconst XYZ_TO_RGB: number[][] = [\n [3.2406, -1.5372, -0.4986],\n [-0.9689, 1.8758, 0.0415],\n [0.0557, -0.204, 1.057]\n];\n\nfunction unnormalizedRgb(wavelength: number): number[] {\n const xyz = XYZ_LOBES.map((lobes) => {\n let sum = 0;\n for (const lobe of lobes) {\n const t = (wavelength - lobe[1]) / (wavelength < lobe[1] ? lobe[2] : lobe[3]);\n sum += lobe[0] * Math.exp(-0.5 * t * t);\n }\n return sum;\n });\n return XYZ_TO_RGB.map((row) => Math.max(0, row[0] * xyz[0] + row[1] * xyz[1] + row[2] * xyz[2]));\n}\n\nfunction channelScale(): number[] {\n const steps = 3000;\n const sum = [0, 0, 0];\n for (let i = 0; i < steps; i++) {\n const rgb = unnormalizedRgb(SPECTRUM_WAVELENGTH_MIN + (SPECTRUM_WAVELENGTH_RANGE * (i + 0.5)) / steps);\n for (let c = 0; c < 3; c++) sum[c] += rgb[c] / steps;\n }\n // Rounded so JavaScript and native builds generate identical shader text.\n return sum.map((mean) => Number((1 / mean).toFixed(6)));\n}\nconst SCALE = channelScale();\n\nexport function spectrumRgb(wavelength: number): number[] {\n return unnormalizedRgb(wavelength).map((value, c) => value * SCALE[c]);\n}\n\n// Inverse CDFs in 5 nm bins: one per RGB channel for camera paths, and r+g+b for\n// photons. Narrow bins keep each sampled response close to the fit.\nconst SAMPLE_BINS = 60;\nconst SAMPLE_BIN_WIDTH = SPECTRUM_WAVELENGTH_RANGE / SAMPLE_BINS;\nexport const SPECTRUM_PHOTON_DISTRIBUTION = 3;\nfunction sampleCdfs(): number[] {\n const substeps = 20;\n const cdfs: number[] = [];\n for (let distribution = 0; distribution <= SPECTRUM_PHOTON_DISTRIBUTION; distribution++) {\n const cdf = [0];\n for (let bin = 0; bin < SAMPLE_BINS; bin++) {\n let mass = 0;\n for (let i = 0; i < substeps; i++) {\n const rgb = spectrumRgb(SPECTRUM_WAVELENGTH_MIN + (bin + (i + 0.5) / substeps) * SAMPLE_BIN_WIDTH);\n mass += distribution === SPECTRUM_PHOTON_DISTRIBUTION ? rgb[0] + rgb[1] + rgb[2] : rgb[distribution];\n }\n cdf.push(cdf[bin] + mass);\n }\n for (const value of cdf) cdfs.push(Number((value / cdf[SAMPLE_BINS]).toFixed(7)));\n }\n return cdfs;\n}\nconst SAMPLE_CDFS = sampleCdfs();\n\n/** Maps a unit random number to a wavelength and its probability density. */\nexport function spectrumSample(distribution: number, u: number) {\n const first = distribution * (SAMPLE_BINS + 1);\n let low = 0;\n let high = SAMPLE_BINS;\n while (high - low > 1) {\n const middle = (low + high) >> 1;\n if (SAMPLE_CDFS[first + middle] <= u) low = middle;\n else high = middle;\n }\n const mass = SAMPLE_CDFS[first + low + 1] - SAMPLE_CDFS[first + low];\n return {\n wavelength: SPECTRUM_WAVELENGTH_MIN + SAMPLE_BIN_WIDTH * (low + (u - SAMPLE_CDFS[first + low]) / mass),\n pdf: mass / SAMPLE_BIN_WIDTH\n };\n}\n\n// Cauchy IOR grows quickly at short wavelengths and strong dispersion scales turn\n// violet light into total internal reflection. Below 500 nm the refracting\n// wavelength eases toward 475 nm, while color still follows the sampled wavelength.\nconst IOR_KNEE = 500;\nconst IOR_KNEE_WIDTH = 25;\n\nexport function spectrumIorWavelength(wavelength: number) {\n if (wavelength >= IOR_KNEE) return wavelength;\n return IOR_KNEE - IOR_KNEE_WIDTH * (1 - Math.exp((wavelength - IOR_KNEE) / IOR_KNEE_WIDTH));\n}\n\nconst CDF_LITERALS = SAMPLE_CDFS.map((value) => value.toFixed(7)).join(',');\nconst lobeSum = (lobes: number[][]) =>\n lobes.map((lobe) => `${lobe[0]}f*spectrumLobe(wavelength,${lobe[1]}f,${lobe[2]}f,${lobe[3]}f)`).join('+');\n\nexport const spectrumWgsl = /* wgsl */ `\nfn spectrumLobe(wavelength:f32,mean:f32,below:f32,above:f32)->f32 {\n let t=(wavelength-mean)/select(above,below,wavelength<mean);\n return exp(-0.5*t*t);\n}\nfn spectrumRgb(wavelength:f32)->vec3f {\n let xyz=vec3f(${XYZ_LOBES.map(lobeSum).join(',')});\n let rgb=mat3x3f(${[0, 1, 2].map((c) => XYZ_TO_RGB.map((row) => `${row[c]}f`).join(',')).join(',')})*xyz;\n return max(rgb,vec3f(0.0))*vec3f(${SCALE.map((s) => `${s}f`).join(',')});\n}\nfn spectrumIorWavelength(wavelength:f32)->f32 {\n if(wavelength>=${IOR_KNEE}.0) { return wavelength; }\n return ${IOR_KNEE}.0-${IOR_KNEE_WIDTH}.0*(1.0-exp((wavelength-${IOR_KNEE}.0)/${IOR_KNEE_WIDTH}.0));\n}\nconst SPECTRUM_CDF=array<f32,${(SAMPLE_BINS + 1) * 4}>(${CDF_LITERALS});\nfn spectrumSample(distribution:u32,u:f32,pdf:ptr<function,f32>)->f32 {\n let first=distribution*${SAMPLE_BINS + 1}u;\n var low=0u;\n var high=${SAMPLE_BINS}u;\n while(high-low>1u) {\n let middle=(low+high)/2u;\n if(SPECTRUM_CDF[first+middle]<=u) { low=middle; } else { high=middle; }\n }\n let mass=SPECTRUM_CDF[first+low+1u]-SPECTRUM_CDF[first+low];\n *pdf=mass/${SAMPLE_BIN_WIDTH}.0;\n return ${SPECTRUM_WAVELENGTH_MIN}.0+${SAMPLE_BIN_WIDTH}.0*(f32(low)+(u-SPECTRUM_CDF[first+low])/mass);\n}\n// Refracting wavelength of a camera path that carries one RGB channel.\nfn spectrumCameraWavelength(channel:u32,u:f32)->f32 {\n var pdf=0.0;\n return spectrumIorWavelength(spectrumSample(channel,u,&pdf));\n}\n`;\n\nexport const spectrumGlsl = /* glsl */ `\nconst float SPECTRUM_CDF[${(SAMPLE_BINS + 1) * 4}]=float[${(SAMPLE_BINS + 1) * 4}](${CDF_LITERALS});\n// Refracting wavelength of a camera path that carries one RGB channel.\nfloat spectrumCameraWavelength(int channel,float u) {\n int first=channel*${SAMPLE_BINS + 1};\n int low=0;\n int high=${SAMPLE_BINS};\n while(high-low>1) {\n int middle=(low+high)/2;\n if(SPECTRUM_CDF[first+middle]<=u) { low=middle; } else { high=middle; }\n }\n float start=SPECTRUM_CDF[first+low];\n float wavelength=${SPECTRUM_WAVELENGTH_MIN}.0+${SAMPLE_BIN_WIDTH}.0*(float(low)+(u-start)/(SPECTRUM_CDF[first+low+1]-start));\n if(wavelength>=${IOR_KNEE}.0) { return wavelength; }\n return ${IOR_KNEE}.0-${IOR_KNEE_WIDTH}.0*(1.0-exp((wavelength-${IOR_KNEE}.0)/${IOR_KNEE_WIDTH}.0));\n}\n`;\n"]}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type TextureState from '../scene/TextureState.js';
|
|
2
|
+
export declare const DEFAULT_MAX_TEXTURE_ARRAY_BYTES: number;
|
|
3
|
+
export interface MaterialTableOptions {
|
|
4
|
+
maxTextureArrayBytes?: number;
|
|
5
|
+
maxTextureArrayLayers?: number;
|
|
6
|
+
maxTextureDimension2D?: number;
|
|
7
|
+
}
|
|
8
|
+
export interface TextureAtlasStats {
|
|
9
|
+
estimatedBytes: number;
|
|
10
|
+
height: number;
|
|
11
|
+
layers: number;
|
|
12
|
+
packTimeMs: number;
|
|
13
|
+
scale: number;
|
|
14
|
+
sourcePixels: number;
|
|
15
|
+
textureCount: number;
|
|
16
|
+
width: number;
|
|
17
|
+
}
|
|
18
|
+
export interface AtlasPlacement {
|
|
19
|
+
height: number;
|
|
20
|
+
index: number;
|
|
21
|
+
layer: number;
|
|
22
|
+
width: number;
|
|
23
|
+
x: number;
|
|
24
|
+
y: number;
|
|
25
|
+
}
|
|
26
|
+
interface AtlasShelf {
|
|
27
|
+
height: number;
|
|
28
|
+
x: number;
|
|
29
|
+
y: number;
|
|
30
|
+
}
|
|
31
|
+
interface AtlasPage {
|
|
32
|
+
nextY: number;
|
|
33
|
+
placements: AtlasPlacement[];
|
|
34
|
+
shelves: AtlasShelf[];
|
|
35
|
+
}
|
|
36
|
+
export declare function planTextureAtlas(textures: TextureState[], mapColorLinear: number[], options?: MaterialTableOptions, floatStorage?: boolean): {
|
|
37
|
+
pages: AtlasPage[];
|
|
38
|
+
placements: AtlasPlacement[];
|
|
39
|
+
width: number;
|
|
40
|
+
height: number;
|
|
41
|
+
floatStorage: boolean;
|
|
42
|
+
bytesPerPixel: number;
|
|
43
|
+
mapInfo: number[];
|
|
44
|
+
mapTransform: number[];
|
|
45
|
+
mapWrap: number[];
|
|
46
|
+
mapUvChannel: number[];
|
|
47
|
+
mapColorLinear: number[];
|
|
48
|
+
stats: {
|
|
49
|
+
estimatedBytes: number;
|
|
50
|
+
height: number;
|
|
51
|
+
layers: number;
|
|
52
|
+
packTimeMs: number;
|
|
53
|
+
scale: number;
|
|
54
|
+
sourcePixels: number;
|
|
55
|
+
textureCount: number;
|
|
56
|
+
width: number;
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
export type TextureAtlasPlan = ReturnType<typeof planTextureAtlas>;
|
|
60
|
+
export {};
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { textureWrapIndex } from '../scene/TextureState.js';
|
|
2
|
+
export const DEFAULT_MAX_TEXTURE_ARRAY_BYTES = 384 * 1024 * 1024;
|
|
3
|
+
/**
|
|
4
|
+
* Packs material textures into a small 2D-array atlas.
|
|
5
|
+
*
|
|
6
|
+
* The input rectangles are sorted from tallest/largest to smallest, then
|
|
7
|
+
* placed with a shelf allocator. Each atlas layer contains horizontal shelves;
|
|
8
|
+
* a texture is inserted into the first shelf with enough remaining width, or a
|
|
9
|
+
* new shelf is opened below the existing ones. A new array layer is allocated
|
|
10
|
+
* only when none of the current layers has enough room.
|
|
11
|
+
*
|
|
12
|
+
* `makeTextureArray` first tries this packing at full resolution. If the result
|
|
13
|
+
* exceeds the adapter layer limit or the configured memory budget, it performs
|
|
14
|
+
* a binary search for the largest uniform scale that fits. This preserves full
|
|
15
|
+
* resolution whenever packing alone is sufficient and degrades predictably on
|
|
16
|
+
* constrained hardware.
|
|
17
|
+
*
|
|
18
|
+
* The returned placements keep the original logical texture indices. Shaders
|
|
19
|
+
* use per-texture atlas metadata instead of treating the logical index as the
|
|
20
|
+
* physical array layer.
|
|
21
|
+
*/
|
|
22
|
+
function packTextureAtlas(textures, pageSize, scale) {
|
|
23
|
+
const pages = [];
|
|
24
|
+
const placements = new Array(textures.length);
|
|
25
|
+
const items = textures
|
|
26
|
+
.map((texture, index) => ({
|
|
27
|
+
height: Math.max(1, Math.floor(texture.image.height * scale)),
|
|
28
|
+
index,
|
|
29
|
+
width: Math.max(1, Math.floor(texture.image.width * scale))
|
|
30
|
+
}))
|
|
31
|
+
.sort((a, b) => b.height - a.height || b.width - a.width);
|
|
32
|
+
for (const item of items) {
|
|
33
|
+
let placement;
|
|
34
|
+
for (let layer = 0; layer < pages.length && !placement; layer++) {
|
|
35
|
+
const page = pages[layer];
|
|
36
|
+
for (const shelf of page.shelves) {
|
|
37
|
+
if (item.height <= shelf.height &&
|
|
38
|
+
shelf.x + item.width <= pageSize) {
|
|
39
|
+
placement = {
|
|
40
|
+
height: item.height, index: item.index, width: item.width,
|
|
41
|
+
layer,
|
|
42
|
+
x: shelf.x,
|
|
43
|
+
y: shelf.y
|
|
44
|
+
};
|
|
45
|
+
shelf.x += item.width;
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (!placement && page.nextY + item.height <= pageSize) {
|
|
50
|
+
placement = {
|
|
51
|
+
height: item.height, index: item.index, width: item.width,
|
|
52
|
+
layer,
|
|
53
|
+
x: 0,
|
|
54
|
+
y: page.nextY
|
|
55
|
+
};
|
|
56
|
+
page.shelves.push({
|
|
57
|
+
height: item.height,
|
|
58
|
+
x: item.width,
|
|
59
|
+
y: page.nextY
|
|
60
|
+
});
|
|
61
|
+
page.nextY += item.height;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (!placement) {
|
|
65
|
+
const layer = pages.length;
|
|
66
|
+
placement = { height: item.height, index: item.index, width: item.width, layer, x: 0, y: 0 };
|
|
67
|
+
pages.push({
|
|
68
|
+
nextY: item.height,
|
|
69
|
+
placements: [],
|
|
70
|
+
shelves: [{ height: item.height, x: item.width, y: 0 }]
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
pages[placement.layer].placements.push(placement);
|
|
74
|
+
placements[item.index] = placement;
|
|
75
|
+
}
|
|
76
|
+
return { pages, placements };
|
|
77
|
+
}
|
|
78
|
+
export function planTextureAtlas(textures, mapColorLinear, options = {}, floatStorage = mapColorLinear.some(value => !!value)) {
|
|
79
|
+
const bytesPerPixel = floatStorage ? 8 : 4;
|
|
80
|
+
if (!textures.length)
|
|
81
|
+
return { pages: [], placements: [],
|
|
82
|
+
width: 1, height: 1, floatStorage, bytesPerPixel, mapInfo: [],
|
|
83
|
+
mapTransform: [], mapWrap: [], mapUvChannel: [], mapColorLinear,
|
|
84
|
+
stats: { estimatedBytes: 0, height: 1, layers: 0, packTimeMs: 0, scale: 1,
|
|
85
|
+
sourcePixels: 0, textureCount: 0, width: 1 } };
|
|
86
|
+
const maxTextureArrayLayers = options.maxTextureArrayLayers ?? Infinity;
|
|
87
|
+
const maxTextureDimension2D = options.maxTextureDimension2D ?? Infinity;
|
|
88
|
+
const maxTextureArrayBytes = options.maxTextureArrayBytes ?? DEFAULT_MAX_TEXTURE_ARRAY_BYTES;
|
|
89
|
+
const sourcePixels = textures.reduce((sum, texture) => sum + texture.image.width * texture.image.height, 0);
|
|
90
|
+
const maxSourceDimension = textures.reduce((max, texture) => Math.max(max, texture.image.width, texture.image.height), 1);
|
|
91
|
+
const maxPageSizeFromBudget = Math.max(1, Math.floor(Math.sqrt(maxTextureArrayBytes / bytesPerPixel)));
|
|
92
|
+
const pageSize = Math.max(1, Math.floor(Math.min(maxSourceDimension, maxTextureDimension2D, maxPageSizeFromBudget)));
|
|
93
|
+
const pageBytes = pageSize * pageSize * bytesPerPixel;
|
|
94
|
+
const maxPageCount = Math.max(1, Math.min(maxTextureArrayLayers, Math.floor(maxTextureArrayBytes / pageBytes)));
|
|
95
|
+
const maxScale = Math.min(1, pageSize / maxSourceDimension);
|
|
96
|
+
let packed = packTextureAtlas(textures, pageSize, maxScale);
|
|
97
|
+
let scale = maxScale;
|
|
98
|
+
if (packed.pages.length > maxPageCount) {
|
|
99
|
+
let low = 0;
|
|
100
|
+
let high = maxScale;
|
|
101
|
+
let bestPacked;
|
|
102
|
+
let bestScale = 0;
|
|
103
|
+
for (let i = 0; i < 14; i++) {
|
|
104
|
+
const candidateScale = (low + high) / 2;
|
|
105
|
+
const candidate = packTextureAtlas(textures, pageSize, candidateScale);
|
|
106
|
+
if (candidate.pages.length <= maxPageCount) {
|
|
107
|
+
low = candidateScale;
|
|
108
|
+
bestScale = candidateScale;
|
|
109
|
+
bestPacked = candidate;
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
high = candidateScale;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (!bestPacked) {
|
|
116
|
+
throw new Error(`Unable to fit ${textures.length} textures into ${maxPageCount} atlas layers.`);
|
|
117
|
+
}
|
|
118
|
+
packed = bestPacked;
|
|
119
|
+
scale = bestScale;
|
|
120
|
+
}
|
|
121
|
+
const atlasWidth = packed.placements.reduce((max, placement) => Math.max(max, placement.x + placement.width), 1);
|
|
122
|
+
const atlasHeight = packed.placements.reduce((max, placement) => Math.max(max, placement.y + placement.height), 1);
|
|
123
|
+
// mapInfo = [uvScale.x, uvScale.y, layer + uvOffset.x, uvOffset.y].
|
|
124
|
+
// Packing layer and X offset into one float keeps the shader metadata to one
|
|
125
|
+
// vec4 per logical texture; floor(z) restores the layer and fract(z) the X.
|
|
126
|
+
const mapInfo = packed.placements.flatMap((placement) => {
|
|
127
|
+
const offsetX = (placement.x + 0.5) / atlasWidth;
|
|
128
|
+
const offsetY = (placement.y + 0.5) / atlasHeight;
|
|
129
|
+
return [
|
|
130
|
+
Math.max(placement.width - 1, 0) / atlasWidth,
|
|
131
|
+
Math.max(placement.height - 1, 0) / atlasHeight,
|
|
132
|
+
placement.layer + offsetX,
|
|
133
|
+
offsetY
|
|
134
|
+
];
|
|
135
|
+
});
|
|
136
|
+
return { pages: packed.pages, placements: packed.placements, width: atlasWidth, height: atlasHeight,
|
|
137
|
+
floatStorage, bytesPerPixel, mapInfo,
|
|
138
|
+
mapTransform: textures.flatMap(texture => [texture.uvScale[0], texture.uvScale[1], texture.uvOffset[0], texture.uvOffset[1]]),
|
|
139
|
+
mapWrap: textures.flatMap(texture => [textureWrapIndex(texture.wrapS), textureWrapIndex(texture.wrapT)]),
|
|
140
|
+
mapUvChannel: textures.map(texture => texture.uvChannel), mapColorLinear,
|
|
141
|
+
stats: { estimatedBytes: atlasWidth * atlasHeight * packed.pages.length * bytesPerPixel,
|
|
142
|
+
height: atlasHeight, layers: packed.pages.length, packTimeMs: 0, scale, sourcePixels,
|
|
143
|
+
textureCount: textures.length, width: atlasWidth } };
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=textureAtlas.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"textureAtlas.js","sourceRoot":"","sources":["../../src/renderer/textureAtlas.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE5D,MAAM,CAAC,MAAM,+BAA+B,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC;AAwCjE;;;;;;;;;;;;;;;;;;GAkBG;AACH,SAAS,gBAAgB,CACvB,QAAwB,EACxB,QAAgB,EAChB,KAAa;IAEb,MAAM,KAAK,GAAgB,EAAE,CAAC;IAC9B,MAAM,UAAU,GAAG,IAAI,KAAK,CAAiB,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC9D,MAAM,KAAK,GAAG,QAAQ;SACnB,GAAG,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;QACxB,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC;QAC7D,KAAK;QACL,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC;KAC5D,CAAC,CAAC;SACF,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;IAE5D,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,SAAqC,CAAC;QAC1C,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC,MAAM,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,EAAE,CAAC;YAChE,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;YAC1B,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;gBACjC,IACE,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM;oBAC3B,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,IAAI,QAAQ,EAChC,CAAC;oBACD,SAAS,GAAG;wBACV,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK;wBACzD,KAAK;wBACL,CAAC,EAAE,KAAK,CAAC,CAAC;wBACV,CAAC,EAAE,KAAK,CAAC,CAAC;qBACX,CAAC;oBACF,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC;oBACtB,MAAM;gBACR,CAAC;YACH,CAAC;YACD,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,MAAM,IAAI,QAAQ,EAAE,CAAC;gBACvD,SAAS,GAAG;oBACV,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK;oBACzD,KAAK;oBACL,CAAC,EAAE,CAAC;oBACJ,CAAC,EAAE,IAAI,CAAC,KAAK;iBACd,CAAC;gBACF,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;oBAChB,MAAM,EAAE,IAAI,CAAC,MAAM;oBACnB,CAAC,EAAE,IAAI,CAAC,KAAK;oBACb,CAAC,EAAE,IAAI,CAAC,KAAK;iBACd,CAAC,CAAC;gBACH,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC;YAC5B,CAAC;QACH,CAAC;QAED,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC;YAC3B,SAAS,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;YAC7F,KAAK,CAAC,IAAI,CAAC;gBACT,KAAK,EAAE,IAAI,CAAC,MAAM;gBAClB,UAAU,EAAE,EAAE;gBACd,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;aACxD,CAAC,CAAC;QACL,CAAC;QACD,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAClD,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,SAAS,CAAC;IACrC,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;AAC/B,CAAC;AAGD,MAAM,UAAU,gBAAgB,CAAC,QAAwB,EAAE,cAAwB,EAAE,UAAgC,EAAE,EACrH,YAAY,GAAG,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;IACpD,MAAM,aAAa,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3C,IAAI,CAAC,QAAQ,CAAC,MAAM;QAAE,OAAO,EAAE,KAAK,EAAE,EAAiB,EAAE,UAAU,EAAE,EAAsB;YACzF,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,YAAY,EAAE,aAAa,EAAE,OAAO,EAAE,EAAc;YACzE,YAAY,EAAE,EAAc,EAAE,OAAO,EAAE,EAAc,EAAE,YAAY,EAAE,EAAc,EAAE,cAAc;YACnG,KAAK,EAAE,EAAC,cAAc,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC;gBACtE,YAAY,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAC,EAAE,CAAC;IAClD,MAAM,qBAAqB,GAAG,OAAO,CAAC,qBAAqB,IAAI,QAAQ,CAAC;IACxE,MAAM,qBAAqB,GAAG,OAAO,CAAC,qBAAqB,IAAI,QAAQ,CAAC;IACxE,MAAM,oBAAoB,GACxB,OAAO,CAAC,oBAAoB,IAAI,+BAA+B,CAAC;IAClE,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAClC,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,CAAC,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,EAClE,CAAC,CACF,CAAC;IACF,MAAM,kBAAkB,GAAG,QAAQ,CAAC,MAAM,CACxC,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,CACf,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,EAC1D,CAAC,CACF,CAAC;IACF,MAAM,qBAAqB,GAAG,IAAI,CAAC,GAAG,CACpC,CAAC,EACD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,oBAAoB,GAAG,aAAa,CAAC,CAAC,CAC5D,CAAC;IACF,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CACvB,CAAC,EACD,IAAI,CAAC,KAAK,CACR,IAAI,CAAC,GAAG,CACN,kBAAkB,EAClB,qBAAqB,EACrB,qBAAqB,CACtB,CACF,CACF,CAAC;IACF,MAAM,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,aAAa,CAAC;IACtD,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAC3B,CAAC,EACD,IAAI,CAAC,GAAG,CACN,qBAAqB,EACrB,IAAI,CAAC,KAAK,CAAC,oBAAoB,GAAG,SAAS,CAAC,CAC7C,CACF,CAAC;IACF,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,GAAG,kBAAkB,CAAC,CAAC;IAC5D,IAAI,MAAM,GAAG,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC5D,IAAI,KAAK,GAAG,QAAQ,CAAC;IAErB,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,YAAY,EAAE,CAAC;QACvC,IAAI,GAAG,GAAG,CAAC,CAAC;QACZ,IAAI,IAAI,GAAG,QAAQ,CAAC;QACpB,IAAI,UAA2D,CAAC;QAChE,IAAI,SAAS,GAAG,CAAC,CAAC;QAClB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;YAC5B,MAAM,cAAc,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;YACxC,MAAM,SAAS,GAAG,gBAAgB,CAChC,QAAQ,EACR,QAAQ,EACR,cAAc,CACf,CAAC;YACF,IAAI,SAAS,CAAC,KAAK,CAAC,MAAM,IAAI,YAAY,EAAE,CAAC;gBAC3C,GAAG,GAAG,cAAc,CAAC;gBACrB,SAAS,GAAG,cAAc,CAAC;gBAC3B,UAAU,GAAG,SAAS,CAAC;YACzB,CAAC;iBAAM,CAAC;gBACN,IAAI,GAAG,cAAc,CAAC;YACxB,CAAC;QACH,CAAC;QACD,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,MAAM,IAAI,KAAK,CACb,iBAAiB,QAAQ,CAAC,MAAM,kBAAkB,YAAY,gBAAgB,CAC/E,CAAC;QACJ,CAAC;QACD,MAAM,GAAG,UAAU,CAAC;QACpB,KAAK,GAAG,SAAS,CAAC;IACpB,CAAC;IAED,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,SAAS,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;IACjH,MAAM,WAAW,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,SAAS,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IACnH,oEAAoE;IACpE,6EAA6E;IAC7E,4EAA4E;IAC5E,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,EAAE;QACtD,MAAM,OAAO,GAAG,CAAC,SAAS,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,UAAU,CAAC;QACjD,MAAM,OAAO,GAAG,CAAC,SAAS,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,WAAW,CAAC;QAClD,OAAO;YACL,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,UAAU;YAC7C,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,WAAW;YAC/C,SAAS,CAAC,KAAK,GAAG,OAAO;YACzB,OAAO;SACR,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW;QACjG,YAAY,EAAE,aAAa,EAAE,OAAO;QACpC,YAAY,EAAE,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7H,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,gBAAgB,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;QACxG,YAAY,EAAE,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,cAAc;QACxE,KAAK,EAAE,EAAE,cAAc,EAAE,UAAU,GAAG,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,aAAa;YACrF,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,EAAE,KAAK,EAAE,YAAY;YACpF,YAAY,EAAE,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,CAAC;AAC3D,CAAC","sourcesContent":["import type TextureState from '../scene/TextureState.js';\nimport { textureWrapIndex } from '../scene/TextureState.js';\n\nexport const DEFAULT_MAX_TEXTURE_ARRAY_BYTES = 384 * 1024 * 1024;\n\nexport interface MaterialTableOptions {\n maxTextureArrayBytes?: number;\n maxTextureArrayLayers?: number;\n maxTextureDimension2D?: number;\n}\n\nexport interface TextureAtlasStats {\n estimatedBytes: number;\n height: number;\n layers: number;\n packTimeMs: number;\n scale: number;\n sourcePixels: number;\n textureCount: number;\n width: number;\n}\n\nexport interface AtlasPlacement {\n height: number;\n index: number;\n layer: number;\n width: number;\n x: number;\n y: number;\n}\n\ninterface AtlasShelf {\n height: number;\n x: number;\n y: number;\n}\n\ninterface AtlasPage {\n nextY: number;\n placements: AtlasPlacement[];\n shelves: AtlasShelf[];\n}\n\n/**\n * Packs material textures into a small 2D-array atlas.\n *\n * The input rectangles are sorted from tallest/largest to smallest, then\n * placed with a shelf allocator. Each atlas layer contains horizontal shelves;\n * a texture is inserted into the first shelf with enough remaining width, or a\n * new shelf is opened below the existing ones. A new array layer is allocated\n * only when none of the current layers has enough room.\n *\n * `makeTextureArray` first tries this packing at full resolution. If the result\n * exceeds the adapter layer limit or the configured memory budget, it performs\n * a binary search for the largest uniform scale that fits. This preserves full\n * resolution whenever packing alone is sufficient and degrades predictably on\n * constrained hardware.\n *\n * The returned placements keep the original logical texture indices. Shaders\n * use per-texture atlas metadata instead of treating the logical index as the\n * physical array layer.\n */\nfunction packTextureAtlas(\n textures: TextureState[],\n pageSize: number,\n scale: number\n) {\n const pages: AtlasPage[] = [];\n const placements = new Array<AtlasPlacement>(textures.length);\n const items = textures\n .map((texture, index) => ({\n height: Math.max(1, Math.floor(texture.image.height * scale)),\n index,\n width: Math.max(1, Math.floor(texture.image.width * scale))\n }))\n .sort((a, b) => b.height - a.height || b.width - a.width);\n\n for (const item of items) {\n let placement: AtlasPlacement | undefined;\n for (let layer = 0; layer < pages.length && !placement; layer++) {\n const page = pages[layer];\n for (const shelf of page.shelves) {\n if (\n item.height <= shelf.height &&\n shelf.x + item.width <= pageSize\n ) {\n placement = {\n height: item.height, index: item.index, width: item.width,\n layer,\n x: shelf.x,\n y: shelf.y\n };\n shelf.x += item.width;\n break;\n }\n }\n if (!placement && page.nextY + item.height <= pageSize) {\n placement = {\n height: item.height, index: item.index, width: item.width,\n layer,\n x: 0,\n y: page.nextY\n };\n page.shelves.push({\n height: item.height,\n x: item.width,\n y: page.nextY\n });\n page.nextY += item.height;\n }\n }\n\n if (!placement) {\n const layer = pages.length;\n placement = { height: item.height, index: item.index, width: item.width, layer, x: 0, y: 0 };\n pages.push({\n nextY: item.height,\n placements: [],\n shelves: [{ height: item.height, x: item.width, y: 0 }]\n });\n }\n pages[placement.layer].placements.push(placement);\n placements[item.index] = placement;\n }\n\n return { pages, placements };\n}\n\n\nexport function planTextureAtlas(textures: TextureState[], mapColorLinear: number[], options: MaterialTableOptions = {},\n floatStorage = mapColorLinear.some(value => !!value)) {\n const bytesPerPixel = floatStorage ? 8 : 4;\n if (!textures.length) return { pages: [] as AtlasPage[], placements: [] as AtlasPlacement[],\n width: 1, height: 1, floatStorage, bytesPerPixel, mapInfo: [] as number[],\n mapTransform: [] as number[], mapWrap: [] as number[], mapUvChannel: [] as number[], mapColorLinear,\n stats: {estimatedBytes: 0, height: 1, layers: 0, packTimeMs: 0, scale: 1,\n sourcePixels: 0, textureCount: 0, width: 1} };\n const maxTextureArrayLayers = options.maxTextureArrayLayers ?? Infinity;\n const maxTextureDimension2D = options.maxTextureDimension2D ?? Infinity;\n const maxTextureArrayBytes =\n options.maxTextureArrayBytes ?? DEFAULT_MAX_TEXTURE_ARRAY_BYTES;\n const sourcePixels = textures.reduce(\n (sum, texture) => sum + texture.image.width * texture.image.height,\n 0\n );\n const maxSourceDimension = textures.reduce(\n (max, texture) =>\n Math.max(max, texture.image.width, texture.image.height),\n 1\n );\n const maxPageSizeFromBudget = Math.max(\n 1,\n Math.floor(Math.sqrt(maxTextureArrayBytes / bytesPerPixel))\n );\n const pageSize = Math.max(\n 1,\n Math.floor(\n Math.min(\n maxSourceDimension,\n maxTextureDimension2D,\n maxPageSizeFromBudget\n )\n )\n );\n const pageBytes = pageSize * pageSize * bytesPerPixel;\n const maxPageCount = Math.max(\n 1,\n Math.min(\n maxTextureArrayLayers,\n Math.floor(maxTextureArrayBytes / pageBytes)\n )\n );\n const maxScale = Math.min(1, pageSize / maxSourceDimension);\n let packed = packTextureAtlas(textures, pageSize, maxScale);\n let scale = maxScale;\n\n if (packed.pages.length > maxPageCount) {\n let low = 0;\n let high = maxScale;\n let bestPacked: ReturnType<typeof packTextureAtlas> | undefined;\n let bestScale = 0;\n for (let i = 0; i < 14; i++) {\n const candidateScale = (low + high) / 2;\n const candidate = packTextureAtlas(\n textures,\n pageSize,\n candidateScale\n );\n if (candidate.pages.length <= maxPageCount) {\n low = candidateScale;\n bestScale = candidateScale;\n bestPacked = candidate;\n } else {\n high = candidateScale;\n }\n }\n if (!bestPacked) {\n throw new Error(\n `Unable to fit ${textures.length} textures into ${maxPageCount} atlas layers.`\n );\n }\n packed = bestPacked;\n scale = bestScale;\n }\n\n const atlasWidth = packed.placements.reduce((max, placement) => Math.max(max, placement.x + placement.width), 1);\n const atlasHeight = packed.placements.reduce((max, placement) => Math.max(max, placement.y + placement.height), 1);\n // mapInfo = [uvScale.x, uvScale.y, layer + uvOffset.x, uvOffset.y].\n // Packing layer and X offset into one float keeps the shader metadata to one\n // vec4 per logical texture; floor(z) restores the layer and fract(z) the X.\n const mapInfo = packed.placements.flatMap((placement) => {\n const offsetX = (placement.x + 0.5) / atlasWidth;\n const offsetY = (placement.y + 0.5) / atlasHeight;\n return [\n Math.max(placement.width - 1, 0) / atlasWidth,\n Math.max(placement.height - 1, 0) / atlasHeight,\n placement.layer + offsetX,\n offsetY\n ];\n });\n\n return { pages: packed.pages, placements: packed.placements, width: atlasWidth, height: atlasHeight,\n floatStorage, bytesPerPixel, mapInfo,\n mapTransform: textures.flatMap(texture => [texture.uvScale[0], texture.uvScale[1], texture.uvOffset[0], texture.uvOffset[1]]),\n mapWrap: textures.flatMap(texture => [textureWrapIndex(texture.wrapS), textureWrapIndex(texture.wrapT)]),\n mapUvChannel: textures.map(texture => texture.uvChannel), mapColorLinear,\n stats: { estimatedBytes: atlasWidth * atlasHeight * packed.pages.length * bytesPerPixel,\n height: atlasHeight, layers: packed.pages.length, packTimeMs: 0, scale, sourcePixels,\n textureCount: textures.length, width: atlasWidth } };\n}\nexport type TextureAtlasPlan = ReturnType<typeof planTextureAtlas>;\n"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { TextureDataSource } from '../scene/textureData.js';
|
|
2
|
+
import type { AtlasPlacement } from './textureAtlas.js';
|
|
3
|
+
export declare function writeAtlasPixel(data: Uint16Array | Uint8Array, index: number, value: number): void;
|
|
4
|
+
export declare function writeRawAtlasPlacement(data: Uint16Array | Uint8Array, width: number, placement: AtlasPlacement, texture: {
|
|
5
|
+
image: TextureDataSource;
|
|
6
|
+
flipY: boolean;
|
|
7
|
+
}, floatStorage: boolean): void;
|