@meimu/mutracer 0.3.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/THIRD_PARTY_NOTICES.md +18 -4
- package/dist/assets/bvh.worker.js +1 -1
- package/dist/mutracer.umd.js +6260 -5580
- package/docs/api.md +45 -18
- package/docs/materials.md +4 -2
- package/docs/performance.md +7 -0
- package/docs/post-processing.md +62 -9
- package/docs/progressive-rendering.md +3 -0
- 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 +29 -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/viewer.md +11 -1
- 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 +2 -1
- package/lib/Engine.js +30 -2
- package/lib/Engine.js.map +1 -1
- package/lib/Render.d.ts +20 -11
- package/lib/Render.js +32 -7
- package/lib/Render.js.map +1 -1
- package/lib/main.d.ts +3 -1
- 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/MaterialData.js +7 -2
- package/lib/renderer/MaterialData.js.map +1 -1
- package/lib/renderer/RenderingPipeline.d.ts +7 -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/WGPUEnvMapDistribution.js +19 -19
- package/lib/renderer/WGPUFullQuadPass.js +3 -3
- package/lib/renderer/WGPURayTraceOutput.js +12 -12
- package/lib/renderer/WGPURayTracePass.d.ts +17 -4
- package/lib/renderer/WGPURayTracePass.js +194 -71
- package/lib/renderer/WGPURayTracePass.js.map +1 -1
- package/lib/renderer/WGPURenderingPipeline.js +46 -40
- 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 +1 -1
- package/lib/renderer/WebGLFullQuadPass.js +8 -2
- 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 +14 -10
- package/lib/renderer/WebGLRayTracePass.js +115 -111
- package/lib/renderer/WebGLRayTracePass.js.map +1 -1
- package/lib/renderer/WebGLRenderingPipeline.js +10 -3
- package/lib/renderer/WebGLRenderingPipeline.js.map +1 -1
- package/lib/renderer/WebGLSkyBaker.js +57 -57
- 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/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 +35 -35
- package/lib/renderer/glsl/aovReflectanceSamples.glsl.js +1 -1
- package/lib/renderer/glsl/aovTrace.frag.js +44 -36
- 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.js +8 -8
- package/lib/renderer/glsl/chunks/envMap.glsl.js +67 -67
- package/lib/renderer/glsl/chunks/intersect.glsl.js +390 -375
- package/lib/renderer/glsl/chunks/intersect.glsl.js.map +1 -1
- package/lib/renderer/glsl/chunks/materialBuffer.glsl.js +120 -120
- package/lib/renderer/glsl/chunks/openPbrBsdf.glsl.js +562 -562
- package/lib/renderer/glsl/chunks/rand.glsl.js +3 -3
- package/lib/renderer/glsl/chunks/random.glsl.js +4 -4
- package/lib/renderer/glsl/chunks/rayTraceCore.glsl.js +37 -35
- package/lib/renderer/glsl/chunks/rayTraceCore.glsl.js.map +1 -1
- package/lib/renderer/glsl/chunks/sampleLight.glsl.js +70 -74
- package/lib/renderer/glsl/chunks/sampleLight.glsl.js.map +1 -1
- package/lib/renderer/glsl/chunks/sampleMaterial.glsl.d.ts +1 -1
- package/lib/renderer/glsl/chunks/sampleMaterial.glsl.js +107 -88
- package/lib/renderer/glsl/chunks/sampleMaterial.glsl.js.map +1 -1
- package/lib/renderer/glsl/chunks/sampleShadowCatcher.glsl.js +11 -11
- package/lib/renderer/glsl/chunks/sampling.glsl.js +77 -77
- package/lib/renderer/glsl/chunks/sobol.glsl.js +70 -70
- 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 +12 -6
- 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.js +233 -170
- package/lib/renderer/glsl/rayTrace.frag.js.map +1 -1
- package/lib/renderer/glsl/shadowCatcher.frag.js +10 -9
- package/lib/renderer/glsl/shadowCatcher.frag.js.map +1 -1
- package/lib/renderer/glsl/webglPipeline.frag.js +58 -58
- package/lib/renderer/gpuMemory.js +1 -1
- package/lib/renderer/gpuMemory.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 +1 -1
- package/lib/renderer/progressiveScheduler.js.map +1 -1
- package/lib/renderer/renderPipeline.d.ts +4 -0
- package/lib/renderer/renderPipeline.js +1 -0
- package/lib/renderer/renderPipeline.js.map +1 -1
- package/lib/renderer/researchTransport.d.ts +1 -1
- package/lib/renderer/researchTransport.js.map +1 -1
- 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 +1 -0
- package/lib/renderer/sceneLayoutSchema.js +2 -2
- 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.js +2 -2
- 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/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 +2 -2
- 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 +15 -0
- package/lib/renderer/wgpuShaderSource.js +1 -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 +39 -39
- 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 +31 -31
- 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 +1 -1
- package/lib/renderer/wgsl/causticLight.compute.js +121 -119
- package/lib/renderer/wgsl/causticLight.compute.js.map +1 -1
- package/lib/renderer/wgsl/chunks/background.wgsl.js +46 -46
- package/lib/renderer/wgsl/chunks/causticAdjoint.wgsl.js +4 -4
- package/lib/renderer/wgsl/chunks/causticAtomic.wgsl.js +3 -3
- package/lib/renderer/wgsl/chunks/caustics.wgsl.js +3 -3
- package/lib/renderer/wgsl/chunks/common.wgsl.js +4 -4
- package/lib/renderer/wgsl/chunks/envMap.wgsl.js +30 -30
- package/lib/renderer/wgsl/chunks/intersect.wgsl.d.ts +6 -2
- package/lib/renderer/wgsl/chunks/intersect.wgsl.js +550 -542
- 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 +18 -16
- package/lib/renderer/wgsl/chunks/intersectionAlpha.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.d.ts +2 -1
- package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.js +70 -69
- package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/chunks/openPbrBsdf.wgsl.js +593 -593
- package/lib/renderer/wgsl/chunks/pdm_displacement.wgsl.js +118 -118
- package/lib/renderer/wgsl/chunks/rand.wgsl.js +3 -3
- package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.d.ts +4 -1
- package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.js +32 -26
- package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/chunks/sampleLight.wgsl.js +114 -114
- package/lib/renderer/wgsl/chunks/sampleMaterial.wgsl.d.ts +1 -1
- package/lib/renderer/wgsl/chunks/sampleMaterial.wgsl.js +159 -137
- package/lib/renderer/wgsl/chunks/sampleMaterial.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/chunks/sampleShadowCatcher.wgsl.js +8 -8
- package/lib/renderer/wgsl/chunks/sampling.wgsl.js +74 -74
- package/lib/renderer/wgsl/chunks/sobol.wgsl.js +74 -74
- 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 +99 -97
- 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 +11 -2
- 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.js +89 -89
- package/lib/renderer/wgsl/proceduralSky.compute.js +61 -61
- package/lib/renderer/wgsl/rayTrace.compute.d.ts +14 -0
- package/lib/renderer/wgsl/rayTrace.compute.js +395 -333
- package/lib/renderer/wgsl/rayTrace.compute.js.map +1 -1
- package/lib/scene/Scene.js.map +1 -1
- package/lib/settings/render.d.ts +11 -0
- package/lib/settings/render.js +1 -0
- package/lib/settings/render.js.map +1 -1
- package/lib/util/fromTHREE.js +21 -14
- 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/package.json +5 -2
- 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":"sampleMaterial.wgsl.js","sourceRoot":"","sources":["../../../../src/renderer/wgsl/chunks/sampleMaterial.wgsl.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,6EAA6E;AAC7E,iIAAiI;AACjI,MAAM,UAAU,wBAAwB,CAAC,uBAAuB,GAAG,IAAI,EAAE,cAAc,GAAG,KAAK,EAAE,QAAQ,GAAG,KAAK,EAAE,oBAAoB,GAAG,EAAE,EAAC,aAAa,GAAC,KAAK;IAC9J,OAAO,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uCA8BqB,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC;;;;;EAK3D,CAAC,CAAC,CAAC,EAAE;;;;;;EAML,cAAc,CAAC,CAAC,CAAC,UAAU,CAAC;0FAC4D,CAAC,CAAC,CAAC,0CAA0C;;;;;;;;;;;;;;;;;EAiBvI,cAAc,CAAC,CAAC,CAAC,UAAU,CAAC,yEAAkF,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiHnH,QAAQ,CAAA,CAAC,CAAA;;;CAGV,CAAA,CAAC,CAAA,EAAE;;;;;;;;;;;;;;;;EAgBQ,cAAc,CAAC,CAAC,CAAC,8GAA8G,CAAC,CAAC,CAAC,uBAAuB;;;;;;;;;;;;;;;;;;EAkB7J,cAAc,CAAC,CAAC,CAAC,UAAU,CAAC;yFAC2D,CAAC,CAAC,CAAC,UAAU,CAAC,0CAA0C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAuC3I,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC;wDACwB,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;EAsB7D,cAAc,CAAC,CAAC,CAAC,UAAU,CAAC;;;;;;;;;;CAU7B,CAAC,CAAC,CAAC,EAAE;;;;;;EAMJ,cAAc,CAAC,CAAC,CAAC,UAAU,CAAC;;;CAG7B,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;EAwBJ,cAAc,CAAC,CAAC,CAAC,UAAU,CAAC;;;;;;;;;;CAU7B,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+CJ,QAAQ,CAAA,CAAC,CAAA;;4CAEiD,CAAA,CAAC,CAAA,mFAAmF;;;;;;;;;;EAU9I,uBAAuB,CAAC,CAAC,CAAC,UAAU,CAAC;;;;;CAKtC,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE;;;EAGf,oBAAoB,GAAG,aAAa,CAAA,CAAC,CAAA,UAAU,CAAC;CACjD,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;EAsBJ,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC;CACvB,CAAC,CAAC,CAAC,EAAE;;;;;;;EAOJ,cAAc,CAAC,CAAC,CAAC,UAAU,CAAC;;CAE7B,CAAC,CAAC,CAAC,EAAE;;;;sBAIkB,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC;yCACD,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;CAyBjD,CAAC;AAEF,CAAC;AAED,eAAe,wBAAwB,EAAE,CAAC","sourcesContent":["// Next-event estimation with resampled importance sampling over the light\n// candidates, followed by BSDF (or phase function) sampling, as described in\n// http://www.pbr-book.org/3ed-2018/Light_Transport_I_Surface_Reflection/Direct_Lighting.html#EstimatingtheDirectLightingIntegral\nexport function createSampleMaterialWgsl(hasAnisotropyDirections = true, hasCoatNormals = false, caustics = false, researchContribution = '',photonMapping=false) {\n return /* wgsl */ `\n\nstruct ShadowRayWork {\n ray: Ray,\n maxDistance: f32,\n triangleIndex: i32,\n contribution: vec3f,\n // RIS target of the candidate. The discrete light-selection PMF is excluded\n // and represented by the candidate's unbiased contribution weight instead.\n risTarget: f32,\n lightSelectionPmf: f32,\n valid: bool,\n}\n\nfn finishDirectLight(\n si: ptr<function, SurfaceInteraction>,\n ma: OpenPbrResolvedMaterial,\n path: ptr<function, Path>,\n ffnormal: vec3f,\n isSurface: bool,\n lightSample: LightSampleRec,\n f: vec3f,\n scatteringPdf: f32,\n shadowWork: ptr<function, ShadowRayWork>\n) -> bool {\n (*shadowWork).valid = false;\n (*shadowWork).lightSelectionPmf = 0.0;\n (*shadowWork).risTarget = 0.0;\n var Li = lightSample.emission;\n\n let lightDir = lightSample.direction;${caustics ? /* wgsl */ `\n if(isSurface&&isCausticSpecular(ma)){\n var connection=*path;\n causticAdvance(&connection,ma,dot(ffnormal,lightDir)<0.0,true);\n if(causticHitOwned(connection,lightSample.sourceType!=0u,true)){return false;}\n }` : ''}\n let viewDir = -(*path).ray.d;\n let lightPdf = lightSample.pdf;\n let lightSelectionPmf = lightSample.selectionPmf;\n // Keep direct-light culling consistent with the two-sided BSDF evaluation.\n // The raw imported normal can point away from the camera on interior walls.\n ${hasCoatNormals ? /* wgsl */ `var cosThetaL = dot(ffnormal, lightDir);\n if (isSurface && ma.coatNormalEnabled) { cosThetaL = dot(ma.geometricNormal, lightDir); }` : 'let cosThetaL = dot(ffnormal, lightDir);'}\n\n if ((lightPdf <= 0.0) | (lightSelectionPmf <= 0.0) |\n (max(max(Li.x, Li.y), Li.z) <= 0.0)) {\n return false;\n }\n\n if ((scatteringPdf <= 0.0) | (max(max(f.x, f.y), f.z) <= 0.0)) {\n return false;\n }\n\n var lightRay: Ray;\n var shadowOrigin = (*si).position + EPS * lightDir;\n if (isSurface) {\n shadowOrigin = offsetSurfaceRay((*si).position, (*si).faceNormal, lightDir);\n let shadowTerminatorCutoff = 0.1;\n var normalLight = dot((*si).normal, lightDir);\n${hasCoatNormals ? /* wgsl */ ` if (ma.coatNormalEnabled) { normalLight = dot((*si).faceNormal, lightDir); }` : ''}\n let geometricNormal = select(\n (*si).faceNormal,\n -(*si).faceNormal,\n normalLight < 0.0\n );\n normalLight = abs(normalLight);\n let geometricLight = dot(geometricNormal, lightDir);\n let offsetAmount = select(\n clamp(1.0 - geometricLight / shadowTerminatorCutoff, 0.0, 1.0),\n clamp(\n 2.0 - (geometricLight + normalLight) / shadowTerminatorCutoff,\n 0.0,\n 1.0\n ),\n normalLight < shadowTerminatorCutoff\n );\n shadowOrigin += (*si).shadowOffset * offsetAmount;\n }\n // Falcor offsets sampled emissive positions along the light normal, then\n // derives the visibility ray from that offset endpoint. Without the target\n // offset, our any-hit traversal sees the sampled light triangle itself and\n // rejects virtually every emissive NEE sample as occluded.\n var visibilityDirection = lightDir;\n var visibilityDistance = lightSample.dist - EPS;\n if (lightSample.sourceType == 1u) {\n let lightEndpoint =\n (*si).position + lightSample.direction * lightSample.dist;\n let offsetLightEndpoint = lightEndpoint + EPS * lightSample.normal;\n let toOffsetLight = offsetLightEndpoint - shadowOrigin;\n visibilityDistance = length(toOffsetLight);\n visibilityDirection = normalize(toOffsetLight);\n }\n initRay(&lightRay, shadowOrigin, visibilityDirection);\n\n // The continuation of a surface transmission sees the displayed background.\n // Evaluate that same endpoint for the environment proposal, so both MIS\n // strategies estimate the same radiance even for a separate/grounded skybox.\n if (isSurface & (cosThetaL < 0.0) & (lightSample.sourceType == 0u)) {\n let background = sampleSceneBackground(lightRay);\n Li = background.rgb * background.a;\n }\n if (SPECTRAL) {\n Li = sampling_spectral_rgb_filter(Li, (*si).spectralChannel);\n }\n\n // A directional source is a delta distribution and cannot be reached by\n // the BSDF-sampling strategy, so its light-sampled contribution has weight 1.\n let misWeight = select(\n neeMISWeight(lightPdf, scatteringPdf),\n 1.0,\n lightSample.isDelta\n );\n if (misWeight > 0.0) {\n let unweightedContribution = Li * f / lightPdf * (*path).beta;\n (*shadowWork).risTarget = max(\n dot(max(unweightedContribution * lightSelectionPmf, vec3f(0.0)), luminance),\n 0.0\n );\n (*shadowWork).ray = lightRay;\n (*shadowWork).maxDistance = visibilityDistance;\n (*shadowWork).triangleIndex = (*si).triangleIndex;\n (*shadowWork).contribution = misWeight * unweightedContribution;\n (*shadowWork).lightSelectionPmf = lightSelectionPmf;\n (*shadowWork).valid = true;\n return true;\n }\n return false;\n}\n\nstruct ScatteringWork {\n direction: vec3f,\n response: vec3f,\n pdf: f32,\n transmission: bool,\n}\n\nfn sampleScattering(\n si: ptr<function, SurfaceInteraction>,\n ma: OpenPbrResolvedMaterial,\n prepared: OpenPbrPreparedBsdf,\n path: ptr<function, Path>,\n ffnormal: vec3f,\n isSurface: bool\n) -> ScatteringWork {\n let candidateCount = neeCandidateCount();\n var selected: ShadowRayWork;\n selected.valid = false;\n var selectedTarget = 0.0;\n var scalarWeightSum = 0.0;\n var result: ScatteringWork;\n // The final iteration samples the continuation after NEE and its shadow ray.\n // Both proposals use one BSDF evaluation call site, avoiding a second inlined\n // optical graph. Keep all random draws and visibility queries in their\n // original order, including the short-circuit reservoir replacement draw.\n for (var event = 0u; event <= candidateCount; event++) {\n let continuation = event == candidateCount;\n var lightSample: LightSampleRec;\n var lightDir: vec3f;\n var scatteringPdf = 0.0;\n var response = vec3f(0.0);\n var discrete = false;\n if (continuation) {\n var candidateUCW = 1.0;\n var valid = selected.valid;\n if (candidateCount > 1u) {\n valid = valid & (selectedTarget > 0.0);\n if (valid) {\n candidateUCW = selected.lightSelectionPmf * scalarWeightSum /\n (f32(candidateCount) * selectedTarget);\n }\n }\n if (valid && !intersectSceneShadow(selected.ray, selected.maxDistance, selected.triangleIndex, (*si).instanceIndex)) {\n${caustics?` var connection=*path;\n if(isSurface&&isCausticSpecular(ma)){causticAdvance(&connection,ma,dot(ffnormal,selected.ray.d)<0.0,true);}\n connection.beta=vec3f(1.0);causticHotRecord(connection,selected.contribution*candidateUCW,0u);\n`:''} (*path).li += selected.contribution * candidateUCW;\n }\n if (!isSurface) {\n result.direction = sampling_henyey_greenstein(-(*path).ray.d,\n (*si).mediumAnisotropy, sample2D(bounceDim(PHASE_DIRECTION)));\n result.pdf = sampling_henyey_greenstein_phase(\n dot(result.direction, -(*path).ray.d), (*si).mediumAnisotropy);\n return result;\n }\n let matRnd = vec3f(sample2D(bounceDim(BSDF_DIRECTION)), sample1D(bounceDim(BSDF_LOBE)));\n discrete = !prepared.material.thinWalled &\n (abs(prepared.material.relativeIor - 1.0) <= 1e-6) &\n (prepared.probabilities[OPENPBR_LOBE_TRANSMISSION] >= 1.0 - 1e-6);\n if (discrete) {\n lightDir = openpbr_to_world(prepared.basis, -prepared.viewLocal);\n response = openpbr_transmission_tint(prepared.material) * openpbr_coat_base_scale(prepared,\n ${hasCoatNormals ? 'select(-prepared.viewLocal.z, dot(prepared.coatBasis.normal, lightDir), prepared.material.coatNormalEnabled)' : '-prepared.viewLocal.z'});\n scatteringPdf = 1.0;\n result.transmission = true;\n } else {\n var roughness = 1.0; var specular = false; var diffuse = true;\n var lobe = u32(OPENPBR_LOBE_DIFFUSE);\n // Use locals rather than member pointers for Naga's SPIR-V writer.\n var transmission = false;\n if (!openpbr_sample_direction(prepared, matRnd, &lightDir, &transmission,\n &roughness, &specular, &diffuse, &lobe)) { return result; }\n result.transmission = transmission;\n }\n } else {\n let lightRnd = vec3f(sample2D(lightDim(event, 1u)), sample1D(lightDim(event, 0u)));\n sampleLightForNEECandidate((*si).position, lightRnd, event, candidateCount, &lightSample);\n lightDir = lightSample.direction;\n if ((lightSample.pdf <= 0.0) | (lightSample.selectionPmf <= 0.0) |\n (max(max(lightSample.emission.x, lightSample.emission.y), lightSample.emission.z) <= 0.0)) { continue; }\n ${hasCoatNormals ? /* wgsl */ `var cosThetaL = dot(ffnormal, lightDir);\n if (isSurface & ma.coatNormalEnabled) { cosThetaL = dot(ma.geometricNormal, lightDir); }` : /* wgsl */ `let cosThetaL = dot(ffnormal, lightDir);`}\n if (isSurface & (cosThetaL <= 0.0) & (ma.transmissionWeight <= 0.0) & (ma.subsurfaceWeight <= 0.0)) { continue; }\n }\n if (!discrete) {\n if (isSurface) {\n response = openpbr_eval_prepared(prepared, lightDir, &scatteringPdf);\n } else {\n scatteringPdf = sampling_henyey_greenstein_phase(\n dot(-(*path).ray.d, lightDir), (*si).mediumAnisotropy);\n response = vec3f(scatteringPdf);\n }\n }\n if (continuation) {\n result.direction = lightDir; result.response = response; result.pdf = scatteringPdf;\n return result;\n }\n var candidate: ShadowRayWork;\n let candidateValid = finishDirectLight(si, ma, path, ffnormal, isSurface,\n lightSample, response, scatteringPdf, &candidate);\n if (!candidateValid) { continue; }\n if (candidateCount == 1u) {\n selected = candidate;\n continue;\n }\n let scalarWeight = candidate.risTarget / max(candidate.lightSelectionPmf, 1e-20);\n if (!(scalarWeight > 0.0) | (scalarWeight != scalarWeight)) { continue; }\n scalarWeightSum += scalarWeight;\n if (!selected.valid ||\n lightCandidateRandom(event) * scalarWeightSum <= scalarWeight) {\n selected = candidate;\n selectedTarget = candidate.risTarget;\n }\n }\n return result;\n}\n\nfn emissiveHitMisWeight(\n si: ptr<function, SurfaceInteraction>,\n path: ptr<function, Path>\n) -> f32 {${caustics ? /* wgsl */ `\n if (causticHitOwned(*path, true, true)) { return 0.0; }` : ''}\n // Secondary traversal accepts back faces for transmission; a one-sided\n // emitter still radiates only into its front hemisphere.\n let cosLight = dot((*si).faceNormal, -(*path).ray.d);\n if (cosLight <= 0.0 && materialsBuffer[(*si).materialIndex].doubleSided < 0.5) { return 0.0; }\n if ((*path).fromEye | (rtUniform.lightWeightTotal <= 0.0) |\n (i32(materialsBuffer[(*si).materialIndex].matType) == UNLIT)) {\n return 1.0;\n }\n let samplingLuminance = dot(\n materialsBuffer[(*si).materialIndex].emission,\n luminance\n );\n if ((samplingLuminance <= 0.0) | (cosLight <= 0.0)) {\n return 1.0;\n }\n let hitDistance = distance((*si).position, (*path).ray.o);\n let lightPdf = samplingLuminance / rtUniform.lightWeightTotal *\n hitDistance * hitDistance / max(cosLight, 1e-8);\n return bsdfMISWeight((*path).scatteringPdf, lightPdf);\n}\n\n${hasCoatNormals ? /* wgsl */ `\n// Keep each shading frame in the geometric/view hemisphere. This correction\n// does not replace the face normal used for topology or ray offsets.\nfn coat_frame_normal(input: vec3f, face: vec3f, view: vec3f) -> vec3f {\n let front = dot(face, view) >= 0.0;\n let ffFace = select(-face, face, front);\n let ffInput = select(-input, input, front);\n if ((dot(input, face) <= 0.0) | (dot(ffInput, view) <= 1e-6)) { return ffFace; }\n return ffInput;\n}\n` : ''}\nfn SampleMaterial(\n si: ptr<function, SurfaceInteraction>,\n ma: ptr<function, OpenPbrResolvedMaterial>,\n path: ptr<function, Path>\n) {\n${hasCoatNormals ? /* wgsl */ `\n let originalFace = (*si).faceNormal;\n let originalNormal = (*si).normal;\n` : ''}\n var ndv1: f32 = -dot((*si).faceNormal, (*path).ray.d);\n var ndv2: f32 = -dot((*si).normal, (*path).ray.d);\n if ((((*ma).transmissionWeight > 0.0) | ((*ma).subsurfaceWeight > 0.0)) & (*ma).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 var useFaceN: bool = (ndv1 >= 0.0) & (ndv2 < 0.0);\n var ndv: f32 = select(ndv2, ndv1, useFaceN);\n var N: vec3f = select((*si).normal, (*si).faceNormal, useFaceN);\n\n (*ma).inside = (ndv <= 0.0) & !(*ma).thinWalled;\n // In or out\n (*ma).relativeIor = select((*ma).specularIor, (1.0 / (*ma).specularIor), ndv > 0.0);\n var ffnormal = select(-N, N, ndv >= 0.0);\n${hasCoatNormals ? /* wgsl */ `\n if ((*ma).coatNormalEnabled) {\n let view = -(*path).ray.d;\n let geometricView = dot(originalFace, view);\n (*ma).geometricNormal = select(-originalFace, originalFace, geometricView >= 0.0);\n ffnormal = coat_frame_normal(originalNormal, originalFace, view);\n (*ma).coatNormal = coat_frame_normal((*si).coatNormal, originalFace, view);\n (*ma).inside = (geometricView <= 0.0) & !(*ma).thinWalled;\n (*ma).relativeIor = select((*ma).specularIor, 1.0 / (*ma).specularIor, (geometricView > 0.0) | (*ma).thinWalled);\n }\n` : ''}\n\n (*path).scatteringIsDelta = false;\n var mediumSampled = false;\n var crossedBoundary = false;\n let mediumType = (*si).mediumType;\n\n var scatteringPdf: f32;\n var scatterDir: vec3f;\n\n if (HAS_MEDIUM) {\n let d = distance((*si).position, (*path).ray.o);\n let segmentOrigin = (*path).ray.o;\n let extinction = (*si).mediumExtinction;\n let scattering = min((*si).mediumScattering, extinction);\n let 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 // avoids high-variance majorant weights for channel-dependent SSS radii.\n let mediumChannel = min(i32(sample1D(bounceDim(MEDIUM_CHANNEL)) * 3.0), 2);\n let channelExtinction = extinction[mediumChannel];\n let scatterDist = select(\n d,\n min(-log(max(sample1D(bounceDim(MEDIUM_DISTANCE)), 1e-7)) / channelExtinction, d),\n channelExtinction > 0.0\n );\n mediumSampled = scatterDist < d;\n let transmittance = exp(-extinction * scatterDist);\n let density = select(\n transmittance,\n extinction * transmittance,\n mediumSampled\n );\n let mediumPdf = max((density.x + density.y + density.z) / 3.0, 1e-8);\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 }\n else {\n (*path).beta *= transmittance / mediumPdf;\n }\n }\n }\n\n if (!mediumSampled) {\n${caustics?` let emissionWeight=emissiveHitMisWeight(si,path);\n causticHotRecord(*path,emissionWeight*(*ma).emission,1u);causticEmitterRecord(*si,*path,emissionWeight,(*ma).emission);\n (*path).li+=emissionWeight*(*ma).emission*(*path).beta;`:' (*path).li += emissiveHitMisWeight(si, path) * (*ma).emission * (*path).beta;'}\n }\n if ((*ma).materialType == UNLIT) {\n (*path).abort = true;\n return;\n }\n // Surface and medium events share the light estimator. Emission is added\n // before NEE, then the continuation direction is sampled.\n var prepared: OpenPbrPreparedBsdf;\n if (!mediumSampled) {\n${hasAnisotropyDirections ? /* wgsl */ `\n (*ma).directionTangent = (*si).directionTangent;\n (*ma).directionBitangent = (*si).directionBitangent;\n (*ma).geometryTangent = (*si).geometryTangent;\n (*ma).geometryBitangent = (*si).geometryBitangent;\n` : /* wgsl */ ``}\n prepared = openpbr_prepare((*si).tangent, *ma, -(*path).ray.d, ffnormal);\n }\n${researchContribution}${photonMapping?/* wgsl */ ` if(!mediumSampled){let value=(*path).beta*photonContribution(*si,prepared,(*path).fromEye,!(*path).causticHasReceiver);causticEstimateRecord(value,1u);(*path).li+=value;}\n` : ''} let scattered = sampleScattering(si, *ma, prepared, path, ffnormal, !mediumSampled);\n scatterDir = scattered.direction;\n scatteringPdf = scattered.pdf;\n if (!mediumSampled) {\n let f = scattered.response;\n let isNextRefraction = scattered.transmission;\n // A rejected microfacet proposal (including failed refraction), or a\n // material with no scattering lobes, has no continuation. Keep emission\n // and NEE already accumulated at this vertex, but never trace a default\n // direction with the incoming throughput: that invents extra light paths.\n if (!(scatteringPdf > 0.0) |\n !all(f == f) | !all(abs(f) < vec3f(3.402823e38)) |\n (dot(scatterDir, scatterDir) < 0.5)) {\n (*path).scatteringPdf = 0.0;\n (*path).abort = true;\n return;\n }\n // Exactly index-matched solid transmission is a discrete null boundary;\n // environment NEE has no competing density for that event.\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${caustics ? /* wgsl */ ` causticAdvance(path, *ma, isNextRefraction, true);\n` : ''} (*path).beta *= f / scatteringPdf;\n\n crossedBoundary = isNextRefraction & !(*ma).thinWalled;\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${hasCoatNormals ? /* wgsl */ `\n if ((*ma).coatNormalEnabled) { (*path).ray.o = (*si).position + EPS * select(-originalFace, originalFace, dot(originalFace, scatterDir) >= 0.0); }\n` : ''}\n }\n (*path).scatteringPdf = scatteringPdf;\n (*path).ray.d = scatterDir;\n if (mediumSampled) {${caustics ? /* wgsl */ `\n causticAdvance(path, *ma, false, false);` : ''}\n (*path).isNextRefraction = false;\n }\n\n (*path).fromEye = false;\n\n if (HAS_MEDIUM) {\n // Reflections stay in the current medium. Enter or leave only after the\n // BSDF actually sampled transmission through a medium boundary.\n if (!mediumSampled & crossedBoundary & ((*ma).mediumType > 0)) {\n if (ndv1 >= 0.0) {\n (*si).mediumType = (*ma).mediumType;\n (*si).mediumExtinction = (*ma).mediumExtinction;\n (*si).mediumScattering = (*ma).mediumScattering;\n (*si).mediumAnisotropy = (*ma).mediumAnisotropy;\n }\n else {\n (*si).mediumType = 0;\n (*si).mediumExtinction = vec3f(0.0);\n (*si).mediumScattering = vec3f(0.0);\n (*si).mediumAnisotropy = 0.0;\n }\n }\n }\n}\n`;\n\n}\n\nexport default createSampleMaterialWgsl();\n"]}
|
|
1
|
+
{"version":3,"file":"sampleMaterial.wgsl.js","sourceRoot":"","sources":["../../../../src/renderer/wgsl/chunks/sampleMaterial.wgsl.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,6EAA6E;AAC7E,iIAAiI;AACjI,MAAM,UAAU,wBAAwB,CAAC,uBAAuB,GAAG,IAAI,EAAE,cAAc,GAAG,KAAK,EAAE,QAAQ,GAAG,KAAK,EAAE,oBAAoB,GAAG,EAAE,EAAC,aAAa,GAAC,KAAK,EAAE,qBAAqB,GAAC,KAAK;IAC3L,OAAO,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uCA8BqB,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC;;;;;EAK3D,CAAC,CAAC,CAAC,EAAE;;;;;;EAML,cAAc,CAAC,CAAC,CAAC,UAAU,CAAC;0FAC4D,CAAC,CAAC,CAAC,0CAA0C;;;;;;;;;;;;;;;;;EAiBvI,cAAc,CAAC,CAAC,CAAC,UAAU,CAAC,yEAAkF,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA0CrG,qBAAqB,CAAC,CAAC,CAAC,0CAA0C,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;+CAcd,qBAAqB,CAAC,CAAC,CAAC,uFAAuF,CAAC,CAAC,CAAC,WAAW;;;;;;sCAMhI,qBAAqB,CAAC,CAAC,CAAC,UAAU,CAAC;;;;;;EAMnG,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmDT,QAAQ,CAAA,CAAC,CAAA;;;CAGV,CAAA,CAAC,CAAA,EAAE;;;;;;;;;;;;;;;;EAgBQ,cAAc,CAAC,CAAC,CAAC,8GAA8G,CAAC,CAAC,CAAC,uBAAuB;;;;;;;;;;;;;;;;;;EAkB7J,cAAc,CAAC,CAAC,CAAC,UAAU,CAAC;yFAC2D,CAAC,CAAC,CAAC,UAAU,CAAC,0CAA0C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAuC3I,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC;wDACwB,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;EAsB7D,cAAc,CAAC,CAAC,CAAC,UAAU,CAAC;;;;;;;;;;CAU7B,CAAC,CAAC,CAAC,EAAE;;;;;;EAMJ,cAAc,CAAC,CAAC,CAAC,UAAU,CAAC;;;CAG7B,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;EAwBJ,cAAc,CAAC,CAAC,CAAC,UAAU,CAAC;;;;;;;;;;CAU7B,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4DJ,QAAQ,CAAA,CAAC,CAAA;;6CAEkD,CAAA,CAAC,CAAA,oFAAoF;;;;;;;;;;EAUhJ,uBAAuB,CAAC,CAAC,CAAC,UAAU,CAAC;;;;;CAKtC,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE;;;EAGf,oBAAoB,GAAG,aAAa,CAAA,CAAC,CAAA,UAAU,CAAC;CACjD,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;EAsBJ,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC;CACvB,CAAC,CAAC,CAAC,EAAE;;;;;;;;;EASJ,cAAc,CAAC,CAAC,CAAC,UAAU,CAAC;;CAE7B,CAAC,CAAC,CAAC,EAAE;;;;sBAIkB,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC;yCACD,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;CA0BjD,CAAC;AAEF,CAAC;AAED,eAAe,wBAAwB,EAAE,CAAC","sourcesContent":["// Next-event estimation with resampled importance sampling over the light\n// candidates, followed by BSDF (or phase function) sampling, as described in\n// http://www.pbr-book.org/3ed-2018/Light_Transport_I_Surface_Reflection/Direct_Lighting.html#EstimatingtheDirectLightingIntegral\nexport function createSampleMaterialWgsl(hasAnisotropyDirections = true, hasCoatNormals = false, caustics = false, researchContribution = '',photonMapping=false, channelIndependentRis=false) {\n return /* wgsl */ `\n\nstruct ShadowRayWork {\n ray: Ray,\n maxDistance: f32,\n triangleIndex: i32,\n contribution: vec3f,\n // RIS target of the candidate. The discrete light-selection PMF is excluded\n // and represented by the candidate's unbiased contribution weight instead.\n risTarget: f32,\n lightSelectionPmf: f32,\n valid: bool,\n}\n\nfn finishDirectLight(\n si: ptr<function, SurfaceInteraction>,\n ma: OpenPbrResolvedMaterial,\n path: ptr<function, Path>,\n ffnormal: vec3f,\n isSurface: bool,\n lightSample: LightSampleRec,\n f: vec3f,\n scatteringPdf: f32,\n shadowWork: ptr<function, ShadowRayWork>\n) -> bool {\n (*shadowWork).valid = false;\n (*shadowWork).lightSelectionPmf = 0.0;\n (*shadowWork).risTarget = 0.0;\n var Li = lightSample.emission;\n\n let lightDir = lightSample.direction;${caustics ? /* wgsl */ `\n if(isSurface&&isCausticSpecular(ma)){\n var connection=*path;\n causticAdvance(&connection,ma,dot(ffnormal,lightDir)<0.0,true);\n if(causticHitOwned(connection,lightSample.sourceType!=0u,true)){return false;}\n }` : ''}\n let viewDir = -(*path).ray.d;\n let lightPdf = lightSample.pdf;\n let lightSelectionPmf = lightSample.selectionPmf;\n // Keep direct-light culling consistent with the two-sided BSDF evaluation.\n // The raw imported normal can point away from the camera on interior walls.\n ${hasCoatNormals ? /* wgsl */ `var cosThetaL = dot(ffnormal, lightDir);\n if (isSurface && ma.coatNormalEnabled) { cosThetaL = dot(ma.geometricNormal, lightDir); }` : 'let cosThetaL = dot(ffnormal, lightDir);'}\n\n if ((lightPdf <= 0.0) | (lightSelectionPmf <= 0.0) |\n (max(max(Li.x, Li.y), Li.z) <= 0.0)) {\n return false;\n }\n\n if ((scatteringPdf <= 0.0) | (max(max(f.x, f.y), f.z) <= 0.0)) {\n return false;\n }\n\n var lightRay: Ray;\n var shadowOrigin = (*si).position + EPS * lightDir;\n if (isSurface) {\n shadowOrigin = offsetSurfaceRay((*si).position, (*si).faceNormal, lightDir);\n let shadowTerminatorCutoff = 0.1;\n var normalLight = dot((*si).normal, lightDir);\n${hasCoatNormals ? /* wgsl */ ` if (ma.coatNormalEnabled) { normalLight = dot((*si).faceNormal, lightDir); }` : ''}\n let geometricNormal = select(\n (*si).faceNormal,\n -(*si).faceNormal,\n normalLight < 0.0\n );\n normalLight = abs(normalLight);\n let geometricLight = dot(geometricNormal, lightDir);\n let offsetAmount = select(\n clamp(1.0 - geometricLight / shadowTerminatorCutoff, 0.0, 1.0),\n clamp(\n 2.0 - (geometricLight + normalLight) / shadowTerminatorCutoff,\n 0.0,\n 1.0\n ),\n normalLight < shadowTerminatorCutoff\n );\n shadowOrigin += (*si).shadowOffset * offsetAmount;\n }\n // Falcor offsets sampled emissive positions along the light normal, then\n // derives the visibility ray from that offset endpoint. Without the target\n // offset, our any-hit traversal sees the sampled light triangle itself and\n // rejects virtually every emissive NEE sample as occluded.\n var visibilityDirection = lightDir;\n var visibilityDistance = lightSample.dist - EPS;\n if (lightSample.sourceType == 1u) {\n let lightEndpoint =\n (*si).position + lightSample.direction * lightSample.dist;\n let offsetLightEndpoint = lightEndpoint + EPS * lightSample.normal;\n let toOffsetLight = offsetLightEndpoint - shadowOrigin;\n visibilityDistance = length(toOffsetLight);\n visibilityDirection = normalize(toOffsetLight);\n }\n initRay(&lightRay, shadowOrigin, visibilityDirection);\n\n // The continuation of a surface transmission sees the displayed background.\n // Evaluate that same endpoint for the environment proposal, so both MIS\n // strategies estimate the same radiance even for a separate/grounded skybox.\n if (isSurface & (cosThetaL < 0.0) & (lightSample.sourceType == 0u)) {\n let background = sampleSceneBackground(lightRay);\n Li = background.rgb * background.a;\n }\n if (SPECTRAL${channelIndependentRis ? ' && rtUniform.dispersionWavelengths == 1' : ''}) {\n Li = sampling_spectral_rgb_filter(Li, (*si).spectralChannel);\n }\n\n // A directional source is a delta distribution and cannot be reached by\n // the BSDF-sampling strategy, so its light-sampled contribution has weight 1.\n let misWeight = select(\n neeMISWeight(lightPdf, scatteringPdf),\n 1.0,\n lightSample.isDelta\n );\n if (misWeight > 0.0) {\n let unweightedContribution = Li * f / lightPdf * (*path).beta;\n (*shadowWork).risTarget = max(\n dot(max(unweightedContribution * lightSelectionPmf, vec3f(0.0)), ${channelIndependentRis ? 'select(luminance, vec3f(1.0 / 3.0), SPECTRAL && rtUniform.dispersionWavelengths != 1)' : 'luminance'}),\n 0.0\n );\n (*shadowWork).ray = lightRay;\n (*shadowWork).maxDistance = visibilityDistance;\n (*shadowWork).triangleIndex = (*si).triangleIndex;\n (*shadowWork).contribution = misWeight * unweightedContribution;${channelIndependentRis ? /* wgsl */ `\n // Give each RGB component equal target weight for all three wavelengths.\n // Single-wavelength preview keeps its original luminance target. Filtering\n // only the estimator preserves the common reservoir and UCW normalization.\n if (SPECTRAL && rtUniform.dispersionWavelengths != 1) {\n (*shadowWork).contribution = sampling_spectral_rgb_filter((*shadowWork).contribution, (*si).spectralChannel);\n }` : ''}\n (*shadowWork).lightSelectionPmf = lightSelectionPmf;\n (*shadowWork).valid = true;\n return true;\n }\n return false;\n}\n\nstruct ScatteringWork {\n direction: vec3f,\n response: vec3f,\n pdf: f32,\n transmission: bool,\n}\n\nfn sampleScattering(\n si: ptr<function, SurfaceInteraction>,\n ma: OpenPbrResolvedMaterial,\n prepared: OpenPbrPreparedBsdf,\n path: ptr<function, Path>,\n ffnormal: vec3f,\n isSurface: bool\n) -> ScatteringWork {\n let candidateCount = neeCandidateCount();\n var selected: ShadowRayWork;\n selected.valid = false;\n var selectedTarget = 0.0;\n var scalarWeightSum = 0.0;\n var result: ScatteringWork;\n // The final iteration samples the continuation after NEE and its shadow ray.\n // Both proposals use one BSDF evaluation call site, avoiding a second inlined\n // optical graph. Keep all random draws and visibility queries in their\n // original order, including the short-circuit reservoir replacement draw.\n for (var event = 0u; event <= candidateCount; event++) {\n let continuation = event == candidateCount;\n var lightSample: LightSampleRec;\n var lightDir: vec3f;\n var scatteringPdf = 0.0;\n var response = vec3f(0.0);\n var discrete = false;\n if (continuation) {\n var candidateUCW = 1.0;\n var valid = selected.valid;\n if (candidateCount > 1u) {\n valid = valid & (selectedTarget > 0.0);\n if (valid) {\n candidateUCW = selected.lightSelectionPmf * scalarWeightSum /\n (f32(candidateCount) * selectedTarget);\n }\n }\n if (valid && !intersectSceneShadow(selected.ray, selected.maxDistance, selected.triangleIndex, (*si).instanceIndex)) {\n${caustics?` var connection=*path;\n if(isSurface&&isCausticSpecular(ma)){causticAdvance(&connection,ma,dot(ffnormal,selected.ray.d)<0.0,true);}\n connection.beta=vec3f(1.0);causticHotRecord(connection,selected.contribution*candidateUCW,0u);\n`:''} (*path).li += selected.contribution * candidateUCW;\n }\n if (!isSurface) {\n result.direction = sampling_henyey_greenstein(-(*path).ray.d,\n (*si).mediumAnisotropy, sample2D(bounceDim(PHASE_DIRECTION)));\n result.pdf = sampling_henyey_greenstein_phase(\n dot(result.direction, -(*path).ray.d), (*si).mediumAnisotropy);\n return result;\n }\n let matRnd = vec3f(sample2D(bounceDim(BSDF_DIRECTION)), sample1D(bounceDim(BSDF_LOBE)));\n discrete = !prepared.material.thinWalled &\n (abs(prepared.material.relativeIor - 1.0) <= 1e-6) &\n (prepared.probabilities[OPENPBR_LOBE_TRANSMISSION] >= 1.0 - 1e-6);\n if (discrete) {\n lightDir = openpbr_to_world(prepared.basis, -prepared.viewLocal);\n response = openpbr_transmission_tint(prepared.material) * openpbr_coat_base_scale(prepared,\n ${hasCoatNormals ? 'select(-prepared.viewLocal.z, dot(prepared.coatBasis.normal, lightDir), prepared.material.coatNormalEnabled)' : '-prepared.viewLocal.z'});\n scatteringPdf = 1.0;\n result.transmission = true;\n } else {\n var roughness = 1.0; var specular = false; var diffuse = true;\n var lobe = u32(OPENPBR_LOBE_DIFFUSE);\n // Use locals rather than member pointers for Naga's SPIR-V writer.\n var transmission = false;\n if (!openpbr_sample_direction(prepared, matRnd, &lightDir, &transmission,\n &roughness, &specular, &diffuse, &lobe)) { return result; }\n result.transmission = transmission;\n }\n } else {\n let lightRnd = vec3f(sample2D(lightDim(event, 1u)), sample1D(lightDim(event, 0u)));\n sampleLightForNEECandidate((*si).position, lightRnd, event, candidateCount, &lightSample);\n lightDir = lightSample.direction;\n if ((lightSample.pdf <= 0.0) | (lightSample.selectionPmf <= 0.0) |\n (max(max(lightSample.emission.x, lightSample.emission.y), lightSample.emission.z) <= 0.0)) { continue; }\n ${hasCoatNormals ? /* wgsl */ `var cosThetaL = dot(ffnormal, lightDir);\n if (isSurface & ma.coatNormalEnabled) { cosThetaL = dot(ma.geometricNormal, lightDir); }` : /* wgsl */ `let cosThetaL = dot(ffnormal, lightDir);`}\n if (isSurface & (cosThetaL <= 0.0) & (ma.transmissionWeight <= 0.0) & (ma.subsurfaceWeight <= 0.0)) { continue; }\n }\n if (!discrete) {\n if (isSurface) {\n response = openpbr_eval_prepared(prepared, lightDir, &scatteringPdf);\n } else {\n scatteringPdf = sampling_henyey_greenstein_phase(\n dot(-(*path).ray.d, lightDir), (*si).mediumAnisotropy);\n response = vec3f(scatteringPdf);\n }\n }\n if (continuation) {\n result.direction = lightDir; result.response = response; result.pdf = scatteringPdf;\n return result;\n }\n var candidate: ShadowRayWork;\n let candidateValid = finishDirectLight(si, ma, path, ffnormal, isSurface,\n lightSample, response, scatteringPdf, &candidate);\n if (!candidateValid) { continue; }\n if (candidateCount == 1u) {\n selected = candidate;\n continue;\n }\n let scalarWeight = candidate.risTarget / max(candidate.lightSelectionPmf, 1e-20);\n if (!(scalarWeight > 0.0) | (scalarWeight != scalarWeight)) { continue; }\n scalarWeightSum += scalarWeight;\n if (!selected.valid ||\n lightCandidateRandom(event) * scalarWeightSum <= scalarWeight) {\n selected = candidate;\n selectedTarget = candidate.risTarget;\n }\n }\n return result;\n}\n\nfn emissiveHitMisWeight(\n si: ptr<function, SurfaceInteraction>,\n path: ptr<function, Path>\n) -> f32 {${caustics ? /* wgsl */ `\n if (causticHitOwned(*path, true, true)) { return 0.0; }` : ''}\n // Secondary traversal accepts back faces for transmission; a one-sided\n // emitter still radiates only into its front hemisphere.\n let cosLight = dot((*si).faceNormal, -(*path).ray.d);\n if (cosLight <= 0.0 && materialsBuffer[(*si).materialIndex].doubleSided < 0.5) { return 0.0; }\n if ((*path).fromEye | (rtUniform.lightWeightTotal <= 0.0) |\n (i32(materialsBuffer[(*si).materialIndex].matType) == UNLIT)) {\n return 1.0;\n }\n let samplingLuminance = dot(\n materialsBuffer[(*si).materialIndex].emission,\n luminance\n );\n if ((samplingLuminance <= 0.0) | (cosLight <= 0.0)) {\n return 1.0;\n }\n let hitDistance = distance((*si).position, (*path).ray.o);\n let lightPdf = samplingLuminance / rtUniform.lightWeightTotal *\n hitDistance * hitDistance / max(cosLight, 1e-8);\n return bsdfMISWeight((*path).scatteringPdf, lightPdf);\n}\n\n${hasCoatNormals ? /* wgsl */ `\n// Keep each shading frame in the geometric/view hemisphere. This correction\n// does not replace the face normal used for topology or ray offsets.\nfn coat_frame_normal(input: vec3f, face: vec3f, view: vec3f) -> vec3f {\n let front = dot(face, view) >= 0.0;\n let ffFace = select(-face, face, front);\n let ffInput = select(-input, input, front);\n if ((dot(input, face) <= 0.0) | (dot(ffInput, view) <= 1e-6)) { return ffFace; }\n return ffInput;\n}\n` : ''}\nfn SampleMaterial(\n si: ptr<function, SurfaceInteraction>,\n ma: ptr<function, OpenPbrResolvedMaterial>,\n path: ptr<function, Path>\n) {\n${hasCoatNormals ? /* wgsl */ `\n let originalFace = (*si).faceNormal;\n let originalNormal = (*si).normal;\n` : ''}\n var ndv1: f32 = -dot((*si).faceNormal, (*path).ray.d);\n var ndv2: f32 = -dot((*si).normal, (*path).ray.d);\n if ((((*ma).transmissionWeight > 0.0) | ((*ma).subsurfaceWeight > 0.0)) & (*ma).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 var useFaceN: bool = (ndv1 >= 0.0) & (ndv2 < 0.0);\n var ndv: f32 = select(ndv2, ndv1, useFaceN);\n var N: vec3f = select((*si).normal, (*si).faceNormal, useFaceN);\n\n (*ma).inside = (ndv <= 0.0) & !(*ma).thinWalled;\n // In or out\n (*ma).relativeIor = select((*ma).specularIor, (1.0 / (*ma).specularIor), ndv > 0.0);\n var ffnormal = select(-N, N, ndv >= 0.0);\n${hasCoatNormals ? /* wgsl */ `\n if ((*ma).coatNormalEnabled) {\n let view = -(*path).ray.d;\n let geometricView = dot(originalFace, view);\n (*ma).geometricNormal = select(-originalFace, originalFace, geometricView >= 0.0);\n ffnormal = coat_frame_normal(originalNormal, originalFace, view);\n (*ma).coatNormal = coat_frame_normal((*si).coatNormal, originalFace, view);\n (*ma).inside = (geometricView <= 0.0) & !(*ma).thinWalled;\n (*ma).relativeIor = select((*ma).specularIor, 1.0 / (*ma).specularIor, (geometricView > 0.0) | (*ma).thinWalled);\n }\n` : ''}\n\n (*path).scatteringIsDelta = false;\n var mediumSampled = false;\n var crossedBoundary = false;\n let mediumType = (*si).mediumType;\n\n var scatteringPdf: f32;\n var scatterDir: vec3f;\n\n if (HAS_MEDIUM) {\n let d = distance((*si).position, (*path).ray.o);\n let segmentOrigin = (*path).ray.o;\n let extinction = (*si).mediumExtinction;\n let scattering = min((*si).mediumScattering, extinction);\n let 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 // avoids high-variance majorant weights for channel-dependent SSS radii.\n let mediumChannel = min(i32(sample1D(bounceDim(MEDIUM_CHANNEL)) * 3.0), 2);\n let channelExtinction = extinction[mediumChannel];\n let scatterDist = select(\n d,\n min(-log(max(sample1D(bounceDim(MEDIUM_DISTANCE)), 1e-7)) / channelExtinction, d),\n channelExtinction > 0.0\n );\n mediumSampled = scatterDist < d;\n let transmittance = exp(-extinction * scatterDist);\n let density = select(\n transmittance,\n extinction * transmittance,\n mediumSampled\n );\n let mediumPdf = max((density.x + density.y + density.z) / 3.0, 1e-8);\n if (mediumSampled) {\n (*path).beta *= transmittance * scattering / mediumPdf;\n // Zero throughput cannot contribute at subsequent vertices or light connections.\n if (all((*path).beta == vec3f(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 }\n else {\n (*path).beta *= transmittance / mediumPdf;\n // Zero throughput cannot contribute at subsequent vertices or light connections.\n if (all((*path).beta == vec3f(0.0))) { (*path).abort = true; return; }\n }\n }\n }\n\n if (!mediumSampled) {\n // Each spectral path carries one channel, including directly hit emitters.\n // Keep the full material emission in the light-selection/MIS density.\n var surfaceEmission = (*ma).emission;\n if (SPECTRAL) {\n surfaceEmission = sampling_spectral_rgb_filter(surfaceEmission, (*si).spectralChannel);\n }\n${caustics?` let emissionWeight=emissiveHitMisWeight(si,path);\n causticHotRecord(*path,emissionWeight*surfaceEmission,1u);causticEmitterRecord(*si,*path,emissionWeight,surfaceEmission);\n (*path).li+=emissionWeight*surfaceEmission*(*path).beta;`:' (*path).li += emissiveHitMisWeight(si, path) * surfaceEmission * (*path).beta;'}\n }\n if ((*ma).materialType == UNLIT) {\n (*path).abort = true;\n return;\n }\n // Surface and medium events share the light estimator. Emission is added\n // before NEE, then the continuation direction is sampled.\n var prepared: OpenPbrPreparedBsdf;\n if (!mediumSampled) {\n${hasAnisotropyDirections ? /* wgsl */ `\n (*ma).directionTangent = (*si).directionTangent;\n (*ma).directionBitangent = (*si).directionBitangent;\n (*ma).geometryTangent = (*si).geometryTangent;\n (*ma).geometryBitangent = (*si).geometryBitangent;\n` : /* wgsl */ ``}\n prepared = openpbr_prepare((*si).tangent, *ma, -(*path).ray.d, ffnormal);\n }\n${researchContribution}${photonMapping?/* wgsl */ ` if(!mediumSampled){let value=(*path).beta*photonContribution(*si,prepared,(*path).fromEye,!(*path).causticHasReceiver);causticEstimateRecord(value,1u);(*path).li+=value;}\n` : ''} let scattered = sampleScattering(si, *ma, prepared, path, ffnormal, !mediumSampled);\n scatterDir = scattered.direction;\n scatteringPdf = scattered.pdf;\n if (!mediumSampled) {\n let f = scattered.response;\n let isNextRefraction = scattered.transmission;\n // A rejected microfacet proposal (including failed refraction), or a\n // material with no scattering lobes, has no continuation. Keep emission\n // and NEE already accumulated at this vertex, but never trace a default\n // direction with the incoming throughput: that invents extra light paths.\n if (!(scatteringPdf > 0.0) |\n !all(f == f) | !all(abs(f) < vec3f(3.402823e38)) |\n (dot(scatterDir, scatterDir) < 0.5)) {\n (*path).scatteringPdf = 0.0;\n (*path).abort = true;\n return;\n }\n // Exactly index-matched solid transmission is a discrete null boundary;\n // environment NEE has no competing density for that event.\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${caustics ? /* wgsl */ ` causticAdvance(path, *ma, isNextRefraction, true);\n` : ''} (*path).beta *= f / scatteringPdf;\n // Zero throughput cannot contribute at subsequent vertices or light connections.\n if (all((*path).beta == vec3f(0.0))) { (*path).abort = true; return; }\n\n crossedBoundary = isNextRefraction & !(*ma).thinWalled;\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${hasCoatNormals ? /* wgsl */ `\n if ((*ma).coatNormalEnabled) { (*path).ray.o = (*si).position + EPS * select(-originalFace, originalFace, dot(originalFace, scatterDir) >= 0.0); }\n` : ''}\n }\n (*path).scatteringPdf = scatteringPdf;\n (*path).ray.d = scatterDir;\n if (mediumSampled) {${caustics ? /* wgsl */ `\n causticAdvance(path, *ma, false, false);` : ''}\n (*path).isNextRefraction = false;\n }\n\n (*path).fromEye = false;\n\n if (HAS_MEDIUM) {\n // Reflections stay in the current medium. Enter or leave only after the\n // BSDF actually sampled transmission through a medium boundary.\n if (!mediumSampled & crossedBoundary & ((*ma).mediumType > 0)) {\n if (ndv1 >= 0.0) {\n (*si).mediumType = (*ma).mediumType;\n (*si).mediumExtinction = (*ma).mediumExtinction;\n (*si).mediumScattering = (*ma).mediumScattering;\n (*path).scatteringMediumEntered = (*path).scatteringMediumEntered || any((*ma).mediumScattering > vec3f(0.0));\n (*si).mediumAnisotropy = (*ma).mediumAnisotropy;\n }\n else {\n (*si).mediumType = 0;\n (*si).mediumExtinction = vec3f(0.0);\n (*si).mediumScattering = vec3f(0.0);\n (*si).mediumAnisotropy = 0.0;\n }\n }\n }\n}\n`;\n\n}\n\nexport default createSampleMaterialWgsl();\n"]}
|
|
@@ -16,7 +16,7 @@ const SHADOW_CATCHER_LIGHT_SAMPLES = 4u;
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
fn sampleShadowCatcher(si: SurfaceInteraction, bounce: i32, path: ptr<function, Path>) -> vec2f {
|
|
19
|
-
let
|
|
19
|
+
let sg = -(*path).ray.d;
|
|
20
20
|
var counts = vec2f(0.0);
|
|
21
21
|
|
|
22
22
|
|
|
@@ -24,10 +24,10 @@ var counts = vec2f(0.0);
|
|
|
24
24
|
if (rtUniform.shadowCatcherChoiceCount > 0) {
|
|
25
25
|
for (var candidate = 0u; candidate < SHADOW_CATCHER_LIGHT_SAMPLES; candidate++) {
|
|
26
26
|
var lightSample: LightSampleRec;
|
|
27
|
-
let
|
|
28
|
-
|
|
27
|
+
let ob = vec3f(sample2D(tF(candidate, 1u)), sample1D(tF(candidate, 0u)));
|
|
28
|
+
hz(
|
|
29
29
|
si.position,
|
|
30
|
-
|
|
30
|
+
ob,
|
|
31
31
|
rtUniform.shadowCatcherChoiceOffset,
|
|
32
32
|
rtUniform.shadowCatcherChoiceCount,
|
|
33
33
|
1.0,
|
|
@@ -35,13 +35,13 @@ rtUniform.shadowCatcherChoiceCount,
|
|
|
35
35
|
);
|
|
36
36
|
let lightDir = lightSample.direction;
|
|
37
37
|
let cosThetaL = dot(si.normal, lightDir);
|
|
38
|
-
let
|
|
39
|
-
if (lightSample.pdf > 0.0 &&
|
|
38
|
+
let rG = dot(si.normal, sg) * cosThetaL;
|
|
39
|
+
if (lightSample.pdf > 0.0 && rG >= 0.0) {
|
|
40
40
|
if (dot(lightSample.emission, luminance) * abs(cosThetaL) > 0.0) {
|
|
41
41
|
var ray: Ray;
|
|
42
42
|
initRay(&ray, si.position + EPS * lightDir, lightDir);
|
|
43
|
-
let
|
|
44
|
-
counts += vec2f(select(0.0, 1.0,
|
|
43
|
+
let mz = intersectSceneShadow(ray, lightSample.dist - EPS, si.triangleIndex,si.instanceIndex);
|
|
44
|
+
counts += vec2f(select(0.0, 1.0, mz), 1.0);
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
}
|
|
@@ -4,70 +4,70 @@ export default /*wgsl*/ `
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
fn aA(view: vec3f, alpha: vec2f, samplePoint: vec2f) -> vec3f {
|
|
7
|
-
let
|
|
8
|
-
let
|
|
9
|
-
let
|
|
10
|
-
let
|
|
11
|
-
let
|
|
12
|
-
let
|
|
13
|
-
let
|
|
14
|
-
let
|
|
7
|
+
let qD = vec3f(alpha, 1.0);
|
|
8
|
+
let cf = normalize(qD * view);
|
|
9
|
+
let rU = min(cf.z, 1.0);
|
|
10
|
+
let ku = 1.0 + rU;
|
|
11
|
+
let kM = (1.0 - samplePoint.y) * ku;
|
|
12
|
+
let ur = samplePoint.y * ku;
|
|
13
|
+
let vK = kM + (1.0 - rU);
|
|
14
|
+
let dw = sqrt(max(0.0, vK * ur));
|
|
15
15
|
let azimuth = TWOPI * samplePoint.x;
|
|
16
|
-
let
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
let mR = vec3f(
|
|
17
|
+
cf.x + dw * cos(azimuth),
|
|
18
|
+
cf.y + dw * sin(azimuth),
|
|
19
|
+
kM
|
|
20
20
|
);
|
|
21
|
-
return normalize(
|
|
21
|
+
return normalize(qD * mR);
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
fn sampling_ggx_ndf(
|
|
25
|
-
let
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
fn sampling_ggx_ndf(qc: vec3f, alpha: vec2f) -> f32 {
|
|
25
|
+
let hG = vec3f(
|
|
26
|
+
qc.x / alpha.x,
|
|
27
|
+
qc.y / alpha.y,
|
|
28
|
+
qc.z
|
|
29
29
|
);
|
|
30
|
-
let ah = dot(
|
|
30
|
+
let ah = dot(hG, hG);
|
|
31
31
|
return 1.0 / (
|
|
32
32
|
PI * alpha.x * alpha.y * ah * ah
|
|
33
33
|
);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
fn aD(direction: vec3f, alpha: vec2f) -> f32 {
|
|
37
|
-
let
|
|
38
|
-
if (
|
|
37
|
+
let eK = abs(direction.z);
|
|
38
|
+
if (eK <= 1e-8) {
|
|
39
39
|
return 0.0;
|
|
40
40
|
}
|
|
41
|
-
let
|
|
42
|
-
let
|
|
43
|
-
/ (
|
|
44
|
-
return 2.0 / (1.0 + sqrt(1.0 +
|
|
41
|
+
let iK = alpha * direction.xy;
|
|
42
|
+
let mS = dot(iK, iK)
|
|
43
|
+
/ (eK * eK);
|
|
44
|
+
return 2.0 / (1.0 + sqrt(1.0 + mS));
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
fn
|
|
48
|
-
let
|
|
49
|
-
return pow(
|
|
47
|
+
fn aI(cosine: f32) -> f32 {
|
|
48
|
+
let da = clamp(1.0 - cosine, 0.0, 1.0);
|
|
49
|
+
return pow(da, 5.0);
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
fn sampling_dielectric_fresnel(J: f32,
|
|
53
|
-
let
|
|
54
|
-
let
|
|
55
|
-
* max(0.0, 1.0 -
|
|
56
|
-
if (
|
|
52
|
+
fn sampling_dielectric_fresnel(J: f32, cH: f32) -> f32 {
|
|
53
|
+
let ja = clamp(abs(J), 0.0, 1.0);
|
|
54
|
+
let ld = cH * cH
|
|
55
|
+
* max(0.0, 1.0 - ja * ja);
|
|
56
|
+
if (ld >= 1.0) {
|
|
57
57
|
return 1.0;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
let
|
|
61
|
-
let
|
|
62
|
-
/ max(
|
|
63
|
-
let
|
|
64
|
-
/ max(
|
|
60
|
+
let nh = sqrt(max(0.0, 1.0 - ld));
|
|
61
|
+
let bf = (ja - cH * nh)
|
|
62
|
+
/ max(ja + cH * nh, 1e-8);
|
|
63
|
+
let rH = (cH * ja - nh)
|
|
64
|
+
/ max(cH * ja + nh, 1e-8);
|
|
65
65
|
return 0.5 * (
|
|
66
|
-
|
|
66
|
+
bf * bf + rH * rH
|
|
67
67
|
);
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
fn
|
|
70
|
+
fn gA(samplePoint: vec2f) -> vec2f {
|
|
71
71
|
let offset = 2.0 * samplePoint - vec2f(1.0);
|
|
72
72
|
if (offset.x == 0.0 && offset.y == 0.0) {
|
|
73
73
|
return vec2f(0.0);
|
|
@@ -87,21 +87,21 @@ return radius * vec2f(cos(angle), sin(angle));
|
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
fn aM(samplePoint: vec2f) -> vec3f {
|
|
90
|
-
let
|
|
90
|
+
let lL = gA(samplePoint);
|
|
91
91
|
return vec3f(
|
|
92
|
-
|
|
93
|
-
sqrt(max(0.0, 1.0 - dot(
|
|
92
|
+
lL,
|
|
93
|
+
sqrt(max(0.0, 1.0 - dot(lL, lL)))
|
|
94
94
|
);
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
fn
|
|
97
|
+
fn aG(firstPdf: f32, secondPdf: f32) -> f32 {
|
|
98
98
|
let scale = max(firstPdf, secondPdf);
|
|
99
99
|
if (scale <= 0.0) {
|
|
100
100
|
return 0.0;
|
|
101
101
|
}
|
|
102
102
|
let normalized = vec2f(firstPdf, secondPdf) / scale;
|
|
103
|
-
let
|
|
104
|
-
return
|
|
103
|
+
let qC = normalized * normalized;
|
|
104
|
+
return qC.x / (qC.x + qC.y);
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
fn sampling_orthonormal_basis(
|
|
@@ -109,17 +109,17 @@ normal: vec3f,
|
|
|
109
109
|
tangent: ptr<function, vec3f>,
|
|
110
110
|
bitangent: ptr<function, vec3f>
|
|
111
111
|
) {
|
|
112
|
-
let
|
|
113
|
-
let
|
|
114
|
-
let xy = normal.x * normal.y *
|
|
112
|
+
let iP = select(-1.0, 1.0, normal.z >= 0.0);
|
|
113
|
+
let cA = -1.0 / (iP + normal.z);
|
|
114
|
+
let xy = normal.x * normal.y * cA;
|
|
115
115
|
*tangent = vec3f(
|
|
116
|
-
1.0 +
|
|
117
|
-
|
|
118
|
-
-
|
|
116
|
+
1.0 + iP * normal.x * normal.x * cA,
|
|
117
|
+
iP * xy,
|
|
118
|
+
-iP * normal.x
|
|
119
119
|
);
|
|
120
120
|
*bitangent = vec3f(
|
|
121
121
|
xy,
|
|
122
|
-
|
|
122
|
+
iP + normal.y * normal.y * cA,
|
|
123
123
|
-normal.y
|
|
124
124
|
);
|
|
125
125
|
}
|
|
@@ -135,30 +135,30 @@ return filtered;
|
|
|
135
135
|
|
|
136
136
|
fn sampling_cauchy_ior(
|
|
137
137
|
wavelength: f32,
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
138
|
+
hy: f32,
|
|
139
|
+
hF: f32,
|
|
140
|
+
sD: f32
|
|
141
141
|
) -> f32 {
|
|
142
|
-
if (wavelength == 0.0 ||
|
|
143
|
-
return
|
|
142
|
+
if (wavelength == 0.0 || hF <= 0.0) {
|
|
143
|
+
return hy;
|
|
144
144
|
}
|
|
145
145
|
|
|
146
146
|
let FRAUNHOFER_C = 656.3;
|
|
147
147
|
let FRAUNHOFER_D = 587.6;
|
|
148
148
|
let FRAUNHOFER_F = 486.1;
|
|
149
|
-
let
|
|
149
|
+
let kD = 1.0 / (
|
|
150
150
|
1.0 / (FRAUNHOFER_F * FRAUNHOFER_F)
|
|
151
151
|
- 1.0 / (FRAUNHOFER_C * FRAUNHOFER_C)
|
|
152
152
|
);
|
|
153
|
-
let
|
|
154
|
-
let
|
|
155
|
-
let
|
|
156
|
-
-
|
|
157
|
-
return
|
|
153
|
+
let oT = max(sD / hF, 1e-6);
|
|
154
|
+
let tj = (hy - 1.0) * kD / oT;
|
|
155
|
+
let wx = hy
|
|
156
|
+
- tj / (FRAUNHOFER_D * FRAUNHOFER_D);
|
|
157
|
+
return wx + tj / (wavelength * wavelength);
|
|
158
158
|
}
|
|
159
159
|
|
|
160
|
-
fn
|
|
161
|
-
|
|
160
|
+
fn dQ(
|
|
161
|
+
gQ: vec3f,
|
|
162
162
|
anisotropy: f32,
|
|
163
163
|
samplePoint: vec2f
|
|
164
164
|
) -> vec3f {
|
|
@@ -167,24 +167,24 @@ if (abs(anisotropy) < 0.001) {
|
|
|
167
167
|
cosine = 1.0 - 2.0 * samplePoint.y;
|
|
168
168
|
}
|
|
169
169
|
else {
|
|
170
|
-
let
|
|
170
|
+
let fw = (1.0 - anisotropy * anisotropy)
|
|
171
171
|
/ (1.0 + anisotropy - 2.0 * anisotropy * samplePoint.y);
|
|
172
172
|
cosine = (
|
|
173
|
-
|
|
173
|
+
fw * fw - 1.0 - anisotropy * anisotropy
|
|
174
174
|
) / (2.0 * anisotropy);
|
|
175
175
|
}
|
|
176
176
|
|
|
177
|
-
let
|
|
177
|
+
let wk = sqrt(max(0.0, 1.0 - cosine * cosine));
|
|
178
178
|
let azimuth = TWOPI * samplePoint.x;
|
|
179
179
|
var tangent: vec3f;
|
|
180
180
|
var bitangent: vec3f;
|
|
181
|
-
sampling_orthonormal_basis(
|
|
182
|
-
return tangent * (
|
|
183
|
-
+ bitangent * (
|
|
184
|
-
+
|
|
181
|
+
sampling_orthonormal_basis(gQ, &tangent, &bitangent);
|
|
182
|
+
return tangent * (wk * cos(azimuth))
|
|
183
|
+
+ bitangent * (wk * sin(azimuth))
|
|
184
|
+
+ gQ * cosine;
|
|
185
185
|
}
|
|
186
186
|
|
|
187
|
-
fn
|
|
187
|
+
fn ba(cosine: f32, anisotropy: f32) -> f32 {
|
|
188
188
|
let ah = 1.0 + anisotropy * anisotropy
|
|
189
189
|
+ 2.0 * anisotropy * cosine;
|
|
190
190
|
return INV4PI * (1.0 - anisotropy * anisotropy)
|
|
@@ -16,41 +16,41 @@ const BOUNCE_STRIDE = 64u;
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
var<private>
|
|
19
|
+
var<private> aJ: vec2u;
|
|
20
20
|
var<private> aC: u32;
|
|
21
21
|
var<private> samplingBounce: u32 = 0u;
|
|
22
|
-
var<private>
|
|
23
|
-
fn
|
|
24
|
-
var x =
|
|
22
|
+
var<private> hashedCounter: u32 = 0u;
|
|
23
|
+
fn cD(lm: u32) -> u32 {
|
|
24
|
+
var x = lm;
|
|
25
25
|
x ^= x >> 16u; x *= 0x7feb352du;
|
|
26
26
|
x ^= x >> 15u; x *= 0x846ca68bu;
|
|
27
27
|
return x ^ (x >> 16u);
|
|
28
28
|
}
|
|
29
29
|
fn ak(a: u32, b: u32) -> u32 {
|
|
30
|
-
return
|
|
30
|
+
return cD(a ^ cD(b + 0x9e3779b9u));
|
|
31
31
|
}
|
|
32
|
-
fn
|
|
33
|
-
var x =
|
|
32
|
+
fn jc(lm: u32, seed: u32) -> u32 {
|
|
33
|
+
var x = lm + seed;
|
|
34
34
|
x ^= x * 0x6c50b47cu; x ^= x * 0xb82f1e52u;
|
|
35
35
|
x ^= x * 0xc7afe638u; x ^= x * 0x8d22f6e6u;
|
|
36
36
|
return x;
|
|
37
37
|
}
|
|
38
|
-
fn
|
|
39
|
-
return reverseBits(
|
|
38
|
+
fn vN(x: u32, seed: u32) -> u32 {
|
|
39
|
+
return reverseBits(jc(reverseBits(x), seed));
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
fn
|
|
43
|
-
var r = reverseBits(
|
|
42
|
+
fn tP(lm: u32) -> u32 {
|
|
43
|
+
var r = reverseBits(lm);
|
|
44
44
|
${sobolD1Steps.map(([shift, mask]) => `r ^= (r << ${shift}u) & 0x${mask.toString(16)}u;`).join("\n ")}
|
|
45
45
|
return r;
|
|
46
46
|
}
|
|
47
|
-
fn
|
|
48
|
-
let i =
|
|
49
|
-
let x = reverseBits(
|
|
50
|
-
let y =
|
|
47
|
+
fn Ac(index: u32, seed: u32) -> vec2f {
|
|
48
|
+
let i = vN(index, ak(seed, 0u));
|
|
49
|
+
let x = reverseBits(jc(i, ak(seed, 1u)));
|
|
50
|
+
let y = vN(tP(i), ak(seed, 2u));
|
|
51
51
|
return vec2f(f32(x >> 8u), f32(y >> 8u)) * (1.0 / 16777216.0);
|
|
52
52
|
}
|
|
53
|
-
fn
|
|
53
|
+
fn wL(p: vec2u) -> u32 {
|
|
54
54
|
var v = p & vec2u(255u);
|
|
55
55
|
v = (v | (v << vec2u(4u))) & vec2u(0x0f0fu);
|
|
56
56
|
v = (v | (v << vec2u(2u))) & vec2u(0x3333u);
|
|
@@ -58,112 +58,112 @@ v = (v | (v << vec2u(1u))) & vec2u(0x5555u);
|
|
|
58
58
|
return v.x | (v.y << 1u);
|
|
59
59
|
}
|
|
60
60
|
${zSobolPackedPermutations.map((v, i) => `const Z_PERM_${i} = ${v}u;`).join("\n")}
|
|
61
|
-
fn
|
|
62
|
-
let group =
|
|
61
|
+
fn lq(wO: u32) -> u32 {
|
|
62
|
+
let group = wO >> 2u;
|
|
63
63
|
var word = Z_PERM_5;
|
|
64
64
|
${[0, 1, 2, 3, 4].map(i => `word = select(word, Z_PERM_${i}, group == ${i}u);`).join("\n ")}
|
|
65
|
-
return (word >> ((
|
|
65
|
+
return (word >> ((wO & 3u) * 8u)) & 255u;
|
|
66
66
|
}
|
|
67
|
-
fn
|
|
67
|
+
fn rX(lS: u32, dim: u32, logSPP: u32) -> u32 {
|
|
68
68
|
let odd = logSPP & 1u;
|
|
69
|
-
let
|
|
69
|
+
let xX = 8u + ((logSPP + 1u) >> 1u);
|
|
70
70
|
var result = 0u;
|
|
71
|
-
for (var digit = i32(
|
|
71
|
+
for (var digit = i32(xX) - 1; digit >= i32(odd); digit--) {
|
|
72
72
|
let shift = 2u*u32(digit) - odd;
|
|
73
73
|
|
|
74
|
-
var
|
|
75
|
-
if (shift < 30u) {
|
|
76
|
-
let
|
|
77
|
-
let d = (
|
|
78
|
-
result |= ((
|
|
74
|
+
var vs = 0u;
|
|
75
|
+
if (shift < 30u) { vs = lS >> (shift + 2u); }
|
|
76
|
+
let wO = (cD(vs ^ (0x55555555u * dim)) >> 24u) % 24u;
|
|
77
|
+
let d = (lS >> shift) & 3u;
|
|
78
|
+
result |= ((lq(wO) >> (2u*d)) & 3u) << shift;
|
|
79
79
|
}
|
|
80
80
|
if (odd != 0u) {
|
|
81
|
-
result |= (
|
|
81
|
+
result |= (lS & 1u) ^ (cD((lS >> 1u) ^ (0x55555555u * dim)) & 1u);
|
|
82
82
|
}
|
|
83
83
|
return result;
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
|
|
87
87
|
|
|
88
|
-
fn
|
|
88
|
+
fn aX(slot: u32) -> u32 {
|
|
89
89
|
return CAMERA_BEVEL_BASE + u32(BEVEL_SAMPLES) + samplingBounce * BOUNCE_STRIDE + slot;
|
|
90
90
|
}
|
|
91
|
-
fn
|
|
91
|
+
fn tF(candidate: u32, slot: u32) -> u32 {
|
|
92
92
|
if (candidate == 0u) {
|
|
93
|
-
if (slot == 2u) { return
|
|
94
|
-
return
|
|
93
|
+
if (slot == 2u) { return aX(8u); }
|
|
94
|
+
return aX(slot);
|
|
95
95
|
}
|
|
96
|
-
return
|
|
96
|
+
return aX(9u + (candidate - 1u) * 3u + slot);
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
|
|
100
|
-
var<private>
|
|
101
|
-
var<private>
|
|
102
|
-
var<private>
|
|
103
|
-
var<private>
|
|
104
|
-
var<private>
|
|
105
|
-
var<private>
|
|
106
|
-
var<private>
|
|
107
|
-
fn
|
|
100
|
+
var<private> hC: vec4u;
|
|
101
|
+
var<private> hD: u32;
|
|
102
|
+
var<private> fM: bool = false;
|
|
103
|
+
var<private> cZ: bool = false;
|
|
104
|
+
var<private> dF: u32;
|
|
105
|
+
var<private> gM: u32;
|
|
106
|
+
var<private> eT: vec2f;
|
|
107
|
+
fn ds(dim: u32) {
|
|
108
108
|
|
|
109
|
-
let
|
|
110
|
-
let key = vec4u(dim, aC,
|
|
111
|
-
if (
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
var seed = ak(ak(
|
|
109
|
+
let kT = aJ.x + aJ.y * u32(rtUniform.outputSize.x);
|
|
110
|
+
let key = vec4u(dim, aC, kT, rtUniform.sequenceSeed);
|
|
111
|
+
if (fM && all(hC == key) && hD == rtUniform.zSobolLogSPP) { return; }
|
|
112
|
+
hC = key; hD = rtUniform.zSobolLogSPP;
|
|
113
|
+
fM = true; cZ = false;
|
|
114
|
+
var seed = ak(ak(kT, dim), rtUniform.sequenceSeed);
|
|
115
115
|
var index = aC;
|
|
116
116
|
if (SAMPLING_PATTERN == 1) {
|
|
117
117
|
var logSPP = rtUniform.zSobolLogSPP;
|
|
118
118
|
if (index == 0u) { logSPP = 0u; }
|
|
119
119
|
else { index -= 1u; }
|
|
120
120
|
|
|
121
|
-
var
|
|
121
|
+
var jH = index >> logSPP;
|
|
122
122
|
let mask = (1u << logSPP) - 1u;
|
|
123
|
-
let
|
|
124
|
-
index =
|
|
125
|
-
let tile =
|
|
123
|
+
let lS = (wL(aJ) << logSPP) | (index & mask);
|
|
124
|
+
index = rX(lS, dim, logSPP);
|
|
125
|
+
let tile = aJ >> vec2u(8u);
|
|
126
126
|
seed = ak(ak(dim, rtUniform.sequenceSeed), ak(tile.x, tile.y));
|
|
127
127
|
|
|
128
|
-
if (aC != 0u) {
|
|
129
|
-
seed = ak(seed,
|
|
128
|
+
if (aC != 0u) { jH += 1u; }
|
|
129
|
+
seed = ak(seed, jH);
|
|
130
130
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
let x = reverseBits(
|
|
134
|
-
|
|
131
|
+
dF = vN(index, ak(seed, 0u));
|
|
132
|
+
gM = seed;
|
|
133
|
+
let x = reverseBits(jc(dF, ak(seed, 1u)));
|
|
134
|
+
eT.x = f32(x >> 8u) * (1.0 / 16777216.0);
|
|
135
135
|
}
|
|
136
|
-
fn
|
|
137
|
-
|
|
138
|
-
if (!
|
|
139
|
-
let y =
|
|
140
|
-
|
|
141
|
-
|
|
136
|
+
fn lZ(dim: u32) -> vec2f {
|
|
137
|
+
ds(dim);
|
|
138
|
+
if (!cZ) {
|
|
139
|
+
let y = vN(tP(dF), ak(gM, 2u));
|
|
140
|
+
eT.y = f32(y >> 8u) * (1.0 / 16777216.0);
|
|
141
|
+
cZ = true;
|
|
142
142
|
}
|
|
143
|
-
return EPS + (1.0 - 2.0*EPS) *
|
|
143
|
+
return EPS + (1.0 - 2.0*EPS) * eT;
|
|
144
144
|
}
|
|
145
145
|
fn sample1D(dim: u32) -> f32 {
|
|
146
146
|
if (SAMPLING_PATTERN == 2) { return EPS + (1.0 - 2.0*EPS)*rand(); }
|
|
147
|
-
|
|
148
|
-
return EPS + (1.0 - 2.0*EPS) *
|
|
147
|
+
ds(dim);
|
|
148
|
+
return EPS + (1.0 - 2.0*EPS) * eT.x;
|
|
149
149
|
}
|
|
150
150
|
fn sample2D(dim: u32) -> vec2f {
|
|
151
151
|
if (SAMPLING_PATTERN == 2) {
|
|
152
152
|
let x = sample1D(dim); let y = sample1D(dim);
|
|
153
153
|
return vec2f(x,y);
|
|
154
154
|
}
|
|
155
|
-
return
|
|
155
|
+
return lZ(dim);
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
-
fn
|
|
159
|
-
let dim = ak(ak(samplingBounce, slot),
|
|
160
|
-
|
|
158
|
+
fn cm(slot: u32) -> f32 {
|
|
159
|
+
let dim = ak(ak(samplingBounce, slot), hashedCounter) | 0x80000000u;
|
|
160
|
+
hashedCounter += 1u;
|
|
161
161
|
if (SAMPLING_PATTERN == 2) { return EPS + (1.0 - 2.0*EPS)*rand(); }
|
|
162
162
|
|
|
163
|
-
let
|
|
164
|
-
let seed = ak(ak(
|
|
165
|
-
let i =
|
|
166
|
-
let x = reverseBits(
|
|
163
|
+
let kT = aJ.x + aJ.y * u32(rtUniform.outputSize.x);
|
|
164
|
+
let seed = ak(ak(kT, dim), rtUniform.sequenceSeed);
|
|
165
|
+
let i = vN(aC, ak(seed, 0u));
|
|
166
|
+
let x = reverseBits(jc(i, ak(seed, 1u)));
|
|
167
167
|
return EPS + (1.0 - 2.0*EPS) * (f32(x >> 8u) * (1.0 / 16777216.0));
|
|
168
168
|
}
|
|
169
169
|
`;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare function spectralPrefixWgsl(shareSecondary?: boolean): string;
|
|
2
|
+
export type PrefixBindings = Record<string, [type: string, expression: string]>;
|
|
3
|
+
export declare const prefixRandomBindings: PrefixBindings;
|
|
4
|
+
export declare function prefixCheckpoint(name: string, bindings: PrefixBindings): string;
|
|
5
|
+
export declare function prefixSave(name: string, bindings: PrefixBindings): string;
|
|
6
|
+
export declare function prefixRestore(name: string, bindings: PrefixBindings): string;
|