@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,41 +1,74 @@
|
|
|
1
1
|
import { textureBytes } from './gpuMemory.js';
|
|
2
|
-
/** Target-owned
|
|
2
|
+
/** Target-owned images. A failed chain never replaces the composed image. */
|
|
3
3
|
export class DisplayPostProcess {
|
|
4
4
|
device;
|
|
5
|
-
textures =
|
|
5
|
+
textures = new Map();
|
|
6
6
|
image;
|
|
7
7
|
constructor(device) {
|
|
8
8
|
this.device = device;
|
|
9
9
|
}
|
|
10
10
|
get output() { return this.image; }
|
|
11
11
|
reset() { this.image = undefined; }
|
|
12
|
-
getMemoryBytes() { return this.textures.reduce((sum, texture) => sum + textureBytes(texture), 0); }
|
|
12
|
+
getMemoryBytes() { return [...this.textures.values()].flat().reduce((sum, texture) => sum + textureBytes(texture), 0); }
|
|
13
13
|
retire(textures) {
|
|
14
14
|
if (!textures.length)
|
|
15
15
|
return;
|
|
16
16
|
void this.device.queue.onSubmittedWorkDone().catch(() => { }).then(() => textures.forEach(texture => texture.destroy()));
|
|
17
17
|
}
|
|
18
|
-
dispose() { this.reset(); this.retire(this.textures); this.textures
|
|
19
|
-
run(input, passes, render) {
|
|
18
|
+
dispose() { this.reset(); this.retire([...this.textures.values()].flat()); this.textures.clear(); }
|
|
19
|
+
run(input, passes, render, display = input, options = [], crop) {
|
|
20
20
|
this.reset();
|
|
21
|
-
|
|
21
|
+
const cropped = crop && (crop.width !== input.width || crop.height !== input.height);
|
|
22
|
+
if (!passes.length && !cropped)
|
|
22
23
|
return;
|
|
23
|
-
|
|
24
|
-
this.
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
const validate = (size) => {
|
|
25
|
+
const limit = this.device.limits.maxTextureDimension2D;
|
|
26
|
+
if (!size || !Number.isInteger(size.width) || !Number.isInteger(size.height) || size.width < 1 || size.height < 1 || size.width > limit || size.height > limit) {
|
|
27
|
+
throw new RangeError('Post-process output dimensions must be positive integers within maxTextureDimension2D.');
|
|
28
|
+
}
|
|
29
|
+
return { width: size.width, height: size.height };
|
|
30
|
+
};
|
|
31
|
+
// Evaluate the entire size chain before recording user commands.
|
|
32
|
+
let size = cropped ? validate(crop) : { width: input.width, height: input.height };
|
|
33
|
+
const sizes = passes.map((_, index) => size = validate(options[index]?.outputSize ? options[index].outputSize({ ...size }, { width: display.width, height: display.height }) : size));
|
|
34
|
+
const active = new Set();
|
|
35
|
+
const acquire = (size, previous) => {
|
|
36
|
+
const key = `${size.width}:${size.height}:${input.format}`;
|
|
37
|
+
active.add(key);
|
|
38
|
+
// Allocate the second image of a size only when consecutive passes need to ping-pong.
|
|
39
|
+
const pair = this.textures.get(key) ?? [];
|
|
40
|
+
this.textures.set(key, pair);
|
|
41
|
+
const index = pair[0] === previous ? 1 : 0;
|
|
42
|
+
pair[index] ??= this.device.createTexture({
|
|
43
|
+
label: `Display post-process ${index}`, size, format: input.format,
|
|
27
44
|
usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST
|
|
28
|
-
})
|
|
29
|
-
|
|
45
|
+
});
|
|
46
|
+
return pair[index];
|
|
47
|
+
};
|
|
48
|
+
const actual = render._output?.getMemory() ?? input;
|
|
30
49
|
const encoder = this.device.createCommandEncoder();
|
|
31
50
|
let previous = input;
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
51
|
+
try {
|
|
52
|
+
if (cropped) {
|
|
53
|
+
const output = acquire(crop, previous);
|
|
54
|
+
encoder.copyTextureToTexture({ texture: input, origin: { x: Math.floor((input.width - crop.width) / 2), y: Math.floor((input.height - crop.height) / 2) } }, { texture: output }, crop);
|
|
55
|
+
previous = output;
|
|
56
|
+
}
|
|
57
|
+
for (let index = 0; index < passes.length; index++) {
|
|
58
|
+
const output = acquire(sizes[index], previous);
|
|
59
|
+
passes[index]({ device: this.device, encoder, input: previous, output, width: actual.width, height: actual.height, render });
|
|
60
|
+
previous = output;
|
|
61
|
+
}
|
|
62
|
+
this.device.queue.submit([encoder.finish()]);
|
|
63
|
+
this.image = previous;
|
|
64
|
+
}
|
|
65
|
+
finally {
|
|
66
|
+
for (const [key, pair] of this.textures)
|
|
67
|
+
if (!active.has(key)) {
|
|
68
|
+
this.textures.delete(key);
|
|
69
|
+
this.retire(pair);
|
|
70
|
+
}
|
|
36
71
|
}
|
|
37
|
-
this.device.queue.submit([encoder.finish()]);
|
|
38
|
-
this.image = previous;
|
|
39
72
|
}
|
|
40
73
|
}
|
|
41
74
|
//# sourceMappingURL=DisplayPostProcess.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DisplayPostProcess.js","sourceRoot":"","sources":["../../src/renderer/DisplayPostProcess.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"DisplayPostProcess.js","sourceRoot":"","sources":["../../src/renderer/DisplayPostProcess.ts"],"names":[],"mappings":"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","sourcesContent":["import type { PostProcess, PostProcessContext, PostProcessOptions } from '../Display.js';\nimport {textureBytes} from './gpuMemory.js';\n\ntype Size = {width: number; height: number};\n/** Target-owned images. A failed chain never replaces the composed image. */\nexport class DisplayPostProcess {\n private textures = new Map<string, GPUTexture[]>();\n private image?: GPUTexture;\n constructor(private readonly device: GPUDevice) {}\n get output() { return this.image; }\n reset() { this.image = undefined; }\n getMemoryBytes() { return [...this.textures.values()].flat().reduce((sum, texture) => sum + textureBytes(texture), 0); }\n private retire(textures: GPUTexture[]) {\n if (!textures.length) return;\n void this.device.queue.onSubmittedWorkDone().catch(() => {}).then(() => textures.forEach(texture => texture.destroy()));\n }\n dispose() { this.reset(); this.retire([...this.textures.values()].flat()); this.textures.clear(); }\n run(input: GPUTexture, passes: readonly PostProcess[], render: PostProcessContext['render'], display: Size = input,\n options: readonly PostProcessOptions[] = [], crop?: Size) {\n this.reset();\n const cropped = crop && (crop.width !== input.width || crop.height !== input.height);\n if (!passes.length && !cropped) return;\n const validate = (size: Size) => {\n const limit = this.device.limits.maxTextureDimension2D;\n if (!size || !Number.isInteger(size.width) || !Number.isInteger(size.height) || size.width < 1 || size.height < 1 || size.width > limit || size.height > limit) {\n throw new RangeError('Post-process output dimensions must be positive integers within maxTextureDimension2D.');\n }\n return {width: size.width, height: size.height};\n };\n // Evaluate the entire size chain before recording user commands.\n let size: Size = cropped ? validate(crop) : {width: input.width, height: input.height};\n const sizes = passes.map((_, index) => size = validate(options[index]?.outputSize ? options[index].outputSize!({...size}, {width: display.width, height: display.height}) : size));\n const active = new Set<string>();\n const acquire = (size: Size, previous: GPUTexture) => {\n const key = `${size.width}:${size.height}:${input.format}`;\n active.add(key);\n // Allocate the second image of a size only when consecutive passes need to ping-pong.\n const pair = this.textures.get(key) ?? [];\n this.textures.set(key, pair);\n const index = pair[0] === previous ? 1 : 0;\n pair[index] ??= this.device.createTexture({\n label: `Display post-process ${index}`, size, format: input.format,\n usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST\n });\n return pair[index];\n };\n const actual = render._output?.getMemory() ?? input;\n const encoder = this.device.createCommandEncoder();\n let previous = input;\n try {\n if (cropped) {\n const output = acquire(crop, previous);\n encoder.copyTextureToTexture({texture: input, origin: {x: Math.floor((input.width-crop.width)/2), y: Math.floor((input.height-crop.height)/2)}}, {texture: output}, crop);\n previous = output;\n }\n for (let index = 0; index < passes.length; index++) {\n const output = acquire(sizes[index], previous);\n passes[index]({device: this.device, encoder, input: previous, output, width: actual.width, height: actual.height, render});\n previous = output;\n }\n this.device.queue.submit([encoder.finish()]);\n this.image = previous;\n } finally {\n for (const [key, pair] of this.textures) if (!active.has(key)) { this.textures.delete(key); this.retire(pair); }\n }\n }\n}\n"]}
|
|
@@ -4,7 +4,8 @@ export declare class GPUTraceQueue {
|
|
|
4
4
|
private pendingMs;
|
|
5
5
|
private pending;
|
|
6
6
|
constructor(queue: GPUQueue);
|
|
7
|
+
get hasPending(): boolean;
|
|
7
8
|
available(budgetMs: number): number;
|
|
8
|
-
whenAvailable(): Promise<
|
|
9
|
+
whenAvailable(): Promise<boolean>;
|
|
9
10
|
track(estimatedMs: number): void;
|
|
10
11
|
}
|
|
@@ -6,11 +6,13 @@ export class GPUTraceQueue {
|
|
|
6
6
|
constructor(queue) {
|
|
7
7
|
this.queue = queue;
|
|
8
8
|
}
|
|
9
|
+
get hasPending() { return this.pending.size > 0; }
|
|
9
10
|
available(budgetMs) {
|
|
10
11
|
return Math.max(0, budgetMs - this.pendingMs);
|
|
11
12
|
}
|
|
12
13
|
whenAvailable() {
|
|
13
|
-
|
|
14
|
+
const pending = this.pending.values().next().value;
|
|
15
|
+
return pending ? pending.then(() => true) : Promise.resolve(false);
|
|
14
16
|
}
|
|
15
17
|
track(estimatedMs) {
|
|
16
18
|
this.pendingMs += estimatedMs;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GPUTraceQueue.js","sourceRoot":"","sources":["../../src/renderer/GPUTraceQueue.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,MAAM,OAAO,aAAa;IAIJ;IAHZ,SAAS,GAAG,CAAC,CAAC;IACd,OAAO,GAAG,IAAI,GAAG,EAAiB,CAAC;IAE3C,YAAoB,KAAe;QAAf,UAAK,GAAL,KAAK,CAAU;IAAG,CAAC;IAEvC,SAAS,CAAC,QAAgB;QACxB,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC;IAChD,CAAC;IAED,aAAa;QACX,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,
|
|
1
|
+
{"version":3,"file":"GPUTraceQueue.js","sourceRoot":"","sources":["../../src/renderer/GPUTraceQueue.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,MAAM,OAAO,aAAa;IAIJ;IAHZ,SAAS,GAAG,CAAC,CAAC;IACd,OAAO,GAAG,IAAI,GAAG,EAAiB,CAAC;IAE3C,YAAoB,KAAe;QAAf,UAAK,GAAL,KAAK,CAAU;IAAG,CAAC;IAEvC,IAAI,UAAU,KAAc,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC;IAE3D,SAAS,CAAC,QAAgB;QACxB,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC;IAChD,CAAC;IAED,aAAa;QACX,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;QACnD,OAAO,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACrE,CAAC;IAED,KAAK,CAAC,WAAmB;QACvB,IAAI,CAAC,SAAS,IAAI,WAAW,CAAC;QAC9B,4EAA4E;QAC5E,6EAA6E;QAC7E,MAAM,MAAM,GAAG,GAAG,EAAE;YAClB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,SAAS,GAAG,WAAW,CAAC,CAAC;YAC3D,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YAChC,qEAAqE;YACrE,wEAAwE;YACxE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI;gBAAE,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;QAC7C,CAAC,CAAC;QACF,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,mBAAmB,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACzE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAC/B,CAAC;CACF","sourcesContent":["/** Shared by resident targets so switching images cannot reset queued work. */\nexport class GPUTraceQueue {\n private pendingMs = 0;\n private pending = new Set<Promise<void>>();\n\n constructor(private queue: GPUQueue) {}\n\n get hasPending(): boolean { return this.pending.size > 0; }\n\n available(budgetMs: number): number {\n return Math.max(0, budgetMs - this.pendingMs);\n }\n\n whenAvailable(): Promise<boolean> {\n const pending = this.pending.values().next().value;\n return pending ? pending.then(() => true) : Promise.resolve(false);\n }\n\n track(estimatedMs: number): void {\n this.pendingMs += estimatedMs;\n // Fence each sample, rather than the entire batch: a later display tick can\n // replace completed samples while the tail of the previous batch still runs.\n const retire = () => {\n this.pendingMs = Math.max(0, this.pendingMs - estimatedMs);\n this.pending.delete(completion);\n // Subtracting estimates leaves rounding residue. An empty queue must\n // admit a sample as long as the budget, or nothing would wake it again.\n if (!this.pending.size) this.pendingMs = 0;\n };\n const completion = this.queue.onSubmittedWorkDone().then(retire, retire);\n this.pending.add(completion);\n }\n}\n"]}
|
|
@@ -18,8 +18,13 @@ export default class MaterialData {
|
|
|
18
18
|
this.textures = maps.textures.slice();
|
|
19
19
|
for (const texture of lightTextures) {
|
|
20
20
|
if (texture) {
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
const existing = options.independentTextures ? this.textures.indexOf(texture) : -1;
|
|
22
|
+
if (existing >= 0)
|
|
23
|
+
this.lightTexturesIndices.push(existing);
|
|
24
|
+
else {
|
|
25
|
+
this.lightTexturesIndices.push(this.textures.length);
|
|
26
|
+
this.textures.push(texture);
|
|
27
|
+
}
|
|
23
28
|
}
|
|
24
29
|
else
|
|
25
30
|
this.lightTexturesIndices.push(-1);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MaterialData.js","sourceRoot":"","sources":["../../src/renderer/MaterialData.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AAC3F,OAAO,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,EAAE,wBAAwB,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AACrF,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAoD,MAAM,mBAAmB,CAAC;AAGvG,oFAAoF;AACpF,mFAAmF;AACnF,MAAM,CAAC,OAAO,OAAO,YAAY;IAC/B,UAAU,CAAa;IACvB,QAAQ,CAAiB;IACzB,gBAAgB,CAAiB;IACjC,oBAAoB,GAAa,EAAE,CAAC;IACpC,OAAO,GAA2B,EAAE,CAAC;IACrC,KAAK,CAAmB;IACxB,YAAY,SAA0B,EAAE,aAA2C,EACjF,WAA8C,EAAE,UAAgC,EAAE,EAClF,YAAiD;QACjD,MAAM,IAAI,GAAG,0BAA0B,CAAC,SAAS,EAAE,sBAAsB,CAAC,CAAC;QAC3E,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QACrH,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;QACtC,KAAK,MAAM,OAAO,IAAI,aAAa,EAAE,CAAC;YACpC,IAAI,OAAO,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"MaterialData.js","sourceRoot":"","sources":["../../src/renderer/MaterialData.ts"],"names":[],"mappings":"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","sourcesContent":["import type MaterialState from '../scene/MaterialState.js';\nimport type TextureState from '../scene/TextureState.js';\nimport { MATERIAL_TEXTURE_NAMES, MATERIAL_TEXTURE_SLOTS } from './materialTextureSlots.js';\nimport { mergeTexturesFromMaterials } from './materialTextures.js';\nimport { createMaterialBufferData, repackMaterialParams } from './materialParams.js';\nimport { packMaterialBuffer } from './materialLayout.js';\nimport { planTextureAtlas, type MaterialTableOptions, type TextureAtlasPlan } from './textureAtlas.js';\nimport type { BufferData } from './materialBufferData.js';\n\n// CPU material preparation shared by browser uploads and native command generation.\n// The adapter describes source encoding; the core never decodes DOM/GPU resources.\nexport default class MaterialData {\n bufferData: BufferData;\n textures: TextureState[];\n displacementMaps: TextureState[];\n lightTexturesIndices: number[] = [];\n defines: Record<string, number> = {};\n atlas: TextureAtlasPlan;\n constructor(materials: MaterialState[], lightTextures: (TextureState | undefined)[],\n colorLinear: (texture: TextureState) => number, options: MaterialTableOptions = {},\n floatStorage?: (texture: TextureState) => boolean) {\n const maps = mergeTexturesFromMaterials(materials, MATERIAL_TEXTURE_NAMES);\n this.displacementMaps = maps.indices.displacementMap.map(index => maps.textures[index]).filter(texture => !!texture);\n this.textures = maps.textures.slice();\n for (const texture of lightTextures) {\n if (texture) {\n const existing = options.independentTextures ? this.textures.indexOf(texture) : -1;\n if (existing >= 0) this.lightTexturesIndices.push(existing);\n else { this.lightTexturesIndices.push(this.textures.length); this.textures.push(texture); }\n }\n else this.lightTexturesIndices.push(-1);\n }\n this.bufferData = createMaterialBufferData(materials);\n this.bufferData.diffuseMapIndex = maps.indices.map;\n this.bufferData.alphaMapIndex = maps.indices.alphaMap;\n this.bufferData.normalMapIndex = maps.indices.normalMap;\n this.bufferData.emissiveMapIndex = maps.indices.emissiveMap;\n this.bufferData.metallicRoughnessMapIndex = maps.indices.metallicRoughnessMap;\n this.bufferData.roughnessMapIndex = maps.indices.roughnessMap;\n this.bufferData.metalnessMapIndex = maps.indices.metalnessMap;\n this.bufferData.transmissionMapIndex = maps.indices.transmissionMap;\n this.bufferData.thinFilmMapIndex = maps.indices.thinFilmMap;\n this.bufferData.displacementMapIndex = maps.indices.displacementMap;\n this.bufferData.coatWeightMapIndex = maps.indices.coatWeightMap;\n this.bufferData.coatRoughnessMapIndex = maps.indices.coatRoughnessMap;\n this.bufferData.fuzzColorMapIndex = maps.indices.fuzzColorMap;\n this.bufferData.fuzzRoughnessMapIndex = maps.indices.fuzzRoughnessMap;\n this.bufferData.specularWeightMapIndex = maps.indices.specularWeightMap;\n this.bufferData.specularColorMapIndex = maps.indices.specularColorMap;\n this.bufferData.anisotropyMapIndex = maps.indices.anisotropyMap;\n this.bufferData.coatNormalMapIndex = maps.indices.coatNormalMap;\n this.atlas = planTextureAtlas(this.textures, this.textures.map(colorLinear), options,\n floatStorage ? this.textures.some(floatStorage) : undefined);\n this.bufferData.mapInfo = this.atlas.mapInfo; this.bufferData.mapTransform = this.atlas.mapTransform;\n this.bufferData.mapWrap = this.atlas.mapWrap;\n this.bufferData.mapUvChannel = this.atlas.mapUvChannel; this.bufferData.mapColorLinear = this.atlas.mapColorLinear;\n this.defines = {NUM_MAPS: this.textures.length};\n for (const slot of MATERIAL_TEXTURE_SLOTS) {\n if (slot.define) this.defines[slot.define] = maps.indices[slot.property].filter(index => index >= 0).length;\n }\n }\n repackParams(materials: MaterialState[]) { repackMaterialParams(this.bufferData, materials); }\n getBufferArray() { return packMaterialBuffer(this.bufferData); }\n}\n"]}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { SurfaceHit } from './surfaceHit.js';
|
|
1
2
|
import type { PostProcess } from '../Display.js';
|
|
2
3
|
import type Render from '../Render.js';
|
|
3
4
|
import type { DenoiserHandle, OIDNWeb } from './denoiser.js';
|
|
@@ -157,6 +158,10 @@ export interface RenderingDiagnostics {
|
|
|
157
158
|
};
|
|
158
159
|
};
|
|
159
160
|
gpuTraceTiming?: {
|
|
161
|
+
/** Last light-tracing batch time in milliseconds. Default undefined until measured. */ causticTimeMs?: number;
|
|
162
|
+
/** Last photon-map batch time in milliseconds. Default undefined until measured. */ photonMappingTimeMs?: number;
|
|
163
|
+
/** Photon emission, count, block scan, sum scan and scatter times in milliseconds. Default undefined until measured. */ photonStagesMs?: number[];
|
|
164
|
+
/** Camera path kernel time in milliseconds. Default undefined until measured. */ pathTracingTimeMs?: number;
|
|
160
165
|
tileTimeMs: number;
|
|
161
166
|
tileTimePerSampleMs?: number;
|
|
162
167
|
estimatedFullFrameTimeMs: number;
|
|
@@ -180,6 +185,7 @@ export interface SceneResources {
|
|
|
180
185
|
getDiagnostics(): RenderingDiagnostics;
|
|
181
186
|
dispose(): void;
|
|
182
187
|
readDepthSamples(area: DepthSampleArea): Promise<Float32Array | undefined>;
|
|
188
|
+
pickSurface?(x: number, y: number, aspect?: number): Promise<SurfaceHit | null | undefined>;
|
|
183
189
|
}
|
|
184
190
|
/** Explicit execution and composition for one accumulation. */
|
|
185
191
|
export interface RenderPasses {
|
|
@@ -189,7 +195,11 @@ export interface RenderPasses {
|
|
|
189
195
|
trace(camera: Camera, maxSamples: number): boolean;
|
|
190
196
|
drawPostProcess(): void;
|
|
191
197
|
/** Apply display-only passes to the last composed image; absent on WebGL. */
|
|
192
|
-
applyPostProcesses?(passes: readonly PostProcess[], render: Render)
|
|
198
|
+
applyPostProcesses?(passes: readonly PostProcess[], render: Render, options?: readonly import('../Display.js').PostProcessOptions[], crop?: {
|
|
199
|
+
width: number;
|
|
200
|
+
height: number;
|
|
201
|
+
}): void;
|
|
202
|
+
getAovTexture?(kind: 'diffuseColor' | 'specularColor' | 'depth'): GPUTexture | undefined;
|
|
193
203
|
getOutputTexture?(kind: 'hdr' | 'display'): GPUTexture | undefined;
|
|
194
204
|
/** Configure deterministic headless batches used by offline frame export. */
|
|
195
205
|
setOfflineRenderOptions(options: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RenderingPipeline.js","sourceRoot":"","sources":["../../src/renderer/RenderingPipeline.ts"],"names":[],"mappings":"AAqLA,OAAO,EAAC,qBAAqB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,+BAA+B,EAAE,2BAA2B,EAAE,2BAA2B,EAAE,8BAA8B,EAAE,qBAAqB,EAAC,MAAM,sBAAsB,CAAC","sourcesContent":["import type {PostProcess} from '../Display.js';\nimport type Render from '../Render.js';\nimport type {DenoiserHandle, OIDNWeb} from './denoiser.js';\nimport type {DenoiseSchedule} from '../Render.js';\nimport type { DepthSampleArea } from './depthQuery.js';\nimport Camera from '../scene/Camera.js';\nimport Mesh from '../scene/Mesh.js';\nimport Geometry from '../scene/Geometry.js';\nimport OpenPBRMaterial from '../scene/OpenPBRMaterial.js';\nimport type { SceneBackground, SceneLight } from '../scene/Scene.js';\nimport type { ColorRGB } from '../types.js';\nimport type { TextureAtlasStats } from './MaterialTable.js';\nimport type {\n OfflineAdaptiveSamplingOptions,\n OfflineAdaptiveSamplingResult\n} from './OfflineAdaptiveSampling.js';\n\nexport type ToneMapping =\n | 'agx'\n | 'aces'\n | 'cineon'\n | 'reinhard'\n | 'linear';\n\nexport interface ToneMappingParams {\n /** Linear exposure multiplier. Default `1`. */\n exposure?: number;\n /** Display tone mapper. Default `agx`. */\n toneMapping?: ToneMapping;\n /** Contrast multiplier. Default `1`. */\n contrast?: number;\n /** Saturation multiplier. Default `1`. */\n saturation?: number;\n /** Color temperature adjustment in [-1, 1]. Default `0`. */\n temperature?: number;\n /** Green/magenta adjustment in [-1, 1]. Default `0`. */\n tint?: number;\n /** Vignette strength in [0, 1]. Default `0`. */\n vignette?: number;\n}\n\nexport type DisplayChannel =\n | 'final'\n | 'shadow'\n | 'albedo'\n | 'normal'\n | 'shadowCatcher'\n | import('./aov.js').AovKind;\n\n/** Primary-ray policy for glTF BLEND materials. */\nexport type AlphaBlendStrategy =\n | 'stochastic'\n | 'deterministic-source-over';\n\n/** Generated source measurements for one shader module. */\nexport interface ShaderModuleCompilationDiagnostics {\n /** Module or pipeline diagnostic label. */\n label: string;\n /** Generated shader source size in bytes. */\n sourceBytes: number;\n /** Generated shader source line count. */\n sourceLines: number;\n /** Stable source-level fingerprint for diagnosing cache-key churn. */\n sourceFingerprint: string;\n}\n\n/** Compilation measurements for one shader pipeline/program. */\nexport interface ShaderPipelineCompilationDiagnostics {\n /** Module or pipeline diagnostic label. */\n label: string;\n /** Compute entry-point name. */\n entryPoint: string;\n /**\n * Whether this pipeline belongs to the minimum set needed to present a\n * usable first image. Optional reuse and quality stages are false even\n * while the current eager compiler still waits for them.\n */\n firstFrameRequired: boolean;\n /** Current compilation state. */\n status: 'queued' | 'compiling' | 'ready' | 'failed';\n /** Milliseconds from the start of this pipeline compilation batch. */\n startedAtMs?: number;\n /** Milliseconds from the start of this pipeline compilation batch. */\n endedAtMs?: number;\n /** Pipeline compilation duration in milliseconds; undefined until completed. */\n durationMs?: number;\n /** Number of pipelines compiling when this one started; undefined before start. */\n concurrentCompilationCount?: number;\n /** Failure message; undefined without a compilation error. */\n error?: string;\n}\n\n/** Source generation and asynchronous pipeline compilation measurements. */\nexport interface ShaderCompilationDiagnostics {\n /** Current compilation state. */\n status: 'compiling' | 'ready' | 'failed';\n /** Generated shader source size in bytes. */\n sourceBytes: number;\n /** Generated shader source line count. */\n sourceLines: number;\n /** Total pipelines in the batch. */\n pipelineCount: number;\n /** Number of pipelines successfully completed. */\n completedPipelineCount: number;\n /** CPU shader source generation time in milliseconds. */\n sourceGenerationTimeMs: number;\n /** Shader module creation time in milliseconds. */\n moduleCreationTimeMs: number;\n /** Per-module source measurements. */\n modules: ShaderModuleCompilationDiagnostics[];\n /** Per-pipeline timing and status measurements. */\n pipelines: ShaderPipelineCompilationDiagnostics[];\n /** Configured pool size, capped to the number of pipelines in this batch. */\n maximumConcurrentPipelineCount: number;\n /** Largest number of createComputePipelineAsync calls active at once. */\n peakConcurrentPipelineCount: number;\n /** Batch pipeline compilation time in milliseconds; undefined until completed. */\n pipelineCompilationTimeMs?: number;\n /** Total batch preparation time in milliseconds; undefined until completed. */\n totalTimeMs?: number;\n /** Failure message; undefined without a compilation error. */\n error?: string;\n}\n\nexport interface RenderingDiagnostics {\n /** Label of the last complete target presented; undefined before the first image. */\n presentedTarget?: string;\n /** Whether the displayed target contains a complete image. Default false. */\n presentedComplete?: boolean;\n /** Resident target dimensions and allocated GPU bytes, including denoise resources. */\n targets?: { label: string; width: number; height: number; bytes: number }[];\n hdrPresentation?: {\n requested: boolean;\n active: boolean;\n /** Largest encoded RGB component sent to the HDR presentation pass. */\n peakDisplayValue?: number;\n };\n textureAtlas?: TextureAtlasStats;\n /** Material texture storage selection and estimated payload; driver allocation overhead is excluded. */\n materialTextures?: {\n requested: 'atlas' | 'auto';\n active: 'atlas' | 'bindless';\n /** Reason auto selected atlas; undefined when no fallback occurred. */\n fallbackReason?: string;\n textureCount: number;\n estimatedBytes: number;\n scale: number;\n /** Metadata buffer bytes; zero for atlas. */\n metadataBytes: number;\n /** Resource-table slots; zero for atlas. */\n resourceTableCapacity: number;\n /** Payload and metadata waiting for previous GPU submissions; zero when none. */\n retiredBytes: number;\n };\n /** Shader compilation measurements: current WebGPU batch or cumulative WebGL programs. */\n shaderCompilation?: ShaderCompilationDiagnostics;\n /** Light-selection table summary (WebGPU). */\n lightSampling?: {\n emissiveTriangles: number;\n activeChoices: number;\n totalWeight: number;\n domains: Record<\n 'environment' | 'infinite' | 'localAndEmissive',\n { count: number; weight: number; pmf: number }\n >;\n };\n /** Traversal stack capacities compiled into the current WebGPU shader. */\n bvh?: {\n tlasTraversalStackSize?: number;\n blasTraversalStackSize?: number;\n /** Last static preparation statistics, excluding queue and WASM loading time. */\n lastBuild?: { geometryCount: number; bvhTimeMs: number };\n };\n gpuTraceTiming?: {\n tileTimeMs: number;\n tileTimePerSampleMs?: number;\n estimatedFullFrameTimeMs: number;\n tileCount: number;\n };\n}\n\nexport {DEFAULT_BEVEL_SAMPLES, MIN_BEVEL_SAMPLES, MAX_BEVEL_SAMPLES, DEFAULT_DIRECT_LIGHT_CANDIDATES, MIN_DIRECT_LIGHT_CANDIDATES, MAX_DIRECT_LIGHT_CANDIDATES, normalizeDirectLightCandidates, normalizeBevelSamples} from './renderingLimits.js';\n\n/** Shared scene resources; uploaded once per committed revision. */\nexport interface SceneResources {\n /** Returns true when scene geometry, materials, or instance transforms changed. */\n setMeshes(meshes: Mesh[], update?: {\n transforms?: readonly Mesh[];\n colors?: readonly Mesh[];\n geometries?: readonly Geometry[];\n materials?: readonly OpenPBRMaterial[];\n }): boolean;\n /** Changes the software memory guard used when packing material textures. */\n setTextureAtlasBudget(maxBytes: number): boolean;\n setLights(lights: SceneLight[]): void;\n setBackground(background?: SceneBackground): void;\n getDiagnostics(): RenderingDiagnostics;\n dispose(): void;\n readDepthSamples(area: DepthSampleArea): Promise<Float32Array | undefined>;\n}\n/** Explicit execution and composition for one accumulation. */\nexport interface RenderPasses {\n isFirstFrame(): boolean;\n /** Discard accumulated samples and any asynchronous denoise output. */\n restartSamples(): void;\n trace(camera: Camera, maxSamples: number): boolean;\n drawPostProcess(): void;\n /** Apply display-only passes to the last composed image; absent on WebGL. */\n applyPostProcesses?(passes: readonly PostProcess[], render: Render): void;\n getOutputTexture?(kind: 'hdr' | 'display'): GPUTexture | undefined;\n /** Configure deterministic headless batches used by offline frame export. */\n setOfflineRenderOptions(options: {\n samplesPerBatch: number;\n deferPostProcess: boolean;\n sampleSequenceOffset: number;\n }): void;\n /** Store luminance second moments in the normal output during a pilot pass. */\n setVarianceMoments(enabled: boolean): void;\n /** Skip pixels once their independent final-pass target has been reached. */\n setAdaptiveSamplingTargets(targets?: {\n width: number;\n height: number;\n data: Float32Array;\n }): void;\n /** Generate final sample targets on GPU; WebGL returns undefined. */\n prepareOfflineAdaptiveSampling(\n options: OfflineAdaptiveSamplingOptions\n ): Promise<OfflineAdaptiveSamplingResult | undefined>;\n /** Enables extended-range float canvas presentation when the host supports it. */\n setHDROutputEnabled?(enabled: boolean): boolean;\n setToneMappingParams(params: ToneMappingParams): boolean;\n setSize(width: number, height: number): void;\n /**\n * Denoises the current image with an explicitly selected built-in or custom filter. Resolves whether the result is now displayed.\n */\n performDenoise?(\n denoiser: DenoiserHandle,\n alphaDenoiser?: OIDNWeb,\n schedule?: DenoiseSchedule,\n signal?: AbortSignal\n ): Promise<boolean>;\n /** Drops a denoise in flight; the next draw invalidates its output. */\n cancelDenoise?(): void;\n /** Keep the last completed OIDN image visible while static while-converging batches accumulate. */\n setPreserveDenoisedOutput?(preserve: boolean): void;\n getTotalSamplesRendered(): number;\n getDiagnostics(): RenderingDiagnostics;\n /** Waits for asynchronous timestamp diagnostics without changing samples. */\n flushDiagnostics(): Promise<void>;\n setShadowCatcherParams(color: ColorRGB, alpha: number): boolean;\n setBloomParams(opts: {\n intensity: number;\n threshold: number;\n radius: number;\n }): boolean;\n setOnSampleRendered(\n cb: (sampleCount: number, isFirstFrame: boolean, frameTime: number) => void\n ): void;\n setOutput(output: DisplayChannel): boolean;\n setAovDisplayOptions?(options: import('./aovDisplay.js').AovDisplayOptions): void;\n dispose(): void;\n aovReady?(kind: import('./aov.js').AovKind): boolean;\n /** Updates optional surface outputs without tracing beauty; false while compiling. */\n refineAovs?(camera: Camera, samples?: number): boolean;\n restartAovs?(): void;\n getAovSamples?(): number;\n readAov?(kind: import('./aov.js').AovKind): Promise<{width: number; height: number; data: Float32Array | Uint32Array}>;\n readOutput(kind: 'hdr' | 'denoised' | 'albedo' | 'normal'): Promise<{\n data: Float32Array;\n width: number;\n height: number;\n }>;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"RenderingPipeline.js","sourceRoot":"","sources":["../../src/renderer/RenderingPipeline.ts"],"names":[],"mappings":"AA0LA,OAAO,EAAC,qBAAqB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,+BAA+B,EAAE,2BAA2B,EAAE,2BAA2B,EAAE,8BAA8B,EAAE,qBAAqB,EAAC,MAAM,sBAAsB,CAAC","sourcesContent":["import type {SurfaceHit} from './surfaceHit.js';\nimport type {PostProcess} from '../Display.js';\nimport type Render from '../Render.js';\nimport type {DenoiserHandle, OIDNWeb} from './denoiser.js';\nimport type {DenoiseSchedule} from '../Render.js';\nimport type { DepthSampleArea } from './depthQuery.js';\nimport Camera from '../scene/Camera.js';\nimport Mesh from '../scene/Mesh.js';\nimport Geometry from '../scene/Geometry.js';\nimport OpenPBRMaterial from '../scene/OpenPBRMaterial.js';\nimport type { SceneBackground, SceneLight } from '../scene/Scene.js';\nimport type { ColorRGB } from '../types.js';\nimport type { TextureAtlasStats } from './MaterialTable.js';\nimport type {\n OfflineAdaptiveSamplingOptions,\n OfflineAdaptiveSamplingResult\n} from './OfflineAdaptiveSampling.js';\n\nexport type ToneMapping =\n | 'agx'\n | 'aces'\n | 'cineon'\n | 'reinhard'\n | 'linear';\n\nexport interface ToneMappingParams {\n /** Linear exposure multiplier. Default `1`. */\n exposure?: number;\n /** Display tone mapper. Default `agx`. */\n toneMapping?: ToneMapping;\n /** Contrast multiplier. Default `1`. */\n contrast?: number;\n /** Saturation multiplier. Default `1`. */\n saturation?: number;\n /** Color temperature adjustment in [-1, 1]. Default `0`. */\n temperature?: number;\n /** Green/magenta adjustment in [-1, 1]. Default `0`. */\n tint?: number;\n /** Vignette strength in [0, 1]. Default `0`. */\n vignette?: number;\n}\n\nexport type DisplayChannel =\n | 'final'\n | 'shadow'\n | 'albedo'\n | 'normal'\n | 'shadowCatcher'\n | import('./aov.js').AovKind;\n\n/** Primary-ray policy for glTF BLEND materials. */\nexport type AlphaBlendStrategy =\n | 'stochastic'\n | 'deterministic-source-over';\n\n/** Generated source measurements for one shader module. */\nexport interface ShaderModuleCompilationDiagnostics {\n /** Module or pipeline diagnostic label. */\n label: string;\n /** Generated shader source size in bytes. */\n sourceBytes: number;\n /** Generated shader source line count. */\n sourceLines: number;\n /** Stable source-level fingerprint for diagnosing cache-key churn. */\n sourceFingerprint: string;\n}\n\n/** Compilation measurements for one shader pipeline/program. */\nexport interface ShaderPipelineCompilationDiagnostics {\n /** Module or pipeline diagnostic label. */\n label: string;\n /** Compute entry-point name. */\n entryPoint: string;\n /**\n * Whether this pipeline belongs to the minimum set needed to present a\n * usable first image. Optional reuse and quality stages are false even\n * while the current eager compiler still waits for them.\n */\n firstFrameRequired: boolean;\n /** Current compilation state. */\n status: 'queued' | 'compiling' | 'ready' | 'failed';\n /** Milliseconds from the start of this pipeline compilation batch. */\n startedAtMs?: number;\n /** Milliseconds from the start of this pipeline compilation batch. */\n endedAtMs?: number;\n /** Pipeline compilation duration in milliseconds; undefined until completed. */\n durationMs?: number;\n /** Number of pipelines compiling when this one started; undefined before start. */\n concurrentCompilationCount?: number;\n /** Failure message; undefined without a compilation error. */\n error?: string;\n}\n\n/** Source generation and asynchronous pipeline compilation measurements. */\nexport interface ShaderCompilationDiagnostics {\n /** Current compilation state. */\n status: 'compiling' | 'ready' | 'failed';\n /** Generated shader source size in bytes. */\n sourceBytes: number;\n /** Generated shader source line count. */\n sourceLines: number;\n /** Total pipelines in the batch. */\n pipelineCount: number;\n /** Number of pipelines successfully completed. */\n completedPipelineCount: number;\n /** CPU shader source generation time in milliseconds. */\n sourceGenerationTimeMs: number;\n /** Shader module creation time in milliseconds. */\n moduleCreationTimeMs: number;\n /** Per-module source measurements. */\n modules: ShaderModuleCompilationDiagnostics[];\n /** Per-pipeline timing and status measurements. */\n pipelines: ShaderPipelineCompilationDiagnostics[];\n /** Configured pool size, capped to the number of pipelines in this batch. */\n maximumConcurrentPipelineCount: number;\n /** Largest number of createComputePipelineAsync calls active at once. */\n peakConcurrentPipelineCount: number;\n /** Batch pipeline compilation time in milliseconds; undefined until completed. */\n pipelineCompilationTimeMs?: number;\n /** Total batch preparation time in milliseconds; undefined until completed. */\n totalTimeMs?: number;\n /** Failure message; undefined without a compilation error. */\n error?: string;\n}\n\nexport interface RenderingDiagnostics {\n /** Label of the last complete target presented; undefined before the first image. */\n presentedTarget?: string;\n /** Whether the displayed target contains a complete image. Default false. */\n presentedComplete?: boolean;\n /** Resident target dimensions and allocated GPU bytes, including denoise resources. */\n targets?: { label: string; width: number; height: number; bytes: number }[];\n hdrPresentation?: {\n requested: boolean;\n active: boolean;\n /** Largest encoded RGB component sent to the HDR presentation pass. */\n peakDisplayValue?: number;\n };\n textureAtlas?: TextureAtlasStats;\n /** Material texture storage selection and estimated payload; driver allocation overhead is excluded. */\n materialTextures?: {\n requested: 'atlas' | 'auto';\n active: 'atlas' | 'bindless';\n /** Reason auto selected atlas; undefined when no fallback occurred. */\n fallbackReason?: string;\n textureCount: number;\n estimatedBytes: number;\n scale: number;\n /** Metadata buffer bytes; zero for atlas. */\n metadataBytes: number;\n /** Resource-table slots; zero for atlas. */\n resourceTableCapacity: number;\n /** Payload and metadata waiting for previous GPU submissions; zero when none. */\n retiredBytes: number;\n };\n /** Shader compilation measurements: current WebGPU batch or cumulative WebGL programs. */\n shaderCompilation?: ShaderCompilationDiagnostics;\n /** Light-selection table summary (WebGPU). */\n lightSampling?: {\n emissiveTriangles: number;\n activeChoices: number;\n totalWeight: number;\n domains: Record<\n 'environment' | 'infinite' | 'localAndEmissive',\n { count: number; weight: number; pmf: number }\n >;\n };\n /** Traversal stack capacities compiled into the current WebGPU shader. */\n bvh?: {\n tlasTraversalStackSize?: number;\n blasTraversalStackSize?: number;\n /** Last static preparation statistics, excluding queue and WASM loading time. */\n lastBuild?: { geometryCount: number; bvhTimeMs: number };\n };\n gpuTraceTiming?: {\n /** Last light-tracing batch time in milliseconds. Default undefined until measured. */ causticTimeMs?:number;\n /** Last photon-map batch time in milliseconds. Default undefined until measured. */ photonMappingTimeMs?:number;\n /** Photon emission, count, block scan, sum scan and scatter times in milliseconds. Default undefined until measured. */ photonStagesMs?:number[];\n /** Camera path kernel time in milliseconds. Default undefined until measured. */ pathTracingTimeMs?:number;\n tileTimeMs: number;\n tileTimePerSampleMs?: number;\n estimatedFullFrameTimeMs: number;\n tileCount: number;\n };\n}\n\nexport {DEFAULT_BEVEL_SAMPLES, MIN_BEVEL_SAMPLES, MAX_BEVEL_SAMPLES, DEFAULT_DIRECT_LIGHT_CANDIDATES, MIN_DIRECT_LIGHT_CANDIDATES, MAX_DIRECT_LIGHT_CANDIDATES, normalizeDirectLightCandidates, normalizeBevelSamples} from './renderingLimits.js';\n\n/** Shared scene resources; uploaded once per committed revision. */\nexport interface SceneResources {\n /** Returns true when scene geometry, materials, or instance transforms changed. */\n setMeshes(meshes: Mesh[], update?: {\n transforms?: readonly Mesh[];\n colors?: readonly Mesh[];\n geometries?: readonly Geometry[];\n materials?: readonly OpenPBRMaterial[];\n }): boolean;\n /** Changes the software memory guard used when packing material textures. */\n setTextureAtlasBudget(maxBytes: number): boolean;\n setLights(lights: SceneLight[]): void;\n setBackground(background?: SceneBackground): void;\n getDiagnostics(): RenderingDiagnostics;\n dispose(): void;\n readDepthSamples(area: DepthSampleArea): Promise<Float32Array | undefined>;\n pickSurface?(x: number, y: number, aspect?: number): Promise<SurfaceHit | null | undefined>;\n}\n/** Explicit execution and composition for one accumulation. */\nexport interface RenderPasses {\n isFirstFrame(): boolean;\n /** Discard accumulated samples and any asynchronous denoise output. */\n restartSamples(): void;\n trace(camera: Camera, maxSamples: number): boolean;\n drawPostProcess(): void;\n /** Apply display-only passes to the last composed image; absent on WebGL. */\n applyPostProcesses?(passes: readonly PostProcess[], render: Render, options?: readonly import('../Display.js').PostProcessOptions[], crop?: {width: number; height: number}): void;\n getAovTexture?(kind: 'diffuseColor' | 'specularColor' | 'depth'): GPUTexture | undefined;\n getOutputTexture?(kind: 'hdr' | 'display'): GPUTexture | undefined;\n /** Configure deterministic headless batches used by offline frame export. */\n setOfflineRenderOptions(options: {\n samplesPerBatch: number;\n deferPostProcess: boolean;\n sampleSequenceOffset: number;\n }): void;\n /** Store luminance second moments in the normal output during a pilot pass. */\n setVarianceMoments(enabled: boolean): void;\n /** Skip pixels once their independent final-pass target has been reached. */\n setAdaptiveSamplingTargets(targets?: {\n width: number;\n height: number;\n data: Float32Array;\n }): void;\n /** Generate final sample targets on GPU; WebGL returns undefined. */\n prepareOfflineAdaptiveSampling(\n options: OfflineAdaptiveSamplingOptions\n ): Promise<OfflineAdaptiveSamplingResult | undefined>;\n /** Enables extended-range float canvas presentation when the host supports it. */\n setHDROutputEnabled?(enabled: boolean): boolean;\n setToneMappingParams(params: ToneMappingParams): boolean;\n setSize(width: number, height: number): void;\n /**\n * Denoises the current image with an explicitly selected built-in or custom filter. Resolves whether the result is now displayed.\n */\n performDenoise?(\n denoiser: DenoiserHandle,\n alphaDenoiser?: OIDNWeb,\n schedule?: DenoiseSchedule,\n signal?: AbortSignal\n ): Promise<boolean>;\n /** Drops a denoise in flight; the next draw invalidates its output. */\n cancelDenoise?(): void;\n /** Keep the last completed OIDN image visible while static while-converging batches accumulate. */\n setPreserveDenoisedOutput?(preserve: boolean): void;\n getTotalSamplesRendered(): number;\n getDiagnostics(): RenderingDiagnostics;\n /** Waits for asynchronous timestamp diagnostics without changing samples. */\n flushDiagnostics(): Promise<void>;\n setShadowCatcherParams(color: ColorRGB, alpha: number): boolean;\n setBloomParams(opts: {\n intensity: number;\n threshold: number;\n radius: number;\n }): boolean;\n setOnSampleRendered(\n cb: (sampleCount: number, isFirstFrame: boolean, frameTime: number) => void\n ): void;\n setOutput(output: DisplayChannel): boolean;\n setAovDisplayOptions?(options: import('./aovDisplay.js').AovDisplayOptions): void;\n dispose(): void;\n aovReady?(kind: import('./aov.js').AovKind): boolean;\n /** Updates optional surface outputs without tracing beauty; false while compiling. */\n refineAovs?(camera: Camera, samples?: number): boolean;\n restartAovs?(): void;\n getAovSamples?(): number;\n readAov?(kind: import('./aov.js').AovKind): Promise<{width: number; height: number; data: Float32Array | Uint32Array}>;\n readOutput(kind: 'hdr' | 'denoised' | 'albedo' | 'normal'): Promise<{\n data: Float32Array;\n width: number;\n height: number;\n }>;\n}\n"]}
|
|
@@ -18,7 +18,7 @@ export declare function makeTileRender(gl?: WebGL2RenderingContext): {
|
|
|
18
18
|
setDesiredMsPerTile(time: number): void;
|
|
19
19
|
getDesiredMsPerTile(): number;
|
|
20
20
|
};
|
|
21
|
-
export declare function makeTileRenderWithPredict(): {
|
|
21
|
+
export declare function makeTileRenderWithPredict(minimumTileSize?: number): {
|
|
22
22
|
nextTile: () => {
|
|
23
23
|
xIndex: number;
|
|
24
24
|
yIndex: number;
|
|
@@ -37,7 +37,7 @@ export declare function makeTileRenderWithPredict(): {
|
|
|
37
37
|
setMaxTiles(maxTiles: number): void;
|
|
38
38
|
setDesiredMsPerTile(time: number): void;
|
|
39
39
|
needsUpdatePredicting(): void;
|
|
40
|
-
setLastTraceTime(time: number): void;
|
|
40
|
+
setLastTraceTime(time: number, timedColumns?: number, timedRows?: number): void;
|
|
41
41
|
getLastTraceTime(): number;
|
|
42
42
|
getDesiredMsPerTile(): number;
|
|
43
43
|
};
|
|
@@ -127,7 +127,7 @@ export function makeTileRender(gl) {
|
|
|
127
127
|
}
|
|
128
128
|
};
|
|
129
129
|
}
|
|
130
|
-
function getPredictResult(width, height, lastTraceTime, expectFrameTime, tilePixels, maxNumTiles) {
|
|
130
|
+
function getPredictResult(width, height, lastTraceTime, expectFrameTime, tilePixels, maxNumTiles, minimumTileSize, minimumPredictionSize) {
|
|
131
131
|
const maxTileSize = [width, height];
|
|
132
132
|
const rawCount = lastTraceTime > 0 ? expectFrameTime / lastTraceTime : 1;
|
|
133
133
|
// GPU cost is not perfectly linear with tile area: tiny probes include fixed
|
|
@@ -148,6 +148,11 @@ function getPredictResult(width, height, lastTraceTime, expectFrameTime, tilePix
|
|
|
148
148
|
samplesPerFrame *= Math.floor(newTileHeight / maxTileSize[1]);
|
|
149
149
|
}
|
|
150
150
|
newTileHeight = Math.min(newTileHeight, maxTileSize[1]);
|
|
151
|
+
// A compute dispatch still occupies a whole workgroup when fewer lanes
|
|
152
|
+
// are active. Splitting below that footprint repeats the fixed kernel cost
|
|
153
|
+
// and can make timestamp feedback progressively slow down a tiny render.
|
|
154
|
+
newTileWidth = Math.max(newTileWidth, Math.min(width, Math.max(minimumTileSize, minimumPredictionSize[0])));
|
|
155
|
+
newTileHeight = Math.max(newTileHeight, Math.min(height, Math.max(minimumTileSize, minimumPredictionSize[1])));
|
|
151
156
|
let newColumns = Math.round(width / newTileWidth);
|
|
152
157
|
let newRows = Math.round(height / newTileHeight);
|
|
153
158
|
newTileWidth = Math.ceil(width / newColumns);
|
|
@@ -181,7 +186,56 @@ function getInitialProbeSize(width, height) {
|
|
|
181
186
|
Math.min(height, Math.max(1, Math.round(Math.sqrt(initialProbePixels / aspectRatio))))
|
|
182
187
|
];
|
|
183
188
|
}
|
|
184
|
-
|
|
189
|
+
// Keep repeated kernel/longest-path cost below one fifth of the sample where
|
|
190
|
+
// possible. If that conflicts with responsiveness, prioritize the tile ceiling.
|
|
191
|
+
const maximumFixedCostShare = 0.2;
|
|
192
|
+
// A throughput-oriented ceiling still leaves over 5x margin below a 2s TDR.
|
|
193
|
+
// This is a prediction, not a guarantee for unusually expensive sample paths.
|
|
194
|
+
const maximumUnattainableTileMs = 350;
|
|
195
|
+
const unattainableBudgetTolerance = 1.1;
|
|
196
|
+
// Nearby grids amplify timestamp noise when extrapolating to zero pixels.
|
|
197
|
+
const minimumAffineAreaChange = 0.2;
|
|
198
|
+
function getUnattainableBudgetGrid(width, height, fixedMs, msPerPixel, minimumTileSize, maxNumTiles, samplesPerFrame) {
|
|
199
|
+
const areaCost = msPerPixel * width * height;
|
|
200
|
+
const maxColumns = Math.max(1, Math.floor(width / minimumTileSize));
|
|
201
|
+
const maxRows = Math.max(1, Math.floor(height / minimumTileSize));
|
|
202
|
+
// If the fixed cost alone exceeds the ceiling, no subdivision can meet it.
|
|
203
|
+
// Avoid multiplying an unavoidable stall by an ever-growing tile count.
|
|
204
|
+
const required = fixedMs < maximumUnattainableTileMs
|
|
205
|
+
? Math.ceil(areaCost / (maximumUnattainableTileMs - fixedMs)) : 1;
|
|
206
|
+
const minimumTiles = clamp(required, 1, maxColumns * maxRows);
|
|
207
|
+
let fewest;
|
|
208
|
+
let withinBoth;
|
|
209
|
+
const better = (candidate, best) => !best || candidate.count < best.count ||
|
|
210
|
+
(candidate.count === best.count &&
|
|
211
|
+
Math.abs(candidate.columns - candidate.rows) < Math.abs(best.columns - best.rows));
|
|
212
|
+
for (let columns = 1; columns <= Math.min(maxColumns, minimumTiles); columns++) {
|
|
213
|
+
const rows = Math.ceil(minimumTiles / columns);
|
|
214
|
+
if (rows > maxRows)
|
|
215
|
+
continue;
|
|
216
|
+
const count = columns * rows, candidate = { columns, rows, count };
|
|
217
|
+
if (better(candidate, fewest))
|
|
218
|
+
fewest = candidate;
|
|
219
|
+
const tileMs = fixedMs + areaCost / count;
|
|
220
|
+
const fixedShare = count * fixedMs / (count * fixedMs + areaCost);
|
|
221
|
+
if (tileMs <= maximumUnattainableTileMs && fixedShare <= maximumFixedCostShare &&
|
|
222
|
+
better(candidate, withinBoth))
|
|
223
|
+
withinBoth = candidate;
|
|
224
|
+
}
|
|
225
|
+
// Fewer tiles also minimize fixed cost. If even the fewest grid that meets
|
|
226
|
+
// the ceiling exceeds the share limit, no grid can satisfy both constraints.
|
|
227
|
+
let { columns, rows, count: numTiles } = (withinBoth ?? fewest);
|
|
228
|
+
if (numTiles > maxNumTiles) {
|
|
229
|
+
// Preserve the existing rectangular rounding of the public maxTiles cap.
|
|
230
|
+
numTiles = maxNumTiles;
|
|
231
|
+
columns = Math.ceil(Math.sqrt(numTiles));
|
|
232
|
+
rows = Math.ceil(numTiles / columns);
|
|
233
|
+
numTiles = columns * rows;
|
|
234
|
+
}
|
|
235
|
+
return { columns, rows, numTiles, tileWidth: Math.ceil(width / columns),
|
|
236
|
+
tileHeight: Math.ceil(height / rows), samplesPerFrame };
|
|
237
|
+
}
|
|
238
|
+
export function makeTileRenderWithPredict(minimumTileSize = 1) {
|
|
185
239
|
let numTiles = 1;
|
|
186
240
|
let currentTile = -1;
|
|
187
241
|
let lastTraceTime = -1;
|
|
@@ -202,6 +256,18 @@ export function makeTileRenderWithPredict() {
|
|
|
202
256
|
let columns = 0;
|
|
203
257
|
let rows = 0;
|
|
204
258
|
let maxNumTiles = Infinity;
|
|
259
|
+
// Validate a refinement against the grid that motivated it. A smaller
|
|
260
|
+
// dispatch can retain most of the longest path / fixed kernel cost.
|
|
261
|
+
let refinement;
|
|
262
|
+
let minimumPredictionSize = [0, 0];
|
|
263
|
+
let lastMeasurement;
|
|
264
|
+
let unattainableGrid;
|
|
265
|
+
function clearPredictionEvidence() {
|
|
266
|
+
refinement = undefined;
|
|
267
|
+
minimumPredictionSize = [0, 0];
|
|
268
|
+
lastMeasurement = undefined;
|
|
269
|
+
unattainableGrid = undefined;
|
|
270
|
+
}
|
|
205
271
|
function nextTile() {
|
|
206
272
|
currentTile++;
|
|
207
273
|
const avgTileTime = lastFrameTraceTimeValidCount > 0
|
|
@@ -212,7 +278,48 @@ export function makeTileRenderWithPredict() {
|
|
|
212
278
|
}
|
|
213
279
|
if (currentTile === 0 && timingRevision !== appliedTimingRevision) {
|
|
214
280
|
appliedTimingRevision = timingRevision;
|
|
215
|
-
const
|
|
281
|
+
const measured = lastFrameTraceTimeValidCount > 0;
|
|
282
|
+
let rollback;
|
|
283
|
+
if (measured && refinement) {
|
|
284
|
+
const areaRatio = refinement.grid.numTiles / numTiles;
|
|
285
|
+
// Require at least half of the area-proportional improvement, unless
|
|
286
|
+
// the new tile already fits the budget (with 10% timing tolerance).
|
|
287
|
+
if (avgTileTime > expectFrameTime * 1.1 &&
|
|
288
|
+
avgTileTime > refinement.time * (1 - (1 - areaRatio) * 0.5)) {
|
|
289
|
+
rollback = refinement;
|
|
290
|
+
minimumPredictionSize = [rollback.grid.tileWidth, rollback.grid.tileHeight];
|
|
291
|
+
}
|
|
292
|
+
refinement = undefined;
|
|
293
|
+
}
|
|
294
|
+
let result = rollback?.grid ?? getPredictResult(width, height, avgTileTime, expectFrameTime, lastTraceTime >= 0 ? tilePixels : getInitialProbeSize(width, height), maxNumTiles, minimumTileSize, minimumPredictionSize);
|
|
295
|
+
if (measured && columns > 0 && rows > 0 && !unattainableGrid) {
|
|
296
|
+
// Use nominal covered area, rather than ceil-rounded dispatch bounds:
|
|
297
|
+
// the interleaved grid covers every pixel exactly once per sample.
|
|
298
|
+
const point = { area: width * height / numTiles, time: avgTileTime };
|
|
299
|
+
if (lastMeasurement && Math.abs(point.area - lastMeasurement.area) >=
|
|
300
|
+
minimumAffineAreaChange * Math.max(point.area, lastMeasurement.area)) {
|
|
301
|
+
const slope = (point.time - lastMeasurement.time) / (point.area - lastMeasurement.area);
|
|
302
|
+
const fixed = point.time - slope * point.area;
|
|
303
|
+
if (Number.isFinite(slope) && slope > 0 && Number.isFinite(fixed) &&
|
|
304
|
+
fixed >= expectFrameTime * unattainableBudgetTolerance) {
|
|
305
|
+
unattainableGrid = getUnattainableBudgetGrid(width, height, fixed, slope, minimumTileSize, maxNumTiles, result.samplesPerFrame);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
lastMeasurement = point;
|
|
309
|
+
}
|
|
310
|
+
if (unattainableGrid) {
|
|
311
|
+
// Retain the decision until explicit invalidation. Re-fitting on its
|
|
312
|
+
// own probe/target grids can alternate counts as path costs fluctuate.
|
|
313
|
+
// Keep the original samplesPerFrame calculation independent of this policy.
|
|
314
|
+
result = { ...unattainableGrid, samplesPerFrame: result.samplesPerFrame };
|
|
315
|
+
refinement = undefined;
|
|
316
|
+
}
|
|
317
|
+
if (!unattainableGrid && !rollback && measured && result.numTiles > numTiles) {
|
|
318
|
+
refinement = {
|
|
319
|
+
grid: { tileWidth, tileHeight, columns, rows, numTiles, samplesPerFrame },
|
|
320
|
+
time: avgTileTime
|
|
321
|
+
};
|
|
322
|
+
}
|
|
216
323
|
lastFrameTotalTraceTime = 0;
|
|
217
324
|
lastFrameTraceTimeValidCount = 0;
|
|
218
325
|
tileWidth = result.tileWidth;
|
|
@@ -246,28 +353,42 @@ export function makeTileRenderWithPredict() {
|
|
|
246
353
|
currentTile = -1;
|
|
247
354
|
},
|
|
248
355
|
setSize(w, h) {
|
|
249
|
-
if (width !== w || height !== h)
|
|
356
|
+
if (width !== w || height !== h) {
|
|
250
357
|
timingRevision++;
|
|
358
|
+
clearPredictionEvidence();
|
|
359
|
+
lastTraceTime = -1;
|
|
360
|
+
lastFrameTotalTraceTime = 0;
|
|
361
|
+
lastFrameTraceTimeValidCount = 0;
|
|
362
|
+
}
|
|
251
363
|
width = w;
|
|
252
364
|
height = h;
|
|
253
365
|
},
|
|
254
366
|
setMaxTiles(maxTiles) {
|
|
255
|
-
if (maxNumTiles !== maxTiles)
|
|
367
|
+
if (maxNumTiles !== maxTiles) {
|
|
256
368
|
timingRevision++;
|
|
369
|
+
clearPredictionEvidence();
|
|
370
|
+
}
|
|
257
371
|
maxNumTiles = maxTiles;
|
|
258
372
|
},
|
|
259
373
|
setDesiredMsPerTile(time) {
|
|
260
|
-
if (expectFrameTime !== time)
|
|
374
|
+
if (expectFrameTime !== time) {
|
|
261
375
|
timingRevision++;
|
|
376
|
+
clearPredictionEvidence();
|
|
377
|
+
}
|
|
262
378
|
expectFrameTime = time;
|
|
263
379
|
},
|
|
264
380
|
needsUpdatePredicting() {
|
|
381
|
+
clearPredictionEvidence();
|
|
265
382
|
timingRevision++;
|
|
266
383
|
lastTraceTime = -1;
|
|
267
384
|
lastFrameTotalTraceTime = 0;
|
|
268
385
|
lastFrameTraceTimeValidCount = 0;
|
|
269
386
|
},
|
|
270
|
-
setLastTraceTime(time) {
|
|
387
|
+
setLastTraceTime(time, timedColumns = columns, timedRows = rows) {
|
|
388
|
+
// A timestamp can arrive after the next sample changed the grid. Only
|
|
389
|
+
// compare measurements of the grid currently being evaluated.
|
|
390
|
+
if (timedColumns !== columns || timedRows !== rows || !Number.isFinite(time) || time <= 0)
|
|
391
|
+
return;
|
|
271
392
|
timingRevision++;
|
|
272
393
|
lastTraceTime = time;
|
|
273
394
|
lastFrameTraceTimeValidCount++;
|