@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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sampleLight.glsl.js","sourceRoot":"","sources":["../../../../src/renderer/glsl/chunks/sampleLight.glsl.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAEvC,eAAe,IAAI,CAAA
|
|
1
|
+
{"version":3,"file":"sampleLight.glsl.js","sourceRoot":"","sources":["../../../../src/renderer/glsl/chunks/sampleLight.glsl.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,yBAAyB,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAEvC,eAAe,IAAI,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA2NjB,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6CT,CAAC","sourcesContent":["import emissive from './emissiveLight.glsl.js';\nimport { glsl } from '../../shader.js';\n\nexport default glsl`\n#ifdef NUM_LIGHTS\nvoid light_sample_sphere(\n in Light light,\n in vec3 shadingPoint,\n in vec2 samplePoint,\n inout LightSampleRec result\n) {\n vec3 toCenter = light.position - shadingPoint;\n float centerDistance = length(toCenter);\n if (light.radius <= 0.0) {\n if (centerDistance <= 1e-6) {\n result.direction = vec3(0.0, 0.0, 1.0);\n result.normal = vec3(0.0, 0.0, -1.0);\n result.dist = 0.0;\n result.pdf = 1.0;\n result.emission = vec3(0.0);\n result.isDelta = true;\n return;\n }\n result.direction = toCenter / centerDistance;\n result.normal = -result.direction;\n result.dist = centerDistance;\n result.pdf = 1.0;\n result.emission = light.emission / max(centerDistance * centerDistance, 1e-8);\n result.isDelta = true;\n return;\n }\n float radius = max(light.radius, 1e-6);\n result.isDelta = false;\n vec3 direction;\n\n if (centerDistance <= radius) {\n float z = 1.0 - 2.0 * samplePoint.x;\n float radial = sqrt(max(0.0, 1.0 - z * z));\n float azimuth = TWOPI * samplePoint.y;\n direction = vec3(radial * cos(azimuth), radial * sin(azimuth), z);\n result.pdf = INV4PI;\n }\n else {\n vec3 axis = toCenter / centerDistance;\n float sineLimitSquared = min(\n 1.0,\n radius * radius / (centerDistance * centerDistance)\n );\n float cosineLimit = sqrt(max(0.0, 1.0 - sineLimitSquared));\n // Keep the small solid angle and sampled sine without subtracting\n // nearly equal floats; otherwise small emitters produce irradiance bands.\n float oneMinusCosineLimit = sineLimitSquared / (1.0 + cosineLimit);\n float oneMinusCosine = samplePoint.x * oneMinusCosineLimit;\n float cosine = 1.0 - oneMinusCosine;\n float sine = sqrt(max(0.0, oneMinusCosine * (2.0 - oneMinusCosine)));\n float azimuth = TWOPI * samplePoint.y;\n vec3 tangent;\n vec3 bitangent;\n sampling_orthonormal_basis(axis, tangent, bitangent);\n direction = axis * cosine\n + tangent * (sine * cos(azimuth))\n + bitangent * (sine * sin(azimuth));\n result.pdf = 1.0 / max(TWOPI * oneMinusCosineLimit, 1e-8);\n }\n\n float projectedCenter = dot(direction, toCenter);\n float discriminant = projectedCenter * projectedCenter\n - dot(toCenter, toCenter) + radius * radius;\n float root = sqrt(max(0.0, discriminant));\n float nearDistance = projectedCenter - root;\n float farDistance = projectedCenter + root;\n result.dist = nearDistance > 1e-6 ? nearDistance : farDistance;\n result.direction = direction;\n vec3 surfacePoint = shadingPoint + direction * result.dist;\n result.normal = normalize(surfacePoint - light.position);\n result.emission = light.emission;\n}\n\nvoid light_apply_rect_texture(\n in Light light,\n in vec3 surfacePoint,\n in vec3 lowerLeft,\n inout LightSampleRec result\n) {\n#ifdef NUM_MAPS\n if (light.textureIndex >= 0) {\n float width = length(light.u);\n float height = length(light.v);\n vec3 relative = surfacePoint - lowerLeft;\n vec2 uv = vec2(\n dot(relative, light.u / width) / width,\n dot(relative, light.v / height) / height\n );\n result.emission *= sampleMap(light.textureIndex, uv).rgb;\n }\n#endif\n}\n\nvoid light_sample_rect(\n in Light light,\n in vec3 shadingPoint,\n in vec2 samplePoint,\n inout LightSampleRec result\n) {\n vec3 normal = normalize(cross(light.u, light.v));\n vec3 lowerLeft = light.position - 0.5 * (light.u + light.v);\n float spread = clamp(light.spread, 0.0, 1.0);\n\n if (spread <= 0.001) {\n float planeDistance = dot(normal, shadingPoint - light.position);\n vec3 surfacePoint = shadingPoint - normal * planeDistance;\n vec3 relative = surfacePoint - lowerLeft;\n float width = length(light.u);\n float height = length(light.v);\n vec2 uv = vec2(\n dot(relative, light.u / width) / width,\n dot(relative, light.v / height) / height\n );\n if (planeDistance <= 0.0 || any(lessThan(uv, vec2(0.0)))\n || any(greaterThan(uv, vec2(1.0)))) {\n result.emission = vec3(0.0);\n result.pdf = 0.0;\n return;\n }\n result.direction = -normal;\n result.dist = planeDistance;\n result.normal = normal;\n result.emission = light.emission;\n result.pdf = 1.0;\n result.isDelta = true;\n light_apply_rect_texture(light, surfacePoint, lowerLeft, result);\n return;\n }\n\n vec3 surfacePoint = lowerLeft\n + light.u * samplePoint.x\n + light.v * samplePoint.y;\n vec3 offset = surfacePoint - shadingPoint;\n float distanceSquared = dot(offset, offset);\n result.dist = sqrt(distanceSquared);\n result.direction = offset / result.dist;\n result.normal = normal;\n float emitterCosine = dot(-result.direction, normal);\n float spreadCosine = cos(0.5 * PI * spread);\n if (emitterCosine <= 0.0 || emitterCosine < spreadCosine) {\n result.emission = vec3(0.0);\n result.pdf = 0.0;\n return;\n }\n result.emission = light.emission;\n result.pdf = distanceSquared / max(light.area * emitterCosine, 1e-8);\n light_apply_rect_texture(light, surfacePoint, lowerLeft, result);\n}\n\nvoid light_sample_directional(\n in Light light,\n in vec3 shadingPoint,\n inout LightSampleRec result\n) {\n result.direction = normalize(-light.u);\n result.normal = -result.direction;\n result.emission = light.emission;\n result.dist = INF;\n result.pdf = 1.0;\n result.isDelta = true;\n}\n\nvoid light_sample_spot(\n in Light light,\n in vec3 shadingPoint,\n in vec2 samplePoint,\n inout LightSampleRec result\n) {\n light_sample_sphere(light, shadingPoint, samplePoint, result);\n vec3 surfacePoint = shadingPoint + result.direction * result.dist;\n result.emission *= evaluateSpotEmissionMultiplier(\n light,\n normalize(shadingPoint - surfacePoint)\n );\n}\n\nvoid sampleAnalyticLight(\n in Light light,\n in vec3 shadingPoint,\n in vec2 samplePoint,\n inout LightSampleRec result\n) {\n int lightType = int(light.type);\n#ifdef HAS_RECT_LIGHTS\n if (lightType == RECT_LIGHT) {\n light_sample_rect(light, shadingPoint, samplePoint, result);\n return;\n }\n#endif\n#ifdef HAS_SPHERE_LIGHTS\n if (lightType == SPHERE_LIGHT) {\n light_sample_sphere(light, shadingPoint, samplePoint, result);\n return;\n }\n#endif\n#ifdef HAS_SPOT_LIGHTS\n if (lightType == SPOT_LIGHT) {\n light_sample_spot(light, shadingPoint, samplePoint, result);\n return;\n }\n#endif\n#ifdef HAS_DIRECTIONAL_LIGHTS\n if (lightType == DIRECTIONAL_LIGHT) {\n light_sample_directional(light, shadingPoint, result);\n }\n#endif\n}\n#endif\n\nvoid sampleEnvLight(in vec2 samplePoint, inout LightSampleRec result) {\n vec2 uv;\n result.direction = sampleEnvmap(samplePoint, uv, result.pdf);\n result.emission = textureLinear(envMap, uv).rgb;\n result.dist = INF;\n}\n\n#ifdef HAS_EMISSIVE_LIGHTS\n${emissive}\n#endif\n\nvoid sampleLight(\n in vec3 shadingPoint,\n in vec3 randomSampleValue,\n inout LightSampleRec result,\n bool distByIntensity\n) {\n#ifdef HAS_EMISSIVE_LIGHTS\n sampleEmissiveSceneLight(shadingPoint,randomSampleValue,result);return;\n#endif\n result.sourceType=0;result.sourceIndex=-1;\n result.isDelta = false;\n float selector = randomSampleValue.z;\n bool choseEnvironment = false;\n#ifdef USE_ENVMAP\n choseEnvironment = selector < envLightSelectionPmf;\n if (choseEnvironment) {\n sampleEnvLight(randomSampleValue.xy, result);\n result.pdf *= envLightSelectionPmf;\n }\n#endif\n\n#ifdef NUM_LIGHTS\n if (!choseEnvironment) {\n int selectedIndex = NUM_LIGHTS - 1;\n for (int index = 0; index < NUM_LIGHTS; index++) {\n if (selector < fetchLight(index).selectionCdf) {\n selectedIndex = index;\n break;\n }\n }\n result.sourceType=2;result.sourceIndex=selectedIndex;\n Light selectedLight = fetchLight(selectedIndex);\n sampleAnalyticLight(\n selectedLight,\n shadingPoint,\n randomSampleValue.xy,\n result\n );\n result.pdf *= selectedLight.selectionPmf;\n }\n#endif\n}\n`;\n"]}
|
|
@@ -1,42 +1,64 @@
|
|
|
1
1
|
// Estimate the direct lighting integral using multiple importance sampling
|
|
2
2
|
// http://www.pbr-book.org/3ed-2018/Light_Transport_I_Surface_Reflection/Direct_Lighting.html#EstimatingtheDirectLightingIntegral
|
|
3
3
|
import { glsl } from '../../shader.js';
|
|
4
|
-
export
|
|
5
|
-
|
|
6
|
-
float
|
|
7
|
-
|
|
4
|
+
export function createSampleMaterialGlsl(fragments = {}, channelIndependentLight = false) {
|
|
5
|
+
return glsl `
|
|
6
|
+
float emissiveHitMisWeight(SurfaceInteraction si,Path path) {
|
|
7
|
+
|
|
8
|
+
float Ar=dot(si.faceNormal,-path.ray.d);
|
|
9
|
+
if(Ar<=0.0&&fetchMatData(si.materialIndex*MAT_DATA_SIZE+MAT_ROW_ALPHA).z<0.5)return 0.0;
|
|
10
|
+
#ifdef HAS_EMISSIVE_LIGHTS
|
|
11
|
+
if(!path.fromEye && emissiveWeightTotal>0.0) {
|
|
12
|
+
vec3 emission=fetchMatData(si.materialIndex*MAT_DATA_SIZE+MAT_ROW_EMISSION).rgb;
|
|
13
|
+
float value=dot(emission,vec3(.2126,.7152,.0722)),cosine=dot(si.faceNormal,-path.ray.d);
|
|
14
|
+
if(value>0.0&&cosine>0.0){float d=distance(si.position,path.ray.o);return aG(path.scatteringPdf,value/emissiveWeightTotal*d*d/cosine);}
|
|
15
|
+
}
|
|
16
|
+
#endif
|
|
17
|
+
return 1.0;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
vec3 qY(SurfaceInteraction si, OpenPbrResolvedMaterial mat, OpenPbrPreparedBsdf prepared, inout Path path, vec3 ffnormal, bool isSurface) {
|
|
21
|
+
float mz = 1.0;
|
|
22
|
+
vec3 ob = vec3(sample2D(aX(LIGHT_POSITION)), sample1D(aX(LIGHT_SELECT)));
|
|
8
23
|
|
|
9
24
|
LightSampleRec lightSample;
|
|
10
|
-
sampleLight(si.position,
|
|
11
|
-
|
|
25
|
+
sampleLight(si.position, ob, lightSample, false);${fragments['sample0'] ?? ''}
|
|
26
|
+
${channelIndependentLight ? /* glsl */ ` if (dispersionWavelengths == 1) {
|
|
27
|
+
lightSample.emission = sampling_spectral_rgb_filter(lightSample.emission, pathChannel);
|
|
28
|
+
}` : /* glsl */ ` lightSample.emission = sampling_spectral_rgb_filter(lightSample.emission, pathChannel);`}
|
|
12
29
|
|
|
13
30
|
vec3 lightDir = lightSample.direction;
|
|
14
|
-
vec3
|
|
15
|
-
float
|
|
31
|
+
vec3 sg = -path.ray.d;
|
|
32
|
+
float lightPdf = lightSample.pdf;
|
|
16
33
|
|
|
17
34
|
|
|
18
35
|
|
|
19
36
|
|
|
20
37
|
float cosThetaL = dot(ffnormal, lightDir);
|
|
21
38
|
#ifdef USE_COAT_NORMAL_FRAMES
|
|
22
|
-
if (
|
|
39
|
+
if (isSurface && mat.coatNormalEnabled) { cosThetaL = dot(mat.geometricNormal, lightDir); }
|
|
23
40
|
#endif
|
|
24
41
|
|
|
25
|
-
if (
|
|
42
|
+
if (lightPdf <= 0.0 || max(max(lightSample.emission.x, lightSample.emission.y), lightSample.emission.z) <= 0.0) {
|
|
26
43
|
return vec3(0.0);
|
|
27
44
|
}
|
|
28
45
|
|
|
29
|
-
|
|
46
|
+
${channelIndependentLight ? /* glsl */ `
|
|
47
|
+
|
|
48
|
+
if (dispersionWavelengths != 1) {
|
|
49
|
+
lightSample.emission = sampling_spectral_rgb_filter(lightSample.emission, pathChannel);
|
|
50
|
+
}
|
|
51
|
+
` : ''} float scatteringPdf = 0.0;
|
|
30
52
|
vec3 f = vec3(0.0);
|
|
31
|
-
if (
|
|
53
|
+
if (isSurface) {
|
|
32
54
|
if (cosThetaL <= 0.0 && mat.transmissionWeight <= 0.0 && mat.subsurfaceWeight <= 0.0) {
|
|
33
55
|
return vec3(0.0);
|
|
34
56
|
}
|
|
35
|
-
f =
|
|
57
|
+
f = openpbr_eval_prepared(prepared, lightDir, scatteringPdf);
|
|
36
58
|
}
|
|
37
59
|
else {
|
|
38
|
-
scatteringPdf =
|
|
39
|
-
dot(
|
|
60
|
+
scatteringPdf = ba(
|
|
61
|
+
dot(sg, lightDir),
|
|
40
62
|
si.mediumAnisotropy
|
|
41
63
|
);
|
|
42
64
|
f = vec3(scatteringPdf);
|
|
@@ -46,83 +68,89 @@ if (scatteringPdf <= 0.0 || max(max(f.x, f.y), f.z) <= 0.0) {
|
|
|
46
68
|
return vec3(0.0);
|
|
47
69
|
}
|
|
48
70
|
|
|
49
|
-
Ray
|
|
50
|
-
vec3
|
|
51
|
-
if (
|
|
52
|
-
const float
|
|
53
|
-
float
|
|
71
|
+
Ray oa;
|
|
72
|
+
vec3 eY = si.position + EPS * lightDir;
|
|
73
|
+
if (isSurface) {
|
|
74
|
+
const float shadowTerminatorCutoff = 0.1;
|
|
75
|
+
float dl = dot(si.normal, lightDir);
|
|
54
76
|
#ifdef USE_COAT_NORMAL_FRAMES
|
|
55
|
-
if (mat.coatNormalEnabled) {
|
|
77
|
+
if (mat.coatNormalEnabled) { dl = dot(si.faceNormal, lightDir); }
|
|
56
78
|
#endif
|
|
57
|
-
vec3 geometricNormal =
|
|
58
|
-
|
|
59
|
-
float
|
|
60
|
-
float
|
|
79
|
+
vec3 geometricNormal = dl < 0.0 ? -si.faceNormal : si.faceNormal;
|
|
80
|
+
dl = abs(dl);
|
|
81
|
+
float iw = dot(geometricNormal, lightDir);
|
|
82
|
+
float qo = dl < shadowTerminatorCutoff
|
|
61
83
|
? clamp(
|
|
62
|
-
2.0 - (
|
|
84
|
+
2.0 - (iw + dl) / shadowTerminatorCutoff,
|
|
63
85
|
0.0,
|
|
64
86
|
1.0
|
|
65
87
|
)
|
|
66
|
-
: clamp(1.0 -
|
|
67
|
-
|
|
88
|
+
: clamp(1.0 - iw / shadowTerminatorCutoff, 0.0, 1.0);
|
|
89
|
+
eY += si.shadowOffset * qo;
|
|
90
|
+
}
|
|
91
|
+
float rM=lightSample.dist-EPS;
|
|
92
|
+
vec3 qS=lightDir;
|
|
93
|
+
if(lightSample.sourceType==1){
|
|
94
|
+
vec3 endpoint=si.position+lightDir*lightSample.dist+EPS*lightSample.normal;
|
|
95
|
+
qS=normalize(endpoint-eY);rM=distance(endpoint,eY);
|
|
68
96
|
}
|
|
69
|
-
|
|
70
|
-
if (intersectSceneShadow(
|
|
97
|
+
initRay(oa, eY, qS);
|
|
98
|
+
if (intersectSceneShadow(oa, rM, si.triangleIndex)) {
|
|
71
99
|
return vec3(0.0);
|
|
72
100
|
}
|
|
73
101
|
|
|
74
102
|
#ifdef USE_ENVMAP
|
|
75
103
|
|
|
76
104
|
|
|
77
|
-
if (
|
|
78
|
-
vec4 background =
|
|
79
|
-
lightSample.emission =
|
|
105
|
+
if (isSurface && cosThetaL < 0.0 && lightSample.sourceType == 0) {
|
|
106
|
+
vec4 background = cq(oa.o, lightDir);
|
|
107
|
+
lightSample.emission = sampling_spectral_rgb_filter(background.rgb * background.a, pathChannel);
|
|
80
108
|
}
|
|
81
109
|
#endif
|
|
82
110
|
|
|
83
111
|
|
|
84
112
|
|
|
85
|
-
float
|
|
113
|
+
float misWeight = lightSample.isDelta
|
|
86
114
|
? 1.0
|
|
87
|
-
:
|
|
88
|
-
return
|
|
89
|
-
?
|
|
115
|
+
: aG(lightPdf, scatteringPdf);
|
|
116
|
+
${fragments['sample1'] ?? ''} return misWeight > 0.0
|
|
117
|
+
? misWeight * lightSample.emission * f / lightPdf
|
|
90
118
|
: vec3(0.0);
|
|
91
119
|
}
|
|
92
120
|
|
|
93
121
|
#ifdef USE_COAT_NORMAL_FRAMES
|
|
94
|
-
vec3
|
|
122
|
+
vec3 fQ(vec3 ru, vec3 face, vec3 view) {
|
|
95
123
|
bool front = dot(face, view) >= 0.0;
|
|
96
|
-
vec3
|
|
97
|
-
vec3
|
|
98
|
-
if (dot(
|
|
99
|
-
return
|
|
124
|
+
vec3 yc = front ? face : -face;
|
|
125
|
+
vec3 tv = front ? ru : -ru;
|
|
126
|
+
if (dot(ru, face) <= 0.0 || dot(tv, view) <= 1e-6) { return yc; }
|
|
127
|
+
return tv;
|
|
100
128
|
}
|
|
101
129
|
#endif
|
|
102
|
-
void
|
|
103
|
-
vec3
|
|
130
|
+
void nB(inout SurfaceInteraction si, OpenPbrResolvedMaterial mat, inout Path path) {
|
|
131
|
+
vec3 yh = vec3(sample2D(aX(BSDF_DIRECTION)), sample1D(aX(BSDF_LOBE)));
|
|
104
132
|
#ifdef USE_COAT_NORMAL_FRAMES
|
|
105
|
-
vec3
|
|
106
|
-
vec3
|
|
133
|
+
vec3 bC = si.faceNormal;
|
|
134
|
+
vec3 oh = si.normal;
|
|
107
135
|
#endif
|
|
108
|
-
float
|
|
109
|
-
float
|
|
136
|
+
float uk = -dot(si.faceNormal, path.ray.d);
|
|
137
|
+
float vH = -dot(si.normal, path.ray.d);
|
|
110
138
|
if ((mat.transmissionWeight > 0.0 || mat.subsurfaceWeight > 0.0) && mat.thinWalled) {
|
|
111
139
|
|
|
112
|
-
if (
|
|
140
|
+
if (uk < 0.0) {
|
|
113
141
|
si.faceNormal = -si.faceNormal;
|
|
114
|
-
|
|
142
|
+
uk = -uk;
|
|
115
143
|
}
|
|
116
|
-
if (
|
|
144
|
+
if (vH < 0.0) {
|
|
117
145
|
si.normal = -si.normal;
|
|
118
|
-
|
|
146
|
+
vH = -vH;
|
|
119
147
|
}
|
|
120
148
|
}
|
|
121
149
|
|
|
122
150
|
|
|
123
|
-
bool
|
|
124
|
-
float ndv =
|
|
125
|
-
vec3 normal =
|
|
151
|
+
bool rS = uk >= 0.0 && vH < 0.0;
|
|
152
|
+
float ndv = rS ? uk : vH;
|
|
153
|
+
vec3 normal = rS ? si.faceNormal : si.normal;
|
|
126
154
|
|
|
127
155
|
mat.inside = ndv <= 0.0 && !mat.thinWalled;
|
|
128
156
|
|
|
@@ -130,140 +158,152 @@ mat.relativeIor = ndv > 0.0 ? (1.0 / mat.specularIor) : mat.specularIor;
|
|
|
130
158
|
vec3 ffnormal = ndv >= 0.0 ? normal : -normal;
|
|
131
159
|
#ifdef USE_COAT_NORMAL_FRAMES
|
|
132
160
|
if (mat.coatNormalEnabled) {
|
|
133
|
-
vec3 view = -
|
|
134
|
-
float
|
|
135
|
-
mat.geometricNormal =
|
|
136
|
-
ffnormal =
|
|
137
|
-
mat.coatNormal =
|
|
138
|
-
mat.inside =
|
|
139
|
-
mat.relativeIor = (
|
|
161
|
+
vec3 view = -path.ray.d;
|
|
162
|
+
float gr = dot(bC, view);
|
|
163
|
+
mat.geometricNormal = gr >= 0.0 ? bC : -bC;
|
|
164
|
+
ffnormal = fQ(oh, bC, view);
|
|
165
|
+
mat.coatNormal = fQ(si.coatNormal, bC, view);
|
|
166
|
+
mat.inside = gr <= 0.0 && !mat.thinWalled;
|
|
167
|
+
mat.relativeIor = (gr > 0.0 || mat.thinWalled) ? 1.0 / mat.specularIor : mat.specularIor;
|
|
140
168
|
}
|
|
141
169
|
#endif
|
|
142
170
|
|
|
143
171
|
|
|
144
172
|
float scatteringPdf;
|
|
145
|
-
vec3
|
|
146
|
-
|
|
147
|
-
bool
|
|
148
|
-
bool
|
|
149
|
-
|
|
173
|
+
vec3 di;
|
|
174
|
+
path.scatteringIsDelta = false;
|
|
175
|
+
bool mediumSampled = false;
|
|
176
|
+
bool hE = false;
|
|
177
|
+
OpenPbrPreparedBsdf prepared;
|
|
150
178
|
|
|
151
179
|
#ifdef HAS_MEDIUM
|
|
152
180
|
int mediumType = si.mediumType;
|
|
153
|
-
float d = distance(si.position,
|
|
154
|
-
vec3
|
|
181
|
+
float d = distance(si.position, path.ray.o);
|
|
182
|
+
vec3 pd = path.ray.o;
|
|
155
183
|
vec3 extinction = si.mediumExtinction;
|
|
156
184
|
vec3 scattering = min(si.mediumScattering, extinction);
|
|
157
|
-
float
|
|
158
|
-
if (mediumType > 0 &&
|
|
185
|
+
float vD = max(max(extinction.x, extinction.y), extinction.z);
|
|
186
|
+
if (mediumType > 0 && vD > 0.0) {
|
|
159
187
|
|
|
160
188
|
|
|
161
189
|
|
|
162
190
|
|
|
163
|
-
int
|
|
164
|
-
float
|
|
165
|
-
float
|
|
166
|
-
? min(-log(max(
|
|
191
|
+
int oW = min(int(sample1D(aX(MEDIUM_CHANNEL)) * 3.0), 2);
|
|
192
|
+
float fP = extinction[oW];
|
|
193
|
+
float iO = fP > 0.0
|
|
194
|
+
? min(-log(max(sample1D(aX(MEDIUM_DISTANCE)), 1e-7)) / fP, d)
|
|
167
195
|
: d;
|
|
168
|
-
|
|
169
|
-
vec3 transmittance = exp(-extinction *
|
|
170
|
-
vec3
|
|
196
|
+
mediumSampled = iO < d;
|
|
197
|
+
vec3 transmittance = exp(-extinction * iO);
|
|
198
|
+
vec3 density = mediumSampled
|
|
171
199
|
? extinction * transmittance
|
|
172
200
|
: transmittance;
|
|
173
|
-
float
|
|
174
|
-
(
|
|
201
|
+
float mediumPdf = max(
|
|
202
|
+
(density.x + density.y + density.z) / 3.0,
|
|
175
203
|
1e-8
|
|
176
204
|
);
|
|
177
|
-
if (
|
|
178
|
-
|
|
205
|
+
if (mediumSampled) {
|
|
206
|
+
path.beta *= transmittance * scattering / mediumPdf;
|
|
179
207
|
|
|
180
|
-
|
|
181
|
-
si.position = aa.ray.o;
|
|
182
|
-
aa.li += ta(si, mat, prepared, aa, ffnormal, false) * aa.beta;
|
|
208
|
+
if (all(equal(path.beta, vec3(0.0)))) { path.abort = true; return; }
|
|
183
209
|
|
|
210
|
+
path.ray.o = pd + iO * path.ray.d;
|
|
211
|
+
si.position = path.ray.o;
|
|
184
212
|
|
|
185
|
-
|
|
186
|
-
-
|
|
213
|
+
si.triangleIndex = -1;
|
|
214
|
+
si.instanceIndex = -1;
|
|
215
|
+
path.li += qY(si, mat, prepared, path, ffnormal, false) * path.beta;
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
di = dQ(
|
|
219
|
+
-path.ray.d,
|
|
187
220
|
si.mediumAnisotropy,
|
|
188
|
-
|
|
221
|
+
sample2D(aX(PHASE_DIRECTION))
|
|
189
222
|
);
|
|
190
|
-
scatteringPdf =
|
|
191
|
-
dot(
|
|
223
|
+
scatteringPdf = ba(
|
|
224
|
+
dot(di, -path.ray.d),
|
|
192
225
|
si.mediumAnisotropy
|
|
193
226
|
);
|
|
194
227
|
}
|
|
195
228
|
else {
|
|
196
|
-
|
|
229
|
+
path.beta *= transmittance / mediumPdf;
|
|
230
|
+
|
|
231
|
+
if (all(equal(path.beta, vec3(0.0)))) { path.abort = true; return; }
|
|
197
232
|
}
|
|
198
233
|
}
|
|
199
234
|
#endif
|
|
200
235
|
|
|
201
236
|
|
|
202
|
-
if (!
|
|
203
|
-
|
|
237
|
+
if (!mediumSampled) {
|
|
238
|
+
|
|
239
|
+
vec3 surfaceEmission = sampling_spectral_rgb_filter(mat.emission, pathChannel);
|
|
240
|
+
${fragments['sample2'] ?? ''}path.li += emissiveHitMisWeight(si,path) * surfaceEmission * path.beta;${fragments['sample3'] ?? ''}
|
|
204
241
|
if (mat.materialType == UNLIT) {
|
|
205
|
-
|
|
242
|
+
path.abort = true;
|
|
206
243
|
return;
|
|
207
244
|
}
|
|
208
|
-
vec3
|
|
245
|
+
vec3 rP = vec3(0.0);
|
|
209
246
|
#ifdef USE_TANGENT
|
|
210
|
-
|
|
247
|
+
rP = si.tangent;
|
|
211
248
|
#endif
|
|
212
249
|
mat.directionTangent = si.directionTangent;
|
|
213
250
|
mat.directionBitangent = si.directionBitangent;
|
|
214
251
|
mat.geometryTangent = si.geometryTangent;
|
|
215
252
|
mat.geometryBitangent = si.geometryBitangent;
|
|
216
|
-
prepared =
|
|
217
|
-
|
|
218
|
-
|
|
253
|
+
prepared = bX(rP, mat, -path.ray.d, ffnormal);
|
|
254
|
+
path.li += qY(si, mat, prepared, path, ffnormal, true) * path.beta;
|
|
255
|
+
${fragments['sample4'] ?? ''}
|
|
219
256
|
bool isNextRefraction;
|
|
220
|
-
vec3 f =
|
|
257
|
+
vec3 f = dr(
|
|
221
258
|
prepared,
|
|
222
|
-
|
|
223
|
-
|
|
259
|
+
yh,
|
|
260
|
+
di,
|
|
224
261
|
scatteringPdf,
|
|
225
262
|
isNextRefraction
|
|
226
263
|
);
|
|
227
264
|
|
|
228
|
-
|
|
265
|
+
path.scatteringIsDelta = !prepared.material.thinWalled &&
|
|
229
266
|
abs(prepared.material.relativeIor - 1.0) <= 1e-6 &&
|
|
230
267
|
prepared.probabilities[OPENPBR_LOBE_TRANSMISSION] >= 1.0 - 1e-6;
|
|
231
268
|
|
|
232
269
|
|
|
233
270
|
|
|
234
271
|
if (!(scatteringPdf > 0.0) || any(isnan(f)) || any(isinf(f)) ||
|
|
235
|
-
dot(
|
|
236
|
-
|
|
237
|
-
|
|
272
|
+
dot(di, di) < 0.5) {
|
|
273
|
+
path.scatteringPdf = 0.0;
|
|
274
|
+
path.abort = true;
|
|
238
275
|
return;
|
|
239
276
|
}
|
|
240
|
-
|
|
241
|
-
|
|
277
|
+
${fragments['sample5'] ?? ''} path.beta *= f / scatteringPdf;
|
|
278
|
+
|
|
279
|
+
if (all(equal(path.beta, vec3(0.0)))) { path.abort = true; return; }
|
|
280
|
+
hE = !mat.thinWalled &&
|
|
242
281
|
isNextRefraction;
|
|
243
|
-
|
|
282
|
+
path.isNextRefraction = isNextRefraction;
|
|
244
283
|
|
|
245
284
|
|
|
246
|
-
|
|
285
|
+
path.ray.o = si.position + EPS * di;
|
|
247
286
|
#ifdef USE_COAT_NORMAL_FRAMES
|
|
248
|
-
if (mat.coatNormalEnabled) {
|
|
287
|
+
if (mat.coatNormalEnabled) { path.ray.o = si.position + EPS * (dot(bC, di) >= 0.0 ? bC : -bC); }
|
|
249
288
|
#endif
|
|
250
289
|
}
|
|
251
290
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
if (
|
|
255
|
-
|
|
291
|
+
path.scatteringPdf = scatteringPdf;
|
|
292
|
+
initRay(path.ray, path.ray.o, di);
|
|
293
|
+
if (mediumSampled) {${fragments['sample6'] ?? ''}
|
|
294
|
+
path.isNextRefraction = false;
|
|
256
295
|
}
|
|
257
|
-
|
|
296
|
+
path.fromEye = false;
|
|
258
297
|
|
|
259
298
|
#ifdef HAS_MEDIUM
|
|
260
299
|
|
|
261
300
|
|
|
262
|
-
if (!
|
|
263
|
-
if (
|
|
301
|
+
if (!mediumSampled && hE && mat.mediumType > 0) {
|
|
302
|
+
if (uk >= 0.0) {
|
|
264
303
|
si.mediumType = mat.mediumType;
|
|
265
304
|
si.mediumExtinction = mat.mediumExtinction;
|
|
266
305
|
si.mediumScattering = mat.mediumScattering;
|
|
306
|
+
path.scatteringMediumEntered = path.scatteringMediumEntered || any(greaterThan(mat.mediumScattering, vec3(0.0)));
|
|
267
307
|
si.mediumAnisotropy = mat.mediumAnisotropy;
|
|
268
308
|
}
|
|
269
309
|
else {
|
|
@@ -276,4 +316,6 @@ si.mediumAnisotropy = 0.0;
|
|
|
276
316
|
#endif
|
|
277
317
|
}
|
|
278
318
|
`;
|
|
319
|
+
}
|
|
320
|
+
export default createSampleMaterialGlsl();
|
|
279
321
|
//# sourceMappingURL=sampleMaterial.glsl.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sampleMaterial.glsl.js","sourceRoot":"","sources":["../../../../src/renderer/glsl/chunks/sampleMaterial.glsl.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,iIAAiI;AAEjI,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACvC,eAAe,IAAI,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkRlB,CAAC","sourcesContent":["// Estimate the direct lighting integral using multiple importance sampling\n// http://www.pbr-book.org/3ed-2018/Light_Transport_I_Surface_Reflection/Direct_Lighting.html#EstimatingtheDirectLightingIntegral\n\nimport { glsl } from '../../shader.js';\nexport default glsl`\nvec3 DirectLight(SurfaceInteraction si, OpenPbrResolvedMaterial mat, OpenPbrPreparedBsdf prepared, inout Path path, vec3 ffnormal, bool isSurface) {\n float occluded = 1.0;\n vec3 lightRnd = vec3(sample2D(bounceDim(LIGHT_POSITION)), sample1D(bounceDim(LIGHT_SELECT)));\n\n LightSampleRec lightSample;\n sampleLight(si.position, lightRnd, lightSample, false);\n lightSample.emission = sampling_spectral_rgb_filter(lightSample.emission, pathWavelength);\n\n vec3 lightDir = lightSample.direction;\n vec3 viewDir = -path.ray.d;\n float lightPdf = lightSample.pdf;\n // Opaque surfaces are rendered two-sided by the core renderer. Use the\n // face-forward shading normal here as well, otherwise the early-out rejects\n // every direct-light sample seen from the back of a triangle (for example\n // the inside of an imported room wall).\n float cosThetaL = dot(ffnormal, lightDir);\n#ifdef USE_COAT_NORMAL_FRAMES\n if (isSurface && mat.coatNormalEnabled) { cosThetaL = dot(mat.geometricNormal, lightDir); }\n#endif\n\n if (lightPdf <= 0.0 || max(max(lightSample.emission.x, lightSample.emission.y), lightSample.emission.z) <= 0.0) {\n return vec3(0.0);\n }\n\n float scatteringPdf = 0.0;\n vec3 f = vec3(0.0);\n if (isSurface) {\n if (cosThetaL <= 0.0 && mat.transmissionWeight <= 0.0 && mat.subsurfaceWeight <= 0.0) {\n return vec3(0.0);\n }\n f = openpbr_eval_prepared(prepared, lightDir, scatteringPdf);\n }\n else {\n scatteringPdf = sampling_henyey_greenstein_phase(\n dot(viewDir, lightDir),\n si.mediumAnisotropy\n );\n f = vec3(scatteringPdf);\n }\n\n if (scatteringPdf <= 0.0 || max(max(f.x, f.y), f.z) <= 0.0) {\n return vec3(0.0);\n }\n\n Ray lightRay;\n vec3 shadowOrigin = si.position + EPS * lightDir;\n if (isSurface) {\n const float shadowTerminatorCutoff = 0.1;\n float normalLight = dot(si.normal, lightDir);\n#ifdef USE_COAT_NORMAL_FRAMES\n if (mat.coatNormalEnabled) { normalLight = dot(si.faceNormal, lightDir); }\n#endif\n vec3 geometricNormal = normalLight < 0.0 ? -si.faceNormal : si.faceNormal;\n normalLight = abs(normalLight);\n float geometricLight = dot(geometricNormal, lightDir);\n float offsetAmount = normalLight < shadowTerminatorCutoff\n ? clamp(\n 2.0 - (geometricLight + normalLight) / shadowTerminatorCutoff,\n 0.0,\n 1.0\n )\n : clamp(1.0 - geometricLight / shadowTerminatorCutoff, 0.0, 1.0);\n shadowOrigin += si.shadowOffset * offsetAmount;\n }\n initRay(lightRay, shadowOrigin, lightDir);\n if (intersectSceneShadow(lightRay, lightSample.dist - EPS, si.triangleIndex)) {\n return vec3(0.0);\n }\n\n#ifdef USE_ENVMAP\n // Match the endpoint used by a BSDF-sampled surface transmission, including\n // a separately displayed or grounded background and its coverage.\n if (isSurface && cosThetaL < 0.0 && lightRnd.z < envLightSelectionPmf) {\n vec4 background = sampleBackgroundFromRay(lightRay.o, lightDir);\n lightSample.emission = sampling_spectral_rgb_filter(background.rgb * background.a, pathWavelength);\n }\n#endif\n\n // Delta lights cannot be sampled by the BSDF strategy, so their MIS weight\n // is exactly one even when their light-selection PMF is small.\n float misWeight = lightSample.isDelta\n ? 1.0\n : sampling_power_heuristic(lightPdf, scatteringPdf);\n return misWeight > 0.0\n ? misWeight * lightSample.emission * f / lightPdf\n : vec3(0.0);\n}\n\n#ifdef USE_COAT_NORMAL_FRAMES\nvec3 coat_frame_normal(vec3 inputNormal, vec3 face, vec3 view) {\n bool front = dot(face, view) >= 0.0;\n vec3 ffFace = front ? face : -face;\n vec3 ffInput = front ? inputNormal : -inputNormal;\n if (dot(inputNormal, face) <= 0.0 || dot(ffInput, view) <= 1e-6) { return ffFace; }\n return ffInput;\n}\n#endif\nvoid SampleMaterial(inout SurfaceInteraction si, OpenPbrResolvedMaterial mat, inout Path path) {\n vec3 matRnd = vec3(sample2D(bounceDim(BSDF_DIRECTION)), sample1D(bounceDim(BSDF_LOBE)));\n#ifdef USE_COAT_NORMAL_FRAMES\n vec3 originalFace = si.faceNormal;\n vec3 originalNormal = si.normal;\n#endif\n float ndv1 = -dot(si.faceNormal, path.ray.d);\n float ndv2 = -dot(si.normal, path.ray.d);\n if ((mat.transmissionWeight > 0.0 || mat.subsurfaceWeight > 0.0) && mat.thinWalled) {\n // Always treat thin material as entering medium\n if (ndv1 < 0.0) {\n si.faceNormal = -si.faceNormal;\n ndv1 = -ndv1;\n }\n if (ndv2 < 0.0) {\n si.normal = -si.normal;\n ndv2 = -ndv2;\n }\n }\n // In same edge cases normal is not torwards the camera while we can still see the face.\n // We need to choose faceNormal in this case.\n bool useFaceN = ndv1 >= 0.0 && ndv2 < 0.0;\n float ndv = useFaceN ? ndv1 : ndv2;\n vec3 normal = useFaceN ? si.faceNormal : si.normal;\n\n mat.inside = ndv <= 0.0 && !mat.thinWalled;\n // In or out\n mat.relativeIor = ndv > 0.0 ? (1.0 / mat.specularIor) : mat.specularIor;\n vec3 ffnormal = ndv >= 0.0 ? normal : -normal;\n#ifdef USE_COAT_NORMAL_FRAMES\n if (mat.coatNormalEnabled) {\n vec3 view = -path.ray.d;\n float geometricView = dot(originalFace, view);\n mat.geometricNormal = geometricView >= 0.0 ? originalFace : -originalFace;\n ffnormal = coat_frame_normal(originalNormal, originalFace, view);\n mat.coatNormal = coat_frame_normal(si.coatNormal, originalFace, view);\n mat.inside = geometricView <= 0.0 && !mat.thinWalled;\n mat.relativeIor = (geometricView > 0.0 || mat.thinWalled) ? 1.0 / mat.specularIor : mat.specularIor;\n }\n#endif\n\n\n float scatteringPdf;\n vec3 scatterDir;\n path.scatteringIsDelta = false;\n bool mediumSampled = false;\n bool crossedBoundary = false;\n OpenPbrPreparedBsdf prepared;\n\n#ifdef HAS_MEDIUM\n int mediumType = si.mediumType;\n float d = distance(si.position, path.ray.o);\n vec3 segmentOrigin = path.ray.o;\n vec3 extinction = si.mediumExtinction;\n vec3 scattering = min(si.mediumScattering, extinction);\n float majorant = max(max(extinction.x, extinction.y), extinction.z);\n if (mediumType > 0 && majorant > 0.0) {\n // Sample one RGB extinction channel and divide by the mixture PDF. This\n // is the homogeneous-medium estimator used by PBRT and avoids the very\n // large exp((majorant - extinction) * distance) weights produced by\n // majorant tracking when OpenPBR SSS radii differ strongly by channel.\n int mediumChannel = min(int(sample1D(bounceDim(MEDIUM_CHANNEL)) * 3.0), 2);\n float channelExtinction = extinction[mediumChannel];\n float scatterDist = channelExtinction > 0.0\n ? min(-log(max(sample1D(bounceDim(MEDIUM_DISTANCE)), 1e-7)) / channelExtinction, d)\n : d;\n mediumSampled = scatterDist < d;\n vec3 transmittance = exp(-extinction * scatterDist);\n vec3 density = mediumSampled\n ? extinction * transmittance\n : transmittance;\n float mediumPdf = max(\n (density.x + density.y + density.z) / 3.0,\n 1e-8\n );\n if (mediumSampled) {\n path.beta *= transmittance * scattering / mediumPdf;\n // Move from the start of the segment, not from its end surface.\n path.ray.o = segmentOrigin + scatterDist * path.ray.d;\n si.position = path.ray.o;\n path.li += DirectLight(si, mat, prepared, path, ffnormal, false) * path.beta;\n\n // Pick a new direction based on the phase function\n scatterDir = sampling_henyey_greenstein(\n -path.ray.d,\n si.mediumAnisotropy,\n sample2D(bounceDim(PHASE_DIRECTION))\n );\n scatteringPdf = sampling_henyey_greenstein_phase(\n dot(scatterDir, -path.ray.d),\n si.mediumAnisotropy\n );\n }\n else {\n path.beta *= transmittance / mediumPdf;\n }\n }\n#endif\n\n // Direct lighting\n if (!mediumSampled) {\n path.li += mat.emission * path.beta;\n if (mat.materialType == UNLIT) {\n path.abort = true;\n return;\n }\n vec3 surfaceTangent = vec3(0.0);\n#ifdef USE_TANGENT\n surfaceTangent = si.tangent;\n#endif\n mat.directionTangent = si.directionTangent;\n mat.directionBitangent = si.directionBitangent;\n mat.geometryTangent = si.geometryTangent;\n mat.geometryBitangent = si.geometryBitangent;\n prepared = openpbr_prepare(surfaceTangent, mat, -path.ray.d, ffnormal);\n path.li += DirectLight(si, mat, prepared, path, ffnormal, true) * path.beta;\n // Sample BSDF for color and outgoing direction\n bool isNextRefraction;\n vec3 f = openpbr_sample_prepared(\n prepared,\n matRnd,\n scatterDir,\n scatteringPdf,\n isNextRefraction\n );\n // Null-boundary transmission is discrete and has no NEE competitor.\n path.scatteringIsDelta = !prepared.material.thinWalled &&\n abs(prepared.material.relativeIor - 1.0) <= 1e-6 &&\n prepared.probabilities[OPENPBR_LOBE_TRANSMISSION] >= 1.0 - 1e-6;\n // Match WebGPU: rejected VNDF/refraction proposals have no continuation.\n // Tracing their fallback direction with the incoming throughput invents\n // light paths, especially after total internal reflection inside glass.\n if (!(scatteringPdf > 0.0) || any(isnan(f)) || any(isinf(f)) ||\n dot(scatterDir, scatterDir) < 0.5) {\n path.scatteringPdf = 0.0;\n path.abort = true;\n return;\n }\n path.beta *= f / scatteringPdf;\n crossedBoundary = !mat.thinWalled &&\n isNextRefraction;\n path.isNextRefraction = isNextRefraction;\n // TODO prefer the opaque surface when transmission surface and opaque surface are overlapped.\n // Or the ray go out from transmission material will miss the opque surface.\n path.ray.o = si.position + EPS * scatterDir;\n#ifdef USE_COAT_NORMAL_FRAMES\n if (mat.coatNormalEnabled) { path.ray.o = si.position + EPS * (dot(originalFace, scatterDir) >= 0.0 ? originalFace : -originalFace); }\n#endif\n }\n\n path.scatteringPdf = scatteringPdf;\n initRay(path.ray, path.ray.o, scatterDir);\n if (mediumSampled) {\n path.isNextRefraction = false;\n }\n path.fromEye = false;\n\n#ifdef HAS_MEDIUM\n // A reflected ray stays in its current medium. Only a sampled transmission\n // event crosses the boundary of a medium-bearing closed mesh.\n if (!mediumSampled && crossedBoundary && mat.mediumType > 0) {\n if (ndv1 >= 0.0) {\n si.mediumType = mat.mediumType;\n si.mediumExtinction = mat.mediumExtinction;\n si.mediumScattering = mat.mediumScattering;\n si.mediumAnisotropy = mat.mediumAnisotropy;\n }\n else {\n si.mediumType = 0;\n si.mediumExtinction = vec3(0.0);\n si.mediumScattering = vec3(0.0);\n si.mediumAnisotropy = 0.0;\n }\n }\n#endif\n}\n`;\n"]}
|
|
1
|
+
{"version":3,"file":"sampleMaterial.glsl.js","sourceRoot":"","sources":["../../../../src/renderer/glsl/chunks/sampleMaterial.glsl.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,iIAAiI;AAEjI,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACvC,MAAM,UAAU,wBAAwB,CAAC,YAA8C,EAAE,EAAE,uBAAuB,GAAG,KAAK;IAAI,OAAO,IAAI,CAAA;;;;;;;;;;;;;;;;;;;;mDAoB9E,SAAS,CAAC,SAAS,CAAC,IAAI,EAAE;EACnF,uBAAuB,CAAC,CAAC,CAAC,UAAU,CAAC;;EAEnC,CAAC,CAAC,CAAC,UAAU,CAAC,2FAA2F;;;;;;;;;;;;;;;;;;EAkB3G,uBAAuB,CAAC,CAAC,CAAC,UAAU,CAAC;;;;;CAKtC,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiEJ,SAAS,CAAC,SAAS,CAAC,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4HtB,SAAS,CAAC,SAAS,CAAC,IAAI,EAAE,0EAA0E,SAAS,CAAC,SAAS,CAAC,IAAI,EAAE;;;;;;;;;;;;;;;EAelI,SAAS,CAAC,SAAS,CAAC,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;EAsB1B,SAAS,CAAC,SAAS,CAAC,IAAI,EAAE;;;;;;;;;;;;;;;;sBAgBJ,SAAS,CAAC,SAAS,CAAC,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;CAyBjD,CAAC;AACF,CAAC;AACD,eAAe,wBAAwB,EAAE,CAAC","sourcesContent":["// Estimate the direct lighting integral using multiple importance sampling\n// http://www.pbr-book.org/3ed-2018/Light_Transport_I_Surface_Reflection/Direct_Lighting.html#EstimatingtheDirectLightingIntegral\n\nimport { glsl } from '../../shader.js';\nexport function createSampleMaterialGlsl(fragments: Readonly<Record<string, string>> = {}, channelIndependentLight = false) { return glsl`\nfloat emissiveHitMisWeight(SurfaceInteraction si,Path path) {\n // Secondary intersections remain two-sided, but one-sided emission does not.\n float facing=dot(si.faceNormal,-path.ray.d);\n if(facing<=0.0&&fetchMatData(si.materialIndex*MAT_DATA_SIZE+MAT_ROW_ALPHA).z<0.5)return 0.0;\n#ifdef HAS_EMISSIVE_LIGHTS\n if(!path.fromEye && emissiveWeightTotal>0.0) {\n vec3 emission=fetchMatData(si.materialIndex*MAT_DATA_SIZE+MAT_ROW_EMISSION).rgb;\n float value=dot(emission,vec3(.2126,.7152,.0722)),cosine=dot(si.faceNormal,-path.ray.d);\n if(value>0.0&&cosine>0.0){float d=distance(si.position,path.ray.o);return sampling_power_heuristic(path.scatteringPdf,value/emissiveWeightTotal*d*d/cosine);}\n }\n#endif\n return 1.0;\n}\n\nvec3 DirectLight(SurfaceInteraction si, OpenPbrResolvedMaterial mat, OpenPbrPreparedBsdf prepared, inout Path path, vec3 ffnormal, bool isSurface) {\n float occluded = 1.0;\n vec3 lightRnd = vec3(sample2D(bounceDim(LIGHT_POSITION)), sample1D(bounceDim(LIGHT_SELECT)));\n\n LightSampleRec lightSample;\n sampleLight(si.position, lightRnd, lightSample, false);${fragments['sample0'] ?? ''}\n${channelIndependentLight ? /* glsl */ ` if (dispersionWavelengths == 1) {\n lightSample.emission = sampling_spectral_rgb_filter(lightSample.emission, pathChannel);\n }` : /* glsl */ ` lightSample.emission = sampling_spectral_rgb_filter(lightSample.emission, pathChannel);`}\n\n vec3 lightDir = lightSample.direction;\n vec3 viewDir = -path.ray.d;\n float lightPdf = lightSample.pdf;\n // Opaque surfaces are rendered two-sided by the core renderer. Use the\n // face-forward shading normal here as well, otherwise the early-out rejects\n // every direct-light sample seen from the back of a triangle (for example\n // the inside of an imported room wall).\n float cosThetaL = dot(ffnormal, lightDir);\n#ifdef USE_COAT_NORMAL_FRAMES\n if (isSurface && mat.coatNormalEnabled) { cosThetaL = dot(mat.geometricNormal, lightDir); }\n#endif\n\n if (lightPdf <= 0.0 || max(max(lightSample.emission.x, lightSample.emission.y), lightSample.emission.z) <= 0.0) {\n return vec3(0.0);\n }\n\n${channelIndependentLight ? /* glsl */ ` // Test the full emission before filtering, so black spectral components\n // still consume the same visibility walk and random stream.\n if (dispersionWavelengths != 1) {\n lightSample.emission = sampling_spectral_rgb_filter(lightSample.emission, pathChannel);\n }\n` : ''} float scatteringPdf = 0.0;\n vec3 f = vec3(0.0);\n if (isSurface) {\n if (cosThetaL <= 0.0 && mat.transmissionWeight <= 0.0 && mat.subsurfaceWeight <= 0.0) {\n return vec3(0.0);\n }\n f = openpbr_eval_prepared(prepared, lightDir, scatteringPdf);\n }\n else {\n scatteringPdf = sampling_henyey_greenstein_phase(\n dot(viewDir, lightDir),\n si.mediumAnisotropy\n );\n f = vec3(scatteringPdf);\n }\n\n if (scatteringPdf <= 0.0 || max(max(f.x, f.y), f.z) <= 0.0) {\n return vec3(0.0);\n }\n\n Ray lightRay;\n vec3 shadowOrigin = si.position + EPS * lightDir;\n if (isSurface) {\n const float shadowTerminatorCutoff = 0.1;\n float normalLight = dot(si.normal, lightDir);\n#ifdef USE_COAT_NORMAL_FRAMES\n if (mat.coatNormalEnabled) { normalLight = dot(si.faceNormal, lightDir); }\n#endif\n vec3 geometricNormal = normalLight < 0.0 ? -si.faceNormal : si.faceNormal;\n normalLight = abs(normalLight);\n float geometricLight = dot(geometricNormal, lightDir);\n float offsetAmount = normalLight < shadowTerminatorCutoff\n ? clamp(\n 2.0 - (geometricLight + normalLight) / shadowTerminatorCutoff,\n 0.0,\n 1.0\n )\n : clamp(1.0 - geometricLight / shadowTerminatorCutoff, 0.0, 1.0);\n shadowOrigin += si.shadowOffset * offsetAmount;\n }\n float shadowDistance=lightSample.dist-EPS;\n vec3 shadowDirection=lightDir;\n if(lightSample.sourceType==1){\n vec3 endpoint=si.position+lightDir*lightSample.dist+EPS*lightSample.normal;\n shadowDirection=normalize(endpoint-shadowOrigin);shadowDistance=distance(endpoint,shadowOrigin);\n }\n initRay(lightRay, shadowOrigin, shadowDirection);\n if (intersectSceneShadow(lightRay, shadowDistance, si.triangleIndex)) {\n return vec3(0.0);\n }\n\n#ifdef USE_ENVMAP\n // Match the endpoint used by a BSDF-sampled surface transmission, including\n // a separately displayed or grounded background and its coverage.\n if (isSurface && cosThetaL < 0.0 && lightSample.sourceType == 0) {\n vec4 background = sampleBackgroundFromRay(lightRay.o, lightDir);\n lightSample.emission = sampling_spectral_rgb_filter(background.rgb * background.a, pathChannel);\n }\n#endif\n\n // Delta lights cannot be sampled by the BSDF strategy, so their MIS weight\n // is exactly one even when their light-selection PMF is small.\n float misWeight = lightSample.isDelta\n ? 1.0\n : sampling_power_heuristic(lightPdf, scatteringPdf);\n${fragments['sample1'] ?? ''} return misWeight > 0.0\n ? misWeight * lightSample.emission * f / lightPdf\n : vec3(0.0);\n}\n\n#ifdef USE_COAT_NORMAL_FRAMES\nvec3 coat_frame_normal(vec3 inputNormal, vec3 face, vec3 view) {\n bool front = dot(face, view) >= 0.0;\n vec3 ffFace = front ? face : -face;\n vec3 ffInput = front ? inputNormal : -inputNormal;\n if (dot(inputNormal, face) <= 0.0 || dot(ffInput, view) <= 1e-6) { return ffFace; }\n return ffInput;\n}\n#endif\nvoid SampleMaterial(inout SurfaceInteraction si, OpenPbrResolvedMaterial mat, inout Path path) {\n vec3 matRnd = vec3(sample2D(bounceDim(BSDF_DIRECTION)), sample1D(bounceDim(BSDF_LOBE)));\n#ifdef USE_COAT_NORMAL_FRAMES\n vec3 originalFace = si.faceNormal;\n vec3 originalNormal = si.normal;\n#endif\n float ndv1 = -dot(si.faceNormal, path.ray.d);\n float ndv2 = -dot(si.normal, path.ray.d);\n if ((mat.transmissionWeight > 0.0 || mat.subsurfaceWeight > 0.0) && mat.thinWalled) {\n // Always treat thin material as entering medium\n if (ndv1 < 0.0) {\n si.faceNormal = -si.faceNormal;\n ndv1 = -ndv1;\n }\n if (ndv2 < 0.0) {\n si.normal = -si.normal;\n ndv2 = -ndv2;\n }\n }\n // In same edge cases normal is not torwards the camera while we can still see the face.\n // We need to choose faceNormal in this case.\n bool useFaceN = ndv1 >= 0.0 && ndv2 < 0.0;\n float ndv = useFaceN ? ndv1 : ndv2;\n vec3 normal = useFaceN ? si.faceNormal : si.normal;\n\n mat.inside = ndv <= 0.0 && !mat.thinWalled;\n // In or out\n mat.relativeIor = ndv > 0.0 ? (1.0 / mat.specularIor) : mat.specularIor;\n vec3 ffnormal = ndv >= 0.0 ? normal : -normal;\n#ifdef USE_COAT_NORMAL_FRAMES\n if (mat.coatNormalEnabled) {\n vec3 view = -path.ray.d;\n float geometricView = dot(originalFace, view);\n mat.geometricNormal = geometricView >= 0.0 ? originalFace : -originalFace;\n ffnormal = coat_frame_normal(originalNormal, originalFace, view);\n mat.coatNormal = coat_frame_normal(si.coatNormal, originalFace, view);\n mat.inside = geometricView <= 0.0 && !mat.thinWalled;\n mat.relativeIor = (geometricView > 0.0 || mat.thinWalled) ? 1.0 / mat.specularIor : mat.specularIor;\n }\n#endif\n\n\n float scatteringPdf;\n vec3 scatterDir;\n path.scatteringIsDelta = false;\n bool mediumSampled = false;\n bool crossedBoundary = false;\n OpenPbrPreparedBsdf prepared;\n\n#ifdef HAS_MEDIUM\n int mediumType = si.mediumType;\n float d = distance(si.position, path.ray.o);\n vec3 segmentOrigin = path.ray.o;\n vec3 extinction = si.mediumExtinction;\n vec3 scattering = min(si.mediumScattering, extinction);\n float majorant = max(max(extinction.x, extinction.y), extinction.z);\n if (mediumType > 0 && majorant > 0.0) {\n // Sample one RGB extinction channel and divide by the mixture PDF. This\n // is the homogeneous-medium estimator used by PBRT and avoids the very\n // large exp((majorant - extinction) * distance) weights produced by\n // majorant tracking when OpenPBR SSS radii differ strongly by channel.\n int mediumChannel = min(int(sample1D(bounceDim(MEDIUM_CHANNEL)) * 3.0), 2);\n float channelExtinction = extinction[mediumChannel];\n float scatterDist = channelExtinction > 0.0\n ? min(-log(max(sample1D(bounceDim(MEDIUM_DISTANCE)), 1e-7)) / channelExtinction, d)\n : d;\n mediumSampled = scatterDist < d;\n vec3 transmittance = exp(-extinction * scatterDist);\n vec3 density = mediumSampled\n ? extinction * transmittance\n : transmittance;\n float mediumPdf = max(\n (density.x + density.y + density.z) / 3.0,\n 1e-8\n );\n if (mediumSampled) {\n path.beta *= transmittance * scattering / mediumPdf;\n // Zero throughput cannot contribute at subsequent vertices or light connections.\n if (all(equal(path.beta, vec3(0.0)))) { path.abort = true; return; }\n // Move from the start of the segment, not from its end surface.\n path.ray.o = segmentOrigin + scatterDist * path.ray.d;\n si.position = path.ray.o;\n // A volume vertex has no originating surface to skip on continuation or shadow rays.\n si.triangleIndex = -1;\n si.instanceIndex = -1;\n path.li += DirectLight(si, mat, prepared, path, ffnormal, false) * path.beta;\n\n // Pick a new direction based on the phase function\n scatterDir = sampling_henyey_greenstein(\n -path.ray.d,\n si.mediumAnisotropy,\n sample2D(bounceDim(PHASE_DIRECTION))\n );\n scatteringPdf = sampling_henyey_greenstein_phase(\n dot(scatterDir, -path.ray.d),\n si.mediumAnisotropy\n );\n }\n else {\n path.beta *= transmittance / mediumPdf;\n // Zero throughput cannot contribute at subsequent vertices or light connections.\n if (all(equal(path.beta, vec3(0.0)))) { path.abort = true; return; }\n }\n }\n#endif\n\n // Direct lighting\n if (!mediumSampled) {\n // Match NEE and background radiance when RGB wavelength passes are added.\n vec3 surfaceEmission = sampling_spectral_rgb_filter(mat.emission, pathChannel);\n ${fragments['sample2'] ?? ''}path.li += emissiveHitMisWeight(si,path) * surfaceEmission * path.beta;${fragments['sample3'] ?? ''}\n if (mat.materialType == UNLIT) {\n path.abort = true;\n return;\n }\n vec3 surfaceTangent = vec3(0.0);\n#ifdef USE_TANGENT\n surfaceTangent = si.tangent;\n#endif\n mat.directionTangent = si.directionTangent;\n mat.directionBitangent = si.directionBitangent;\n mat.geometryTangent = si.geometryTangent;\n mat.geometryBitangent = si.geometryBitangent;\n prepared = openpbr_prepare(surfaceTangent, mat, -path.ray.d, ffnormal);\n path.li += DirectLight(si, mat, prepared, path, ffnormal, true) * path.beta;\n${fragments['sample4'] ?? ''} // Sample BSDF for color and outgoing direction\n bool isNextRefraction;\n vec3 f = openpbr_sample_prepared(\n prepared,\n matRnd,\n scatterDir,\n scatteringPdf,\n isNextRefraction\n );\n // Null-boundary transmission is discrete and has no NEE competitor.\n path.scatteringIsDelta = !prepared.material.thinWalled &&\n abs(prepared.material.relativeIor - 1.0) <= 1e-6 &&\n prepared.probabilities[OPENPBR_LOBE_TRANSMISSION] >= 1.0 - 1e-6;\n // Match WebGPU: rejected VNDF/refraction proposals have no continuation.\n // Tracing their fallback direction with the incoming throughput invents\n // light paths, especially after total internal reflection inside glass.\n if (!(scatteringPdf > 0.0) || any(isnan(f)) || any(isinf(f)) ||\n dot(scatterDir, scatterDir) < 0.5) {\n path.scatteringPdf = 0.0;\n path.abort = true;\n return;\n }\n${fragments['sample5'] ?? ''} path.beta *= f / scatteringPdf;\n // Zero throughput cannot contribute at subsequent vertices or light connections.\n if (all(equal(path.beta, vec3(0.0)))) { path.abort = true; return; }\n crossedBoundary = !mat.thinWalled &&\n isNextRefraction;\n path.isNextRefraction = isNextRefraction;\n // TODO prefer the opaque surface when transmission surface and opaque surface are overlapped.\n // Or the ray go out from transmission material will miss the opque surface.\n path.ray.o = si.position + EPS * scatterDir;\n#ifdef USE_COAT_NORMAL_FRAMES\n if (mat.coatNormalEnabled) { path.ray.o = si.position + EPS * (dot(originalFace, scatterDir) >= 0.0 ? originalFace : -originalFace); }\n#endif\n }\n\n path.scatteringPdf = scatteringPdf;\n initRay(path.ray, path.ray.o, scatterDir);\n if (mediumSampled) {${fragments['sample6'] ?? ''}\n path.isNextRefraction = false;\n }\n path.fromEye = false;\n\n#ifdef HAS_MEDIUM\n // A reflected ray stays in its current medium. Only a sampled transmission\n // event crosses the boundary of a medium-bearing closed mesh.\n if (!mediumSampled && crossedBoundary && mat.mediumType > 0) {\n if (ndv1 >= 0.0) {\n si.mediumType = mat.mediumType;\n si.mediumExtinction = mat.mediumExtinction;\n si.mediumScattering = mat.mediumScattering;\n path.scatteringMediumEntered = path.scatteringMediumEntered || any(greaterThan(mat.mediumScattering, vec3(0.0)));\n si.mediumAnisotropy = mat.mediumAnisotropy;\n }\n else {\n si.mediumType = 0;\n si.mediumExtinction = vec3(0.0);\n si.mediumScattering = vec3(0.0);\n si.mediumAnisotropy = 0.0;\n }\n }\n#endif\n}\n`;\n}\nexport default createSampleMaterialGlsl();\n"]}
|
|
@@ -12,39 +12,39 @@ export default glsl `
|
|
|
12
12
|
|
|
13
13
|
const uint SHADOW_CATCHER_LIGHT_SAMPLES = 4u;
|
|
14
14
|
|
|
15
|
-
uint
|
|
16
|
-
return candidate == 0u ?
|
|
15
|
+
uint lA(uint candidate, uint slot) {
|
|
16
|
+
return candidate == 0u ? aX(slot) : aX(9u + (candidate - 1u) * 3u + slot);
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
vec2 sampleShadowCatcher(SurfaceInteraction si, int bounce, inout Path
|
|
22
|
-
vec3
|
|
21
|
+
vec2 sampleShadowCatcher(SurfaceInteraction si, int bounce, inout Path path) {
|
|
22
|
+
vec3 sg = -path.ray.d;
|
|
23
23
|
vec2 counts = vec2(0.0);
|
|
24
24
|
|
|
25
25
|
#if defined(NUM_LIGHTS) || defined(USE_ENVMAP)
|
|
26
26
|
for (uint candidate = 0u; candidate < SHADOW_CATCHER_LIGHT_SAMPLES; candidate++) {
|
|
27
27
|
LightSampleRec lightSample;
|
|
28
|
-
vec3
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
vec3 ob = vec3(
|
|
29
|
+
sample2D(lA(candidate, LIGHT_POSITION)),
|
|
30
|
+
sample1D(lA(candidate, LIGHT_SELECT))
|
|
31
31
|
);
|
|
32
|
-
sampleLight(si.position,
|
|
32
|
+
sampleLight(si.position, ob, lightSample, false);
|
|
33
33
|
|
|
34
34
|
vec3 lightDir = lightSample.direction;
|
|
35
35
|
float cosThetaL = dot(si.normal, lightDir);
|
|
36
|
-
float
|
|
37
|
-
if (lightSample.pdf > 0.0 &&
|
|
36
|
+
float rG = dot(si.normal, sg) * cosThetaL;
|
|
37
|
+
if (lightSample.pdf > 0.0 && rG >= 0.0) {
|
|
38
38
|
if (dot(lightSample.emission, luminance) * abs(cosThetaL) > 0.0) {
|
|
39
39
|
Ray ray;
|
|
40
|
-
|
|
41
|
-
bool
|
|
42
|
-
counts += vec2(
|
|
40
|
+
initRay(ray, si.position + EPS * lightDir, lightDir);
|
|
41
|
+
bool mz = intersectSceneShadow(ray, lightSample.dist - EPS, si.triangleIndex);
|
|
42
|
+
counts += vec2(mz ? 1.0 : 0.0, 1.0);
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
#endif
|
|
47
|
-
|
|
47
|
+
path.fromEye = false;
|
|
48
48
|
return counts;
|
|
49
49
|
}
|
|
50
50
|
`;
|