@meimu/mutracer 0.2.0 → 0.3.1
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.md +222 -0
- package/LICENSES/FidelityFX-FSR.txt +19 -0
- package/LICENSES/pbrt-v4-Apache-2.0.txt +202 -0
- package/README.md +3 -0
- package/THIRD_PARTY_NOTICES.md +18 -4
- package/dist/assets/bvh.worker.js +1 -1
- package/dist/mutracer.umd.js +9328 -7614
- package/docs/api.md +83 -35
- package/docs/caustics.md +80 -0
- package/docs/materials.md +9 -6
- package/docs/performance.md +7 -0
- package/docs/post-processing.md +62 -9
- package/docs/progressive-rendering.md +53 -9
- package/docs/sampling.md +4 -0
- package/docs/technical/acceleration.md +52 -0
- package/docs/technical/aovs.md +79 -0
- package/docs/technical/caustics.md +109 -0
- package/docs/technical/continuous-spectrum.md +122 -0
- package/docs/technical/display-upscale.md +82 -0
- package/docs/technical/openpbr.md +99 -0
- package/docs/technical/pbrt-import.md +168 -0
- package/docs/technical/tiling.md +74 -0
- package/docs/technical/webgl.md +53 -0
- package/docs/updates.md +3 -1
- package/docs/viewer-checklist.md +65 -0
- package/docs/viewer.md +18 -6
- package/lib/Display.d.ts +19 -5
- package/lib/Display.js +10 -7
- package/lib/Display.js.map +1 -1
- package/lib/Engine.d.ts +4 -1
- package/lib/Engine.js +77 -14
- package/lib/Engine.js.map +1 -1
- package/lib/Render.d.ts +81 -24
- package/lib/Render.js +201 -26
- package/lib/Render.js.map +1 -1
- package/lib/RenderLoop.d.ts +7 -3
- package/lib/RenderLoop.js +68 -44
- package/lib/RenderLoop.js.map +1 -1
- package/lib/main.d.ts +4 -2
- package/lib/main.js +1 -0
- package/lib/main.js.map +1 -1
- package/lib/oidn.d.ts +1 -1
- package/lib/renderer/AovPrimitiveCache.js +39 -8
- package/lib/renderer/AovPrimitiveCache.js.map +1 -1
- package/lib/renderer/DisplayPostProcess.d.ts +8 -3
- package/lib/renderer/DisplayPostProcess.js +51 -18
- package/lib/renderer/DisplayPostProcess.js.map +1 -1
- package/lib/renderer/GPUTraceQueue.d.ts +2 -1
- package/lib/renderer/GPUTraceQueue.js +3 -1
- package/lib/renderer/GPUTraceQueue.js.map +1 -1
- package/lib/renderer/MaterialData.js +7 -2
- package/lib/renderer/MaterialData.js.map +1 -1
- package/lib/renderer/RenderingPipeline.d.ts +11 -1
- package/lib/renderer/RenderingPipeline.js.map +1 -1
- package/lib/renderer/TileRender.d.ts +2 -2
- package/lib/renderer/TileRender.js +128 -7
- package/lib/renderer/TileRender.js.map +1 -1
- package/lib/renderer/WGPUAov.d.ts +6 -1
- package/lib/renderer/WGPUAov.js +108 -14
- package/lib/renderer/WGPUAov.js.map +1 -1
- package/lib/renderer/WGPUCanvasSurface.js +12 -1
- package/lib/renderer/WGPUCanvasSurface.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/WGPUEnvMapDistribution.js +19 -19
- package/lib/renderer/WGPUFullQuadPass.js +3 -3
- 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 +122 -28
- package/lib/renderer/WGPURayTraceOutput.js.map +1 -1
- package/lib/renderer/WGPURayTracePass.d.ts +65 -21
- package/lib/renderer/WGPURayTracePass.js +730 -409
- package/lib/renderer/WGPURayTracePass.js.map +1 -1
- package/lib/renderer/WGPURenderingPipeline.js +110 -68
- package/lib/renderer/WGPURenderingPipeline.js.map +1 -1
- package/lib/renderer/WebGLAov.js +3 -3
- package/lib/renderer/WebGLAov.js.map +1 -1
- package/lib/renderer/WebGLFullQuadPass.d.ts +2 -1
- package/lib/renderer/WebGLFullQuadPass.js +10 -0
- package/lib/renderer/WebGLFullQuadPass.js.map +1 -1
- package/lib/renderer/WebGLJNLMDenoiser.js +66 -66
- package/lib/renderer/WebGLJNLMDenoiser.js.map +1 -1
- package/lib/renderer/WebGLRayTraceOutputPass.js +4 -4
- package/lib/renderer/WebGLRayTracePass.d.ts +20 -11
- package/lib/renderer/WebGLRayTracePass.js +157 -116
- package/lib/renderer/WebGLRayTracePass.js.map +1 -1
- package/lib/renderer/WebGLRenderingPipeline.js +17 -14
- package/lib/renderer/WebGLRenderingPipeline.js.map +1 -1
- package/lib/renderer/WebGLSkyBaker.js +60 -60
- package/lib/renderer/accumulationTarget.d.ts +2 -1
- package/lib/renderer/accumulationTarget.js.map +1 -1
- package/lib/renderer/aov.d.ts +13 -1
- package/lib/renderer/aov.js +21 -2
- package/lib/renderer/aov.js.map +1 -1
- package/lib/renderer/aovDisplay.js +2 -2
- package/lib/renderer/aovDisplay.js.map +1 -1
- package/lib/renderer/binnedSahBvh.d.ts +2 -1
- package/lib/renderer/binnedSahBvh.js +24 -17
- package/lib/renderer/binnedSahBvh.js.map +1 -1
- package/lib/renderer/bvhAccel.d.ts +3 -1
- package/lib/renderer/bvhAccel.js +36 -6
- package/lib/renderer/bvhAccel.js.map +1 -1
- package/lib/renderer/cameraUniform.d.ts +1 -1
- package/lib/renderer/cameraUniform.js +6 -2
- package/lib/renderer/cameraUniform.js.map +1 -1
- 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/compactVertices.d.ts +14 -0
- package/lib/renderer/compactVertices.js +124 -0
- package/lib/renderer/compactVertices.js.map +1 -0
- package/lib/renderer/easu.d.ts +11 -0
- package/lib/renderer/easu.js +156 -0
- package/lib/renderer/easu.js.map +1 -0
- package/lib/renderer/geometryUpdateState.d.ts +1 -0
- package/lib/renderer/geometryUpdateState.js.map +1 -1
- package/lib/renderer/geometryUpdates.js +3 -2
- package/lib/renderer/geometryUpdates.js.map +1 -1
- package/lib/renderer/glsl/aovDisplay.frag.js +5 -5
- package/lib/renderer/glsl/aovReflectance.glsl.js +53 -53
- package/lib/renderer/glsl/aovReflectanceSamples.glsl.js +1 -1
- package/lib/renderer/glsl/aovTrace.frag.js +45 -37
- package/lib/renderer/glsl/aovTrace.frag.js.map +1 -1
- package/lib/renderer/glsl/chunks/cameraProjection.glsl.d.ts +2 -0
- package/lib/renderer/glsl/chunks/cameraProjection.glsl.js +16 -0
- package/lib/renderer/glsl/chunks/cameraProjection.glsl.js.map +1 -0
- package/lib/renderer/glsl/chunks/cameraRay.glsl.d.ts +1 -1
- package/lib/renderer/glsl/chunks/cameraRay.glsl.js +9 -16
- package/lib/renderer/glsl/chunks/cameraRay.glsl.js.map +1 -1
- 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 -73
- package/lib/renderer/glsl/chunks/intersect.glsl.js +478 -465
- 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 +156 -153
- package/lib/renderer/glsl/chunks/materialBuffer.glsl.js.map +1 -1
- package/lib/renderer/glsl/chunks/openPbrBsdf.glsl.js +771 -771
- 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 +70 -63
- package/lib/renderer/glsl/chunks/rayTraceCore.glsl.js.map +1 -1
- package/lib/renderer/glsl/chunks/sampleLight.glsl.js +89 -75
- 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 +160 -118
- package/lib/renderer/glsl/chunks/sampleMaterial.glsl.js.map +1 -1
- package/lib/renderer/glsl/chunks/sampleShadowCatcher.glsl.js +14 -14
- package/lib/renderer/glsl/chunks/sampling.glsl.js +88 -91
- 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/spectralPrefix.glsl.d.ts +6 -0
- package/lib/renderer/glsl/chunks/spectralPrefix.glsl.js +47 -0
- package/lib/renderer/glsl/chunks/spectralPrefix.glsl.js.map +1 -0
- package/lib/renderer/glsl/chunks/textureLinear.glsl.js +5 -5
- package/lib/renderer/glsl/chunks/uvProjection.glsl.js +11 -11
- package/lib/renderer/glsl/depthQuery.frag.js +13 -7
- package/lib/renderer/glsl/depthQuery.frag.js.map +1 -1
- package/lib/renderer/glsl/normalizeRayTraceOutput.frag.js +10 -10
- package/lib/renderer/glsl/rayTrace.frag.d.ts +1 -1
- package/lib/renderer/glsl/rayTrace.frag.js +338 -252
- package/lib/renderer/glsl/rayTrace.frag.js.map +1 -1
- package/lib/renderer/glsl/shadowCatcher.frag.js +27 -26
- package/lib/renderer/glsl/shadowCatcher.frag.js.map +1 -1
- package/lib/renderer/glsl/webglPipeline.frag.js +59 -59
- package/lib/renderer/gpuMemory.js +1 -1
- package/lib/renderer/gpuMemory.js.map +1 -1
- package/lib/renderer/lightSampling.d.ts +3 -2
- package/lib/renderer/lightSampling.js +14 -8
- package/lib/renderer/lightSampling.js.map +1 -1
- package/lib/renderer/openPbrEnergyLut.d.ts +2 -1
- package/lib/renderer/openPbrEnergyLut.js +18 -1
- package/lib/renderer/openPbrEnergyLut.js.map +1 -1
- package/lib/renderer/pathLimits.d.ts +5 -4
- package/lib/renderer/pathLimits.js +6 -5
- package/lib/renderer/pathLimits.js.map +1 -1
- package/lib/renderer/prepareMeshBVH.d.ts +2 -0
- package/lib/renderer/prepareMeshBVH.js +5 -3
- package/lib/renderer/prepareMeshBVH.js.map +1 -1
- package/lib/renderer/progressiveScheduler.js +5 -4
- package/lib/renderer/progressiveScheduler.js.map +1 -1
- package/lib/renderer/renderPipeline.d.ts +5 -0
- package/lib/renderer/renderPipeline.js +1 -0
- package/lib/renderer/renderPipeline.js.map +1 -1
- 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 +1 -1
- package/lib/renderer/sceneAssembly.js +4 -3
- package/lib/renderer/sceneAssembly.js.map +1 -1
- package/lib/renderer/sceneChangeDetector.d.ts +1 -1
- package/lib/renderer/sceneChangeDetector.js +3 -1
- package/lib/renderer/sceneChangeDetector.js.map +1 -1
- package/lib/renderer/sceneLayoutSchema.d.ts +2 -0
- package/lib/renderer/sceneLayoutSchema.js +3 -3
- package/lib/renderer/sceneLayoutSchema.js.map +1 -1
- package/lib/renderer/scenePreparation.d.ts +3 -2
- package/lib/renderer/scenePreparation.js +18 -2
- package/lib/renderer/scenePreparation.js.map +1 -1
- package/lib/renderer/scratchSampling.js +6 -6
- 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/staticBvhPreparation.d.ts +9 -0
- package/lib/renderer/staticBvhPreparation.js +8 -2
- package/lib/renderer/staticBvhPreparation.js.map +1 -1
- package/lib/renderer/surfaceHit.d.ts +10 -0
- package/lib/renderer/surfaceHit.js +22 -0
- package/lib/renderer/surfaceHit.js.map +1 -0
- package/lib/renderer/tangentRequirements.d.ts +2 -0
- package/lib/renderer/tangentRequirements.js +7 -0
- package/lib/renderer/tangentRequirements.js.map +1 -0
- package/lib/renderer/textureAtlas.d.ts +4 -0
- package/lib/renderer/textureAtlas.js +48 -2
- package/lib/renderer/textureAtlas.js.map +1 -1
- package/lib/renderer/webgl.js +4 -0
- 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/webglVertexAttributes.d.ts +17 -0
- package/lib/renderer/webglVertexAttributes.js +44 -0
- package/lib/renderer/webglVertexAttributes.js.map +1 -0
- package/lib/renderer/wgpuBindlessSource.js +3 -3
- package/lib/renderer/wgpuMaterialConstants.js +4 -3
- package/lib/renderer/wgpuMaterialConstants.js.map +1 -1
- package/lib/renderer/wgpuSceneUniform.js +2 -2
- package/lib/renderer/wgpuSceneUniform.js.map +1 -1
- package/lib/renderer/wgpuShaderSource.d.ts +22 -0
- package/lib/renderer/wgpuShaderSource.js +3 -1
- package/lib/renderer/wgpuShaderSource.js.map +1 -1
- package/lib/renderer/wgsl/aovCompact.wgsl.d.ts +4 -0
- package/lib/renderer/wgsl/aovCompact.wgsl.js +26 -0
- package/lib/renderer/wgsl/aovCompact.wgsl.js.map +1 -0
- package/lib/renderer/wgsl/aovDisplay.wgsl.js +9 -9
- package/lib/renderer/wgsl/aovReflectance.wgsl.js +55 -55
- package/lib/renderer/wgsl/aovReflectanceSamples.wgsl.js +1 -1
- package/lib/renderer/wgsl/aovResolve.wgsl.d.ts +4 -0
- package/lib/renderer/wgsl/aovResolve.wgsl.js +21 -2
- package/lib/renderer/wgsl/aovResolve.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/aovSnapshot.wgsl.js +2 -2
- package/lib/renderer/wgsl/aovSnapshot.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/aovTrace.wgsl.js +33 -33
- package/lib/renderer/wgsl/aovTraceDisplay.wgsl.d.ts +2 -0
- package/lib/renderer/wgsl/aovTraceDisplay.wgsl.js +56 -0
- package/lib/renderer/wgsl/aovTraceDisplay.wgsl.js.map +1 -0
- package/lib/renderer/wgsl/bloom.wgsl.js +18 -18
- package/lib/renderer/wgsl/causticLight.compute.d.ts +6 -0
- package/lib/renderer/wgsl/causticLight.compute.js +539 -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.js +37 -37
- package/lib/renderer/wgsl/chunks/intersect.wgsl.d.ts +6 -2
- package/lib/renderer/wgsl/chunks/intersect.wgsl.js +634 -620
- package/lib/renderer/wgsl/chunks/intersect.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/chunks/intersectionAlpha.wgsl.d.ts +1 -1
- package/lib/renderer/wgsl/chunks/intersectionAlpha.wgsl.js +23 -21
- package/lib/renderer/wgsl/chunks/intersectionAlpha.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.d.ts +3 -1
- package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.js +77 -74
- package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/chunks/openPbrBsdf.wgsl.js +795 -795
- package/lib/renderer/wgsl/chunks/pdm_displacement.wgsl.js +139 -139
- package/lib/renderer/wgsl/chunks/rand.wgsl.js +3 -3
- package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.d.ts +5 -1
- package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.js +45 -29
- 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 +142 -138
- 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 +228 -189
- 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 +11 -11
- 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 +88 -92
- package/lib/renderer/wgsl/chunks/sampling.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/chunks/sobol.wgsl.js +83 -83
- package/lib/renderer/wgsl/chunks/spectralPrefix.wgsl.d.ts +6 -0
- package/lib/renderer/wgsl/chunks/spectralPrefix.wgsl.js +66 -0
- package/lib/renderer/wgsl/chunks/spectralPrefix.wgsl.js.map +1 -0
- package/lib/renderer/wgsl/chunks/uvProjection.wgsl.js +11 -11
- package/lib/renderer/wgsl/chunks/vertexAttributes.wgsl.d.ts +2 -0
- package/lib/renderer/wgsl/chunks/vertexAttributes.wgsl.js +61 -0
- package/lib/renderer/wgsl/chunks/vertexAttributes.wgsl.js.map +1 -0
- package/lib/renderer/wgsl/compose.frag.wgsl.d.ts +2 -0
- package/lib/renderer/wgsl/compose.frag.wgsl.js +100 -98
- 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.d.ts +1 -1
- package/lib/renderer/wgsl/depthQuery.wgsl.js +12 -3
- package/lib/renderer/wgsl/depthQuery.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/easu.wgsl.d.ts +2 -0
- package/lib/renderer/wgsl/easu.wgsl.js +80 -0
- package/lib/renderer/wgsl/easu.wgsl.js.map +1 -0
- package/lib/renderer/wgsl/easuDetail.wgsl.d.ts +21 -0
- package/lib/renderer/wgsl/easuDetail.wgsl.js +230 -0
- package/lib/renderer/wgsl/easuDetail.wgsl.js.map +1 -0
- package/lib/renderer/wgsl/jnlm.compute.js +74 -74
- package/lib/renderer/wgsl/jnlm.compute.js.map +1 -1
- package/lib/renderer/wgsl/offlineAdaptive.compute.js +26 -26
- package/lib/renderer/wgsl/oidnAuxiliary.wgsl.js +3 -3
- 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.js +64 -64
- package/lib/renderer/wgsl/rayTrace.compute.d.ts +23 -1
- package/lib/renderer/wgsl/rayTrace.compute.js +531 -543
- package/lib/renderer/wgsl/rayTrace.compute.js.map +1 -1
- package/lib/scene/MaterialState.d.ts +2 -2
- package/lib/scene/MaterialState.js +2 -2
- package/lib/scene/MaterialState.js.map +1 -1
- package/lib/scene/Scene.js.map +1 -1
- package/lib/settings/render.d.ts +22 -0
- package/lib/settings/render.js +2 -0
- package/lib/settings/render.js.map +1 -1
- package/lib/util/fromTHREE.js +23 -16
- package/lib/util/fromTHREE.js.map +1 -1
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/lib/version.js.map +1 -1
- package/llms.txt +2 -1
- package/package.json +7 -4
- package/lib/oidnBundledWeights.cdn.d.ts +0 -2
- package/lib/oidnBundledWeights.cdn.js +0 -5
- package/lib/oidnBundledWeights.cdn.js.map +0 -1
- package/lib/renderer/bvh.worker.d.ts +0 -1
- package/lib/renderer/bvh.worker.js +0 -16
- package/lib/renderer/bvh.worker.js.map +0 -1
- package/lib/renderer/bvhWorkerBuild.d.ts +0 -13
- package/lib/renderer/bvhWorkerBuild.js +0 -17
- package/lib/renderer/bvhWorkerBuild.js.map +0 -1
- package/lib/renderer/lightCore.d.ts +0 -12
- package/lib/renderer/lightCore.js +0 -13
- package/lib/renderer/lightCore.js.map +0 -1
- package/lib/renderer/materialCore.d.ts +0 -8
- package/lib/renderer/materialCore.js +0 -9
- package/lib/renderer/materialCore.js.map +0 -1
- package/lib/scene/PixelTexture.d.ts +0 -6
- package/lib/scene/PixelTexture.js +0 -10
- package/lib/scene/PixelTexture.js.map +0 -1
- package/lib/util/studioLighting.d.ts +0 -18
- package/lib/util/studioLighting.js +0 -36
- package/lib/util/studioLighting.js.map +0 -1
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
import { type BvhBuildConfig } from './geometryBvh.js';
|
|
2
2
|
import type Mesh from '../scene/Mesh.js';
|
|
3
3
|
import type { TinyBvhLayout } from '../tinybvh/TinyBvhBuilder.js';
|
|
4
|
+
import { type FlattendBVH } from './bvhAccel.js';
|
|
4
5
|
import { BvhWorkerPool } from './bvhWorkerClient.js';
|
|
6
|
+
import { getMeshBlasInput } from './prepareMeshBVH.js';
|
|
7
|
+
export type StaticBvhCacheInput = ReturnType<typeof getMeshBlasInput>;
|
|
8
|
+
/** Internal application cache. Failures never prevent scene preparation. */
|
|
9
|
+
export interface StaticBvhCache {
|
|
10
|
+
load(input: StaticBvhCacheInput, config: BvhBuildConfig): Promise<FlattendBVH | undefined>;
|
|
11
|
+
store(input: StaticBvhCacheInput, config: BvhBuildConfig, bvh: FlattendBVH): Promise<void>;
|
|
12
|
+
}
|
|
5
13
|
export interface StaticBvhPreparationOptions {
|
|
6
14
|
config?: BvhBuildConfig;
|
|
15
|
+
cache?: StaticBvhCache;
|
|
7
16
|
builder: 'builtin' | 'tinybvh';
|
|
8
17
|
layout: TinyBvhLayout;
|
|
9
18
|
spatialSplits: boolean;
|
|
@@ -83,10 +83,16 @@ export async function prepareStaticBvhs(meshes, options) {
|
|
|
83
83
|
if (!meshBlasSnapshotIsCurrent(mesh, target, snapshot))
|
|
84
84
|
continue;
|
|
85
85
|
const input = getMeshBlasInput(mesh);
|
|
86
|
-
const
|
|
86
|
+
const config = options.config ?? options;
|
|
87
|
+
const cached = options.cache ? await options.cache.load(input, config).catch(() => undefined) : undefined;
|
|
88
|
+
if (options.isCancelled?.() || !meshBlasSnapshotIsCurrent(mesh, target, snapshot))
|
|
89
|
+
continue;
|
|
90
|
+
const bvh = cached ?? await buildWithFallback(input);
|
|
87
91
|
if (!options.isCancelled?.() && meshBlasSnapshotIsCurrent(mesh, target, snapshot)) {
|
|
88
|
-
setGeometryBvh(target, bvh,
|
|
92
|
+
setGeometryBvh(target, bvh, config);
|
|
89
93
|
result.geometryCount++;
|
|
94
|
+
if (!cached)
|
|
95
|
+
await options.cache?.store(input, config, bvh).catch(() => { });
|
|
90
96
|
}
|
|
91
97
|
}
|
|
92
98
|
catch (error) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"staticBvhPreparation.js","sourceRoot":"","sources":["../../src/renderer/staticBvhPreparation.ts"],"names":[],"mappings":"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","sourcesContent":["import { setGeometryBvh, type BvhBuildConfig } from './geometryBvh.js';\nimport type Mesh from '../scene/Mesh.js';\nimport type Geometry from '../scene/Geometry.js';\nimport type { TinyBvhLayout } from '../tinybvh/TinyBvhBuilder.js';\nimport { buildBLAS, type FlattendBVH } from './bvhAccel.js';\nimport {\n buildBvhInWorker, BvhWorkerPool, BvhWorkerUnavailableError, BvhWorkerDisposedError\n} from './bvhWorkerClient.js';\nimport {\n captureMeshBlasSnapshot,\n getMeshBlasInput,\n getPreparedMeshGeometry,\n meshNeedsStaticBvh,\n meshBlasSnapshotIsCurrent\n} from './prepareMeshBVH.js';\n\nexport interface StaticBvhPreparationOptions {\n config?: BvhBuildConfig;\n builder: 'builtin' | 'tinybvh';\n layout: TinyBvhLayout;\n spatialSplits: boolean;\n useWorker: boolean;\n workerPool?: BvhWorkerPool;\n isCancelled?: () => boolean;\n rebuild: boolean;\n onProgress?: (progress: number) => void;\n}\n\nexport interface StaticBvhPreparationResult {\n geometryCount: number;\n bvhTimeMs: number;\n failedMeshes: Mesh[];\n workerUnavailable: boolean;\n tinyBvhUnavailable: boolean;\n}\n\n/** Build static BLASes once per target geometry, preserving old BVHs until writeback. */\nexport async function prepareStaticBvhs(\n meshes: readonly Mesh[], options: StaticBvhPreparationOptions\n): Promise<StaticBvhPreparationResult> {\n const result: StaticBvhPreparationResult = {\n geometryCount: 0, bvhTimeMs: 0, failedMeshes: [],\n workerUnavailable: false, tinyBvhUnavailable: false\n };\n const jobs = new Map<Geometry, {\n mesh: Mesh;\n snapshot: ReturnType<typeof captureMeshBlasSnapshot>;\n }>();\n for (const mesh of meshes) {\n if (!mesh.geometry.position?.array.length || mesh.geometry.dynamic) continue;\n const target = getPreparedMeshGeometry(mesh);\n if (jobs.has(target) || (!meshNeedsStaticBvh(mesh, options.config ?? options) && !options.rebuild)) continue;\n try {\n jobs.set(target, { mesh, snapshot: captureMeshBlasSnapshot(mesh, target) });\n } catch {\n result.failedMeshes.push(mesh);\n }\n }\n const pool = options.useWorker ? options.workerPool ?? new BvhWorkerPool(1) : undefined;\n\n async function build(\n input: ReturnType<typeof getMeshBlasInput>, builder: StaticBvhPreparationOptions['builder'], useWorker: boolean\n ): Promise<FlattendBVH> {\n const { geometry, displacementScale, trianglesDisplacement } = input;\n let bvh: FlattendBVH & { bvhTimeMs?: number };\n if (useWorker) {\n bvh = await buildBvhInWorker(geometry, displacementScale, trianglesDisplacement,\n builder, builder === 'tinybvh' ? options.layout : 'bvh2', options.spatialSplits, pool);\n } else if (builder === 'tinybvh') {\n const { buildTinyBvh } = await import('../tinybvh/TinyBvhBuilder.js');\n bvh = await buildTinyBvh(geometry, displacementScale, trianglesDisplacement,\n options.layout, options.spatialSplits);\n } else {\n const start = performance.now();\n bvh = { ...buildBLAS(geometry, displacementScale, trianglesDisplacement),\n bvhTimeMs: performance.now() - start };\n }\n if (builder === 'tinybvh' && (bvh.builder !== 'tinybvh' || !bvh.buffer.byteLength)) {\n throw new Error('TinyBVH did not build every scene geometry.');\n }\n result.bvhTimeMs += bvh.bvhTimeMs ?? 0;\n return bvh;\n }\n\n async function buildWithFallback(input: ReturnType<typeof getMeshBlasInput>) {\n let builder = options.builder;\n let useWorker = options.useWorker && !result.workerUnavailable;\n for (;;) {\n if (options.isCancelled?.()) throw new BvhWorkerDisposedError();\n try {\n return await build(input, builder, useWorker);\n } catch (error) {\n if (error instanceof BvhWorkerDisposedError) throw error;\n if (error instanceof BvhWorkerUnavailableError && useWorker) {\n result.workerUnavailable = true;\n useWorker = false;\n } else if (builder === 'tinybvh') {\n result.tinyBvhUnavailable = true;\n builder = 'builtin';\n useWorker = options.useWorker && !result.workerUnavailable;\n } else {\n throw error;\n }\n }\n }\n }\n\n let completed = 0;\n // Large BLASes start first to reduce the tail. Only active lanes prepare\n // attributes/displacement inputs and submit geometry to Workers.\n const pending = [...jobs].sort(([a], [b]) =>\n (b.indices?.array.length ?? 0) - (a.indices?.array.length ?? 0));\n let next = 0;\n async function runLane() {\n while (next < pending.length && !options.isCancelled?.()) {\n const [target, { mesh, snapshot }] = pending[next++];\n try {\n if (!meshBlasSnapshotIsCurrent(mesh, target, snapshot)) continue;\n const input = getMeshBlasInput(mesh);\n const bvh = await buildWithFallback(input);\n if (!options.isCancelled?.() && meshBlasSnapshotIsCurrent(mesh, target, snapshot)) {\n setGeometryBvh(target, bvh, options.config ?? options);\n result.geometryCount++;\n }\n } catch (error) {\n if (!(error instanceof BvhWorkerDisposedError)) result.failedMeshes.push(mesh);\n } finally {\n if (!options.isCancelled?.()) {\n // A loading-screen callback must not stop a lane and strand jobs.\n try { options.onProgress?.(++completed / jobs.size); } catch { /* Keep building. */ }\n }\n }\n }\n }\n try {\n await Promise.allSettled(Array.from({ length: Math.min(pool?.size ?? 1, jobs.size) }, runLane));\n } finally {\n if (!options.workerPool) pool?.dispose();\n }\n return result;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"staticBvhPreparation.js","sourceRoot":"","sources":["../../src/renderer/staticBvhPreparation.ts"],"names":[],"mappings":"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","sourcesContent":["import { setGeometryBvh, type BvhBuildConfig } from './geometryBvh.js';\nimport type Mesh from '../scene/Mesh.js';\nimport type Geometry from '../scene/Geometry.js';\nimport type { TinyBvhLayout } from '../tinybvh/TinyBvhBuilder.js';\nimport { buildBLAS, type FlattendBVH } from './bvhAccel.js';\nimport {\n buildBvhInWorker, BvhWorkerPool, BvhWorkerUnavailableError, BvhWorkerDisposedError\n} from './bvhWorkerClient.js';\nimport {\n captureMeshBlasSnapshot,\n getMeshBlasInput,\n getPreparedMeshGeometry,\n meshNeedsStaticBvh,\n meshBlasSnapshotIsCurrent\n} from './prepareMeshBVH.js';\n\nexport type StaticBvhCacheInput = ReturnType<typeof getMeshBlasInput>;\n/** Internal application cache. Failures never prevent scene preparation. */\nexport interface StaticBvhCache {\n load(input: StaticBvhCacheInput, config: BvhBuildConfig): Promise<FlattendBVH | undefined>;\n store(input: StaticBvhCacheInput, config: BvhBuildConfig, bvh: FlattendBVH): Promise<void>;\n}\n\nexport interface StaticBvhPreparationOptions {\n config?: BvhBuildConfig;\n cache?: StaticBvhCache;\n builder: 'builtin' | 'tinybvh';\n layout: TinyBvhLayout;\n spatialSplits: boolean;\n useWorker: boolean;\n workerPool?: BvhWorkerPool;\n isCancelled?: () => boolean;\n rebuild: boolean;\n onProgress?: (progress: number) => void;\n}\n\nexport interface StaticBvhPreparationResult {\n geometryCount: number;\n bvhTimeMs: number;\n failedMeshes: Mesh[];\n workerUnavailable: boolean;\n tinyBvhUnavailable: boolean;\n}\n\n/** Build static BLASes once per target geometry, preserving old BVHs until writeback. */\nexport async function prepareStaticBvhs(\n meshes: readonly Mesh[], options: StaticBvhPreparationOptions\n): Promise<StaticBvhPreparationResult> {\n const result: StaticBvhPreparationResult = {\n geometryCount: 0, bvhTimeMs: 0, failedMeshes: [],\n workerUnavailable: false, tinyBvhUnavailable: false\n };\n const jobs = new Map<Geometry, {\n mesh: Mesh;\n snapshot: ReturnType<typeof captureMeshBlasSnapshot>;\n }>();\n for (const mesh of meshes) {\n if (!mesh.geometry.position?.array.length || mesh.geometry.dynamic) continue;\n const target = getPreparedMeshGeometry(mesh);\n if (jobs.has(target) || (!meshNeedsStaticBvh(mesh, options.config ?? options) && !options.rebuild)) continue;\n try {\n jobs.set(target, { mesh, snapshot: captureMeshBlasSnapshot(mesh, target) });\n } catch {\n result.failedMeshes.push(mesh);\n }\n }\n const pool = options.useWorker ? options.workerPool ?? new BvhWorkerPool(1) : undefined;\n\n async function build(\n input: ReturnType<typeof getMeshBlasInput>, builder: StaticBvhPreparationOptions['builder'], useWorker: boolean\n ): Promise<FlattendBVH> {\n const { geometry, displacementScale, trianglesDisplacement } = input;\n let bvh: FlattendBVH & { bvhTimeMs?: number };\n if (useWorker) {\n bvh = await buildBvhInWorker(geometry, displacementScale, trianglesDisplacement,\n builder, builder === 'tinybvh' ? options.layout : 'bvh2', options.spatialSplits, pool);\n } else if (builder === 'tinybvh') {\n const { buildTinyBvh } = await import('../tinybvh/TinyBvhBuilder.js');\n bvh = await buildTinyBvh(geometry, displacementScale, trianglesDisplacement,\n options.layout, options.spatialSplits);\n } else {\n const start = performance.now();\n bvh = { ...buildBLAS(geometry, displacementScale, trianglesDisplacement),\n bvhTimeMs: performance.now() - start };\n }\n if (builder === 'tinybvh' && (bvh.builder !== 'tinybvh' || !bvh.buffer.byteLength)) {\n throw new Error('TinyBVH did not build every scene geometry.');\n }\n result.bvhTimeMs += bvh.bvhTimeMs ?? 0;\n return bvh;\n }\n\n async function buildWithFallback(input: ReturnType<typeof getMeshBlasInput>) {\n let builder = options.builder;\n let useWorker = options.useWorker && !result.workerUnavailable;\n for (;;) {\n if (options.isCancelled?.()) throw new BvhWorkerDisposedError();\n try {\n return await build(input, builder, useWorker);\n } catch (error) {\n if (error instanceof BvhWorkerDisposedError) throw error;\n if (error instanceof BvhWorkerUnavailableError && useWorker) {\n result.workerUnavailable = true;\n useWorker = false;\n } else if (builder === 'tinybvh') {\n result.tinyBvhUnavailable = true;\n builder = 'builtin';\n useWorker = options.useWorker && !result.workerUnavailable;\n } else {\n throw error;\n }\n }\n }\n }\n\n let completed = 0;\n // Large BLASes start first to reduce the tail. Only active lanes prepare\n // attributes/displacement inputs and submit geometry to Workers.\n const pending = [...jobs].sort(([a], [b]) =>\n (b.indices?.array.length ?? 0) - (a.indices?.array.length ?? 0));\n let next = 0;\n async function runLane() {\n while (next < pending.length && !options.isCancelled?.()) {\n const [target, { mesh, snapshot }] = pending[next++];\n try {\n if (!meshBlasSnapshotIsCurrent(mesh, target, snapshot)) continue;\n const input = getMeshBlasInput(mesh);\n const config = options.config ?? options;\n const cached = options.cache ? await options.cache.load(input, config).catch(() => undefined) : undefined;\n if (options.isCancelled?.() || !meshBlasSnapshotIsCurrent(mesh, target, snapshot)) continue;\n const bvh = cached ?? await buildWithFallback(input);\n if (!options.isCancelled?.() && meshBlasSnapshotIsCurrent(mesh, target, snapshot)) {\n setGeometryBvh(target, bvh, config);\n result.geometryCount++;\n if (!cached) await options.cache?.store(input, config, bvh).catch(() => {});\n }\n } catch (error) {\n if (!(error instanceof BvhWorkerDisposedError)) result.failedMeshes.push(mesh);\n } finally {\n if (!options.isCancelled?.()) {\n // A loading-screen callback must not stop a lane and strand jobs.\n try { options.onProgress?.(++completed / jobs.size); } catch { /* Keep building. */ }\n }\n }\n }\n }\n try {\n await Promise.allSettled(Array.from({ length: Math.min(pool?.size ?? 1, jobs.size) }, runLane));\n } finally {\n if (!options.workerPool) pool?.dispose();\n }\n return result;\n}\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { AovSceneSource } from './aovScene.js';
|
|
2
|
+
import type { FlattendBVH } from './bvhAccel.js';
|
|
3
|
+
/** Internal GPU picking result; IDs refer to the committed source objects. */
|
|
4
|
+
export interface SurfaceHit {
|
|
5
|
+
object: number;
|
|
6
|
+
material: number;
|
|
7
|
+
instance: number;
|
|
8
|
+
}
|
|
9
|
+
/** Numeric 16-bit halves survive both storage buffers and float render targets. */
|
|
10
|
+
export declare function resolveSurfaceHit(source: AovSceneSource, tlas: FlattendBVH, samples: Float32Array): SurfaceHit | null | undefined;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { aovInstanceOrder } from './aovScene.js';
|
|
2
|
+
import { PackedMeshInstances } from './packedMeshInstances.js';
|
|
3
|
+
/** Numeric 16-bit halves survive both storage buffers and float render targets. */
|
|
4
|
+
export function resolveSurfaceHit(source, tlas, samples) {
|
|
5
|
+
const words = samples.subarray(0, 4);
|
|
6
|
+
if (words.length !== 4 || words.some(value => !Number.isInteger(value) || value < 0 || value > 65535))
|
|
7
|
+
return;
|
|
8
|
+
const instance = words[0] + words[1] * 65536 - 1, material = words[2] + words[3] * 65536 - 1;
|
|
9
|
+
if (instance === -1 && material === -1)
|
|
10
|
+
return null;
|
|
11
|
+
const index = aovInstanceOrder(tlas)[instance];
|
|
12
|
+
if (index == null)
|
|
13
|
+
return;
|
|
14
|
+
const instances = source.instances;
|
|
15
|
+
const binding = source.instanceBindings[instances instanceof PackedMeshInstances ? instances.bindingIndices[index] : index];
|
|
16
|
+
const selectedMaterial = source.materials[material];
|
|
17
|
+
if (!binding || !selectedMaterial)
|
|
18
|
+
return;
|
|
19
|
+
return { object: binding.mesh.aovId, material: selectedMaterial.aovId,
|
|
20
|
+
instance: instances instanceof PackedMeshInstances ? instances.localIndices[index] : 0 };
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=surfaceHit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"surfaceHit.js","sourceRoot":"","sources":["../../src/renderer/surfaceHit.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,gBAAgB,EAAC,MAAM,eAAe,CAAC;AAE/C,OAAO,EAAC,mBAAmB,EAAC,MAAM,0BAA0B,CAAC;AAK7D,mFAAmF;AACnF,MAAM,UAAU,iBAAiB,CAAC,MAAsB,EAAE,IAAiB,EAAE,OAAqB;IAChG,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACrC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,KAAK,CAAC;QAAE,OAAO;IAC9G,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;IAC7F,IAAI,QAAQ,KAAK,CAAC,CAAC,IAAI,QAAQ,KAAK,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACpD,MAAM,KAAK,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC/C,IAAI,KAAK,IAAI,IAAI;QAAE,OAAO;IAC1B,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;IACnC,MAAM,OAAO,GAAG,MAAM,CAAC,gBAAgB,CAAC,SAAS,YAAY,mBAAmB,CAAC,CAAC,CAAC,SAAS,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAC5H,MAAM,gBAAgB,GAAG,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IACpD,IAAI,CAAC,OAAO,IAAI,CAAC,gBAAgB;QAAE,OAAO;IAC1C,OAAO,EAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,gBAAgB,CAAC,KAAK;QAClE,QAAQ,EAAE,SAAS,YAAY,mBAAmB,CAAC,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAC,CAAC;AAC5F,CAAC","sourcesContent":["import type {AovSceneSource} from './aovScene.js';\nimport {aovInstanceOrder} from './aovScene.js';\nimport type {FlattendBVH} from './bvhAccel.js';\nimport {PackedMeshInstances} from './packedMeshInstances.js';\n\n/** Internal GPU picking result; IDs refer to the committed source objects. */\nexport interface SurfaceHit {object: number; material: number; instance: number;}\n\n/** Numeric 16-bit halves survive both storage buffers and float render targets. */\nexport function resolveSurfaceHit(source: AovSceneSource, tlas: FlattendBVH, samples: Float32Array): SurfaceHit | null | undefined {\n const words = samples.subarray(0, 4);\n if (words.length !== 4 || words.some(value => !Number.isInteger(value) || value < 0 || value > 65535)) return;\n const instance = words[0] + words[1] * 65536 - 1, material = words[2] + words[3] * 65536 - 1;\n if (instance === -1 && material === -1) return null;\n const index = aovInstanceOrder(tlas)[instance];\n if (index == null) return;\n const instances = source.instances;\n const binding = source.instanceBindings[instances instanceof PackedMeshInstances ? instances.bindingIndices[index] : index];\n const selectedMaterial = source.materials[material];\n if (!binding || !selectedMaterial) return;\n return {object: binding.mesh.aovId, material: selectedMaterial.aovId,\n instance: instances instanceof PackedMeshInstances ? instances.localIndices[index] : 0};\n}\n"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// Both shader families use vertex tangents for anisotropy and coat frames.
|
|
2
|
+
// Base normal maps use triangle UV differentials, independently of this attribute.
|
|
3
|
+
export function materialNeedsVertexTangents(material) {
|
|
4
|
+
return material.specularAnisotropy > 0 || material.coatAnisotropy > 0 ||
|
|
5
|
+
material.coatWeight > 0 && !!material.coatNormalMap;
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=tangentRequirements.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tangentRequirements.js","sourceRoot":"","sources":["../../src/renderer/tangentRequirements.ts"],"names":[],"mappings":"AAEA,2EAA2E;AAC3E,mFAAmF;AACnF,MAAM,UAAU,2BAA2B,CAAC,QAAuB;IACjE,OAAO,QAAQ,CAAC,kBAAkB,GAAG,CAAC,IAAI,QAAQ,CAAC,cAAc,GAAG,CAAC;QACnE,QAAQ,CAAC,UAAU,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC;AACxD,CAAC","sourcesContent":["import type MaterialState from '../scene/MaterialState.js';\n\n// Both shader families use vertex tangents for anisotropy and coat frames.\n// Base normal maps use triangle UV differentials, independently of this attribute.\nexport function materialNeedsVertexTangents(material: MaterialState): boolean {\n return material.specularAnisotropy > 0 || material.coatAnisotropy > 0 ||\n material.coatWeight > 0 && !!material.coatNormalMap;\n}\n"]}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import type TextureState from '../scene/TextureState.js';
|
|
2
2
|
export declare const DEFAULT_MAX_TEXTURE_ARRAY_BYTES: number;
|
|
3
3
|
export interface MaterialTableOptions {
|
|
4
|
+
/** Native binding arrays: retain separate images instead of packing atlas pages. Default false. */
|
|
5
|
+
independentTextures?: boolean;
|
|
6
|
+
textureSource?: (texture: TextureState) => object;
|
|
4
7
|
maxTextureArrayBytes?: number;
|
|
5
8
|
maxTextureArrayLayers?: number;
|
|
6
9
|
maxTextureDimension2D?: number;
|
|
@@ -34,6 +37,7 @@ interface AtlasPage {
|
|
|
34
37
|
shelves: AtlasShelf[];
|
|
35
38
|
}
|
|
36
39
|
export declare function planTextureAtlas(textures: TextureState[], mapColorLinear: number[], options?: MaterialTableOptions, floatStorage?: boolean): {
|
|
40
|
+
independentTextures: boolean;
|
|
37
41
|
pages: AtlasPage[];
|
|
38
42
|
placements: AtlasPlacement[];
|
|
39
43
|
width: number;
|
|
@@ -78,11 +78,57 @@ function packTextureAtlas(textures, pageSize, scale) {
|
|
|
78
78
|
export function planTextureAtlas(textures, mapColorLinear, options = {}, floatStorage = mapColorLinear.some(value => !!value)) {
|
|
79
79
|
const bytesPerPixel = floatStorage ? 8 : 4;
|
|
80
80
|
if (!textures.length)
|
|
81
|
-
return { pages: [], placements: [],
|
|
81
|
+
return { independentTextures: !!options.independentTextures, pages: [], placements: [],
|
|
82
82
|
width: 1, height: 1, floatStorage, bytesPerPixel, mapInfo: [],
|
|
83
83
|
mapTransform: [], mapWrap: [], mapUvChannel: [], mapColorLinear,
|
|
84
84
|
stats: { estimatedBytes: 0, height: 1, layers: 0, packTimeMs: 0, scale: 1,
|
|
85
85
|
sourcePixels: 0, textureCount: 0, width: 1 } };
|
|
86
|
+
if (options.independentTextures) {
|
|
87
|
+
const budget = options.maxTextureArrayBytes ?? DEFAULT_MAX_TEXTURE_ARRAY_BYTES;
|
|
88
|
+
const dimension = options.maxTextureDimension2D ?? Infinity;
|
|
89
|
+
const sources = new Map(), unique = [];
|
|
90
|
+
const layers = textures.map((texture, index) => {
|
|
91
|
+
const source = options.textureSource?.(texture) ?? texture.image;
|
|
92
|
+
let flips = sources.get(source);
|
|
93
|
+
if (!flips) {
|
|
94
|
+
flips = new Map();
|
|
95
|
+
sources.set(source, flips);
|
|
96
|
+
}
|
|
97
|
+
let layer = flips.get(texture.flipY);
|
|
98
|
+
if (layer === undefined) {
|
|
99
|
+
layer = unique.length;
|
|
100
|
+
flips.set(texture.flipY, layer);
|
|
101
|
+
unique.push(index);
|
|
102
|
+
}
|
|
103
|
+
return layer;
|
|
104
|
+
});
|
|
105
|
+
const extents = (scale) => textures.map((texture, index) => ({ index, layer: layers[index], x: 0, y: 0,
|
|
106
|
+
width: Math.max(1, Math.floor(texture.image.width * scale)), height: Math.max(1, Math.floor(texture.image.height * scale)) }));
|
|
107
|
+
const bytes = (items) => unique.reduce((sum, index) => sum + items[index].width * items[index].height * bytesPerPixel, 0);
|
|
108
|
+
if (unique.length * bytesPerPixel > budget)
|
|
109
|
+
throw new Error('Material textures cannot fit the budget even at 1×1.');
|
|
110
|
+
let scale = textures.reduce((s, t) => Math.min(s, dimension / Math.max(t.image.width, t.image.height)), 1);
|
|
111
|
+
if (bytes(extents(scale)) > budget) {
|
|
112
|
+
let low = 0, high = scale;
|
|
113
|
+
for (let i = 0; i < 40; i++) {
|
|
114
|
+
const mid = (low + high) / 2;
|
|
115
|
+
if (bytes(extents(mid)) <= budget)
|
|
116
|
+
low = mid;
|
|
117
|
+
else
|
|
118
|
+
high = mid;
|
|
119
|
+
}
|
|
120
|
+
scale = low;
|
|
121
|
+
}
|
|
122
|
+
const placements = extents(scale);
|
|
123
|
+
const width = placements.reduce((n, p) => Math.max(n, p.width), 1), height = placements.reduce((n, p) => Math.max(n, p.height), 1);
|
|
124
|
+
return { independentTextures: true, pages: unique.map(index => ({ nextY: placements[index].height, placements: [placements[index]], shelves: [] })), placements,
|
|
125
|
+
width, height, floatStorage, bytesPerPixel, mapInfo: placements.flatMap(p => [p.width, p.height, p.layer, 0]),
|
|
126
|
+
mapTransform: textures.flatMap(t => [...t.uvScale, ...t.uvOffset]),
|
|
127
|
+
mapWrap: textures.flatMap(t => [textureWrapIndex(t.wrapS), textureWrapIndex(t.wrapT)]),
|
|
128
|
+
mapUvChannel: textures.map(t => t.uvChannel), mapColorLinear,
|
|
129
|
+
stats: { estimatedBytes: bytes(placements), width, height, layers: unique.length, packTimeMs: 0, scale,
|
|
130
|
+
sourcePixels: unique.reduce((n, i) => n + textures[i].image.width * textures[i].image.height, 0), textureCount: textures.length } };
|
|
131
|
+
}
|
|
86
132
|
const maxTextureArrayLayers = options.maxTextureArrayLayers ?? Infinity;
|
|
87
133
|
const maxTextureDimension2D = options.maxTextureDimension2D ?? Infinity;
|
|
88
134
|
const maxTextureArrayBytes = options.maxTextureArrayBytes ?? DEFAULT_MAX_TEXTURE_ARRAY_BYTES;
|
|
@@ -133,7 +179,7 @@ export function planTextureAtlas(textures, mapColorLinear, options = {}, floatSt
|
|
|
133
179
|
offsetY
|
|
134
180
|
];
|
|
135
181
|
});
|
|
136
|
-
return { pages: packed.pages, placements: packed.placements, width: atlasWidth, height: atlasHeight,
|
|
182
|
+
return { independentTextures: false, pages: packed.pages, placements: packed.placements, width: atlasWidth, height: atlasHeight,
|
|
137
183
|
floatStorage, bytesPerPixel, mapInfo,
|
|
138
184
|
mapTransform: textures.flatMap(texture => [texture.uvScale[0], texture.uvScale[1], texture.uvOffset[0], texture.uvOffset[1]]),
|
|
139
185
|
mapWrap: textures.flatMap(texture => [textureWrapIndex(texture.wrapS), textureWrapIndex(texture.wrapT)]),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"textureAtlas.js","sourceRoot":"","sources":["../../src/renderer/textureAtlas.ts"],"names":[],"mappings":"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","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"]}
|
|
1
|
+
{"version":3,"file":"textureAtlas.js","sourceRoot":"","sources":["../../src/renderer/textureAtlas.ts"],"names":[],"mappings":"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","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 /** Native binding arrays: retain separate images instead of packing atlas pages. Default false. */\n independentTextures?: boolean;\n // Native descriptors can expose several logical samplers over one owned image.\n textureSource?: (texture: TextureState) => object;\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 { independentTextures: !!options.independentTextures, 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 if (options.independentTextures) {\n const budget = options.maxTextureArrayBytes ?? DEFAULT_MAX_TEXTURE_ARRAY_BYTES;\n const dimension = options.maxTextureDimension2D ?? Infinity;\n const sources = new Map<object, Map<boolean, number>>(), unique: number[] = [];\n const layers = textures.map((texture, index) => {\n const source = options.textureSource?.(texture) ?? texture.image;\n let flips = sources.get(source);\n if (!flips) { flips = new Map(); sources.set(source, flips); }\n let layer = flips.get(texture.flipY);\n if (layer === undefined) { layer = unique.length; flips.set(texture.flipY, layer); unique.push(index); }\n return layer;\n });\n const extents = (scale: number) => textures.map((texture, index) => ({index, layer: layers[index], x: 0, y: 0,\n width: Math.max(1, Math.floor(texture.image.width * scale)), height: Math.max(1, Math.floor(texture.image.height * scale))}));\n const bytes = (items: AtlasPlacement[]) => unique.reduce((sum, index) => sum + items[index].width * items[index].height * bytesPerPixel, 0);\n if (unique.length * bytesPerPixel > budget) throw new Error('Material textures cannot fit the budget even at 1×1.');\n let scale = textures.reduce((s, t) => Math.min(s, dimension / Math.max(t.image.width, t.image.height)), 1);\n if (bytes(extents(scale)) > budget) {\n let low = 0, high = scale;\n for (let i = 0; i < 40; i++) { const mid = (low + high) / 2; if (bytes(extents(mid)) <= budget) low = mid; else high = mid; }\n scale = low;\n }\n const placements = extents(scale);\n const width = placements.reduce((n, p) => Math.max(n, p.width), 1), height = placements.reduce((n, p) => Math.max(n, p.height), 1);\n return {independentTextures: true, pages: unique.map(index => ({nextY: placements[index].height, placements: [placements[index]], shelves: [] as AtlasShelf[]})), placements,\n width, height, floatStorage, bytesPerPixel, mapInfo: placements.flatMap(p => [p.width, p.height, p.layer, 0]),\n mapTransform: textures.flatMap(t => [...t.uvScale, ...t.uvOffset]),\n mapWrap: textures.flatMap(t => [textureWrapIndex(t.wrapS), textureWrapIndex(t.wrapT)]),\n mapUvChannel: textures.map(t => t.uvChannel), mapColorLinear,\n stats: {estimatedBytes: bytes(placements), width, height, layers: unique.length, packTimeMs: 0, scale,\n sourcePixels: unique.reduce((n, i) => n + textures[i].image.width * textures[i].image.height, 0), textureCount: textures.length}};\n }\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 { independentTextures: false, 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"]}
|
package/lib/renderer/webgl.js
CHANGED
|
@@ -345,6 +345,10 @@ function setUniform(gl, location, uniform, value) {
|
|
|
345
345
|
gl.uniform3fv(location, data);
|
|
346
346
|
else if (uniform.type === 'vec4')
|
|
347
347
|
gl.uniform4fv(location, data);
|
|
348
|
+
else if (uniform.type === 'mat3')
|
|
349
|
+
gl.uniformMatrix3fv(location, false, data);
|
|
350
|
+
else if (uniform.type === 'mat4')
|
|
351
|
+
gl.uniformMatrix4fv(location, false, data);
|
|
348
352
|
else
|
|
349
353
|
gl.uniform1fv(location, data);
|
|
350
354
|
return;
|