@meimu/mutracer 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/dist/assets/bvh.worker.js +1 -1
- package/dist/mutracer.umd.js +8949 -7915
- package/docs/api.md +42 -21
- package/docs/caustics.md +80 -0
- package/docs/materials.md +5 -4
- package/docs/progressive-rendering.md +50 -9
- package/docs/technical/continuous-spectrum.md +93 -0
- package/docs/updates.md +3 -1
- package/docs/viewer-checklist.md +65 -0
- package/docs/viewer.md +7 -5
- package/lib/Display.js +1 -1
- package/lib/Display.js.map +1 -1
- package/lib/Engine.d.ts +2 -0
- package/lib/Engine.js +47 -12
- package/lib/Engine.js.map +1 -1
- package/lib/Render.d.ts +61 -13
- package/lib/Render.js +169 -19
- 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 +1 -1
- package/lib/main.js.map +1 -1
- package/lib/oidn.d.ts +1 -1
- package/lib/oidnBundledWeights.cdn.d.ts +2 -2
- 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/RenderingPipeline.d.ts +4 -0
- package/lib/renderer/RenderingPipeline.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 +18 -18
- 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 +48 -17
- package/lib/renderer/WGPURayTracePass.js +538 -340
- package/lib/renderer/WGPURayTracePass.js.map +1 -1
- package/lib/renderer/WGPURenderingPipeline.js +83 -47
- package/lib/renderer/WGPURenderingPipeline.js.map +1 -1
- package/lib/renderer/WebGLFullQuadPass.d.ts +2 -1
- package/lib/renderer/WebGLFullQuadPass.js +4 -0
- package/lib/renderer/WebGLFullQuadPass.js.map +1 -1
- package/lib/renderer/WebGLJNLMDenoiser.js +66 -66
- package/lib/renderer/WebGLRayTraceOutputPass.js +4 -4
- package/lib/renderer/WebGLRayTracePass.d.ts +6 -1
- package/lib/renderer/WebGLRayTracePass.js +43 -6
- package/lib/renderer/WebGLRayTracePass.js.map +1 -1
- package/lib/renderer/WebGLRenderingPipeline.js +10 -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/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/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 +33 -33
- package/lib/renderer/glsl/chunks/cameraRay.glsl.js +9 -9
- 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 +426 -428
- 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 +68 -63
- package/lib/renderer/glsl/chunks/rayTraceCore.glsl.js.map +1 -1
- package/lib/renderer/glsl/chunks/sampleLight.glsl.js +94 -76
- package/lib/renderer/glsl/chunks/sampleLight.glsl.js.map +1 -1
- package/lib/renderer/glsl/chunks/sampleMaterial.glsl.d.ts +1 -0
- package/lib/renderer/glsl/chunks/sampleMaterial.glsl.js +140 -117
- 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 +89 -92
- package/lib/renderer/glsl/chunks/sampling.glsl.js.map +1 -1
- package/lib/renderer/glsl/chunks/sobol.glsl.js +79 -79
- package/lib/renderer/glsl/chunks/textureLinear.glsl.js +5 -5
- package/lib/renderer/glsl/chunks/uvProjection.glsl.js +11 -11
- package/lib/renderer/glsl/depthQuery.frag.js +2 -2
- 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 +260 -237
- package/lib/renderer/glsl/rayTrace.frag.js.map +1 -1
- package/lib/renderer/glsl/shadowCatcher.frag.js +26 -26
- package/lib/renderer/glsl/shadowCatcher.frag.js.map +1 -1
- package/lib/renderer/glsl/webglPipeline.frag.js +59 -59
- 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/progressiveScheduler.js +4 -3
- package/lib/renderer/progressiveScheduler.js.map +1 -1
- package/lib/renderer/renderPipeline.d.ts +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/sceneLayoutSchema.d.ts +1 -0
- package/lib/renderer/sceneLayoutSchema.js +2 -2
- package/lib/renderer/sceneLayoutSchema.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/webglLightSampling.d.ts +39 -0
- package/lib/renderer/webglLightSampling.js +15 -0
- package/lib/renderer/webglLightSampling.js.map +1 -0
- package/lib/renderer/wgpuBindlessSource.js +3 -3
- package/lib/renderer/wgpuShaderSource.d.ts +7 -0
- package/lib/renderer/wgpuShaderSource.js +2 -0
- package/lib/renderer/wgpuShaderSource.js.map +1 -1
- 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.js +2 -2
- package/lib/renderer/wgsl/aovSnapshot.wgsl.js +1 -1
- package/lib/renderer/wgsl/aovTrace.wgsl.js +33 -33
- 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 +537 -0
- package/lib/renderer/wgsl/causticLight.compute.js.map +1 -0
- package/lib/renderer/wgsl/chunks/background.wgsl.d.ts +2 -0
- package/lib/renderer/wgsl/chunks/background.wgsl.js +102 -0
- package/lib/renderer/wgsl/chunks/background.wgsl.js.map +1 -0
- package/lib/renderer/wgsl/chunks/causticAdjoint.wgsl.d.ts +2 -0
- package/lib/renderer/wgsl/chunks/causticAdjoint.wgsl.js +12 -0
- package/lib/renderer/wgsl/chunks/causticAdjoint.wgsl.js.map +1 -0
- package/lib/renderer/wgsl/chunks/causticAtomic.wgsl.d.ts +2 -0
- package/lib/renderer/wgsl/chunks/causticAtomic.wgsl.js +16 -0
- package/lib/renderer/wgsl/chunks/causticAtomic.wgsl.js.map +1 -0
- package/lib/renderer/wgsl/chunks/caustics.wgsl.d.ts +1 -0
- package/lib/renderer/wgsl/chunks/caustics.wgsl.js +62 -0
- package/lib/renderer/wgsl/chunks/caustics.wgsl.js.map +1 -0
- package/lib/renderer/wgsl/chunks/common.wgsl.js +4 -4
- package/lib/renderer/wgsl/chunks/envMap.wgsl.js +37 -37
- package/lib/renderer/wgsl/chunks/intersect.wgsl.js +598 -592
- package/lib/renderer/wgsl/chunks/intersect.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/chunks/intersectionAlpha.wgsl.js +14 -14
- package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.d.ts +2 -1
- package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.js +75 -73
- package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.js.map +1 -1
- package/lib/renderer/wgsl/chunks/openPbrBsdf.wgsl.js +794 -794
- 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 +2 -1
- package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.js +35 -25
- 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 +204 -187
- 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 +89 -93
- 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/uvProjection.wgsl.js +11 -11
- package/lib/renderer/wgsl/compose.frag.wgsl.js +98 -98
- package/lib/renderer/wgsl/customDenoise.wgsl.js +10 -10
- package/lib/renderer/wgsl/depthQuery.wgsl.js +2 -2
- package/lib/renderer/wgsl/jnlm.compute.js +74 -74
- package/lib/renderer/wgsl/offlineAdaptive.compute.js +25 -25
- 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 +9 -1
- package/lib/renderer/wgsl/rayTrace.compute.js +448 -522
- 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/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 +2 -2
- 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 +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rayTraceCore.wgsl.js","sourceRoot":"","sources":["../../../../src/renderer/wgsl/chunks/rayTraceCore.wgsl.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAC,6BAA6B,EAAE,yBAAyB,EAAC,MAAM,6BAA6B,CAAC;AACrG,OAAO,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC7E,OAAO,EACL,0BAA0B,EAC1B,mBAAmB,EACnB,qBAAqB,EACrB,mBAAmB,EACpB,MAAM,yBAAyB,CAAC;AAEjC,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,EACnC,uBAAuB,GAAG,IAAI,EAC9B,cAAc,GAAG,KAAK,EACtB,aAAa,GAAG,IAAI,EACpB,iBAAiB,GAAG,6BAA6B,EAMlD;IACC,OAAO,QAAQ,CAAC;;;;;;gBAMF,aAAa;yBACJ,qBAAqB;;qBAEzB,mBAAmB;uBACjB,qBAAqB;4BAChB,0BAA0B;qBACjC,mBAAmB;iCACP,CAAC,iBAAiB,GAAG,yBAAyB,CAAC,WAAW,CAAC,KAAK,CAAC;+BACnE,CAAC,iBAAiB,GAAG,yBAAyB,CAAC,SAAS,CAAC,KAAK,CAAC;+BAC/D,CAAC,iBAAiB,GAAG,yBAAyB,CAAC,SAAS,CAAC,KAAK,CAAC;sCACxD,CAAC,iBAAiB,GAAG,yBAAyB,CAAC,gBAAgB,CAAC,KAAK,CAAC;mCACzE,CAAC,iBAAiB,GAAG,yBAAyB,CAAC,QAAQ,CAAC,KAAK,CAAC;;;;;;;;;;;;;;;EAe/F,cAAc,CAAC,CAAC,CAAC,UAAU,CAAC;;CAE7B,CAAC,CAAC,CAAC,EAAE;;;;;;;;EAQJ,uBAAuB,CAAC,CAAC,CAAC,UAAU,CAAC;;;;;CAKtC,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA2Df,uBAAuB,CAAC,CAAC,CAAC,UAAU,CAAC;;;;EAIrC,uBAAuB,CAAC,CAAC,CAAC,UAAU,CAAC;;;;;CAKtC,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE;CAChB,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE;EACf,cAAc,CAAC,CAAC,CAAC,UAAU,CAAC;;;;CAI7B,CAAC,CAAC,CAAC,EAAE;;;;;;EAMF,aAAa,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAsFxC,kBAAkB,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8DAmDwC,uBAAuB,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqE9H,CAAC;AACF,CAAC","sourcesContent":["import { materialBufferWgsl } from '../../materialLayoutSchema.js';\nimport {ALL_LIGHT_SHADER_CAPABILITIES, LIGHT_SHADER_CAPABILITIES} from '../../shaderCapabilities.js';\nimport { ShadowCatcherMaterial, UnlitMaterial } from '../../../constants.js';\nimport {\n CONSTANT_DIRECTIONAL_LIGHT,\n CONSTANT_RECT_LIGHT,\n CONSTANT_SPHERE_LIGHT,\n CONSTANT_SPOT_LIGHT\n} from '../../lightConstants.js';\n\nexport default function rayTraceCore({\n hasAnisotropyDirections = true,\n hasCoatNormals = false,\n hasSceneAlpha = true,\n lightCapabilities = ALL_LIGHT_SHADER_CAPABILITIES\n}: {\n hasAnisotropyDirections?: boolean;\n hasCoatNormals?: boolean;\n hasSceneAlpha?: boolean;\n lightCapabilities?: number;\n}) {\n return /*wgsl*/ `\n// https://www.w3.org/WAI/GL/wiki/Relative_luminance\nconst luminance = vec3f(0.2126, 0.7152, 0.0722);\nconst RAY_MAX_DISTANCE = 9999.0;\n\nconst STANDARD = 0;\nconst UNLIT = ${UnlitMaterial};\nconst SHADOW_CATCHER = ${ShadowCatcherMaterial};\n\nconst RECT_LIGHT = ${CONSTANT_RECT_LIGHT};\nconst SPHERE_LIGHT = ${CONSTANT_SPHERE_LIGHT};\nconst DIRECTIONAL_LIGHT = ${CONSTANT_DIRECTIONAL_LIGHT};\nconst SPOT_LIGHT = ${CONSTANT_SPOT_LIGHT};\nconst HAS_SCENE_SPHERE_LIGHT = ${(lightCapabilities & LIGHT_SHADER_CAPABILITIES.SphereLight) !== 0};\nconst HAS_SCENE_RECT_LIGHT = ${(lightCapabilities & LIGHT_SHADER_CAPABILITIES.RectLight) !== 0};\nconst HAS_SCENE_SPOT_LIGHT = ${(lightCapabilities & LIGHT_SHADER_CAPABILITIES.SpotLight) !== 0};\nconst HAS_SCENE_DIRECTIONAL_LIGHT = ${(lightCapabilities & LIGHT_SHADER_CAPABILITIES.DirectionalLight) !== 0};\nconst HAS_SCENE_EMISSIVE_LIGHT = ${(lightCapabilities & LIGHT_SHADER_CAPABILITIES.emissive) !== 0};\n\nstruct Ray {\n o: vec3f,\n d: vec3f,\n};\n\nstruct SurfaceInteraction {\n position: vec3f,\n // For perfect specular or transmission surface\n // We use the albedo and normal of first diffuse or glossy surface hit instead for denoising\n // See albedo section in https://www.openimagedenoise.org/documentation.html\n albedoSampled: bool,\n\n normal: vec3f, // material shading normal\n${hasCoatNormals ? /* wgsl */ `\n coatNormal: vec3f, // independent, built before base normal mapping\n` : ''}\n vertexNormal: vec3f, // interpolated mesh normal before normal mapping\n shadowOffset: vec3f, // smooth-surface offset for direct-light shadow rays\n\n faceNormal: vec3f, // normal of the triangle\n hit: bool,\n\n tangent: vec3f,\n${hasAnisotropyDirections ? /* wgsl */ `\n directionTangent: vec3f,\n directionBitangent: vec3f,\n geometryTangent: vec3f,\n geometryBitangent: vec3f,\n` : /* wgsl */ ``}\n uv: vec2f,\n uv1: vec2f,\n vertexColor: vec3f,\n\n triangleIndex: i32,\n instanceIndex: i32,\n materialIndex: i32,\n barycentrics: vec2f,\n\n wavelength: f32,\n\n mediumType: i32,\n mediumExtinction: vec3f,\n mediumScattering: vec3f,\n mediumAnisotropy: f32,\n\n};\n\n// Texture-resolved OpenPBR inputs used by the surface integrator. The storage\n// buffer keeps its compact legacy layout; getMaterial() is the compatibility\n// boundary that maps it to these canonical names.\nstruct OpenPbrResolvedMaterial {\n baseColor: vec3f,\n transmissionWeight: f32,\n\n emission: vec3f,\n specularAnisotropy: f32,\n\n baseMetalness: f32,\n specularIor: f32,\n specularRoughness: f32,\n\n transmissionDispersionScale: f32,\n dispersionAbbeNumber: f32,\n thinFilmThickness: f32,\n thinFilmIor: f32,\n thinFilmWeight: f32,\n\n // Medium\n mediumType: i32,\n mediumExtinction: vec3f,\n mediumScattering: vec3f,\n mediumAnisotropy: f32,\n\n baseWeight: f32,\n diffuseRoughness: f32,\n specularWeight: f32,\n specularColor: vec3f,\n subsurfaceWeight: f32,\n subsurfaceColor: vec3f,\n transmissionColor: vec3f,\n fuzzWeight: f32,\n fuzzColor: vec3f,\n fuzzRoughness: f32,\n coatWeight: f32,\n coatColor: vec3f,\n coatRoughness: f32,\n coatAnisotropy: f32,\n${hasAnisotropyDirections ? /* wgsl */ `\n anisotropyDirection: vec2f,\n anisotropyDirectionEnabled: bool,\n coatAnisotropyRotation: f32,\n${hasAnisotropyDirections ? /* wgsl */ `\n directionTangent: vec3f,\n directionBitangent: vec3f,\n geometryTangent: vec3f,\n geometryBitangent: vec3f,\n` : /* wgsl */ ``}\n` : /* wgsl */ ``}\n${hasCoatNormals ? /* wgsl */ `\n coatNormal: vec3f,\n coatNormalEnabled: bool,\n geometricNormal: vec3f, // face normal oriented toward the view\n` : ''}\n coatIor: f32,\n coatDarkening: f32,\n\n // Alpha\n alpha: f32,\n ${hasSceneAlpha ? 'alphaMode: i32,' : ''}\n\n materialType: i32,\n\n bevel: f32,\n\n relativeIor: f32,\n inside: bool,\n\n alphaX: f32,\n alphaY: f32,\n thinWalled: bool,\n};\n\nstruct Path {\n ray: Ray,\n li: vec3f,\n alpha: f32,\n beta: vec3f,\n fromEye: bool,\n abort: bool,\n scatteringPdf: f32,\n scatteringIsDelta: bool,\n isNextRefraction: bool,\n};\n\nstruct LightSampleRec {\n normal: vec3f,\n emission: vec3f,\n direction: vec3f,\n dist: f32,\n pdf: f32,\n // Discrete probability of selecting this light before sampling its\n // conditional point/direction. Light RIS excludes this term from the target\n // and carries it in the unbiased contribution weight instead.\n selectionPmf: f32,\n isDelta: bool,\n // Light source type: environment=0, emissive triangle=1, analytic=2.\n sourceType: u32,\n sourceIndex: u32,\n};\n\nstruct Light {\n position: vec3f,\n litType: f32,\n\n emission: vec3f,\n area: f32,\n\n u: vec3f,\n // Radius for sphere light, spread for rect light\n radiusOrSpread: f32,\n\n v: vec3f,\n textureIndex: f32,\n\n selectionPmf: f32,\n _samplingPadding0: f32,\n _samplingPadding1: f32,\n _samplingPadding2: f32,\n iesReference: vec3f,\n _iesPadding: f32,\n};\n\nstruct EmissiveTriangle {\n p0: vec3f,\n selectionPmf: f32,\n p1: vec3f,\n area: f32,\n p2: vec3f,\n materialIndex: f32,\n uv0: vec2f,\n uv1: vec2f,\n uv2: vec2f,\n secondaryUv0: vec2f,\n secondaryUv1: vec2f,\n secondaryUv2: vec2f,\n};\n\nstruct LightChoice {\n probability: f32,\n aliasIndex: i32,\n sourceType: i32,\n sourceIndex: i32,\n};\n\n${materialBufferWgsl()}\n\nstruct CameraUniform {\n viewProjectionInv: mat4x4<f32>,\n viewInv: mat4x4<f32>,\n apertureRadius: f32,\n focusDistance: f32,\n};\n\nstruct RayTraceUniform {\n outputSize: vec2f,\n sampleCount: f32,\n scaleOffset: vec4f,\n lightsCount: i32,\n transmissiveOutputAlphaMin: f32,\n jitter: vec2f,\n backgroundColor: vec4f,\n groundedBackgroundParams: vec4f,\n groundedBackgroundCenter: vec2f,\n blasOffset: i32,\n isEmpty: i32,\n bevel: i32,\n dispersionWavelengths: i32,\n envLightPmf: f32,\n lightChoiceCount: i32,\n lightWeightTotal: f32,\n lightSamplingTextureWidth: i32,\n lightChoiceTexelOffset: i32,\n bounces: i32,\n varianceMoments: i32,\n adaptiveSampling: i32,\n clamping: f32,\n directLightCandidates: i32,\n backgroundFlags: i32,\n // Fixed at 4: runtime trip bounds discourage thin-film loop unrolling.\n loopUnrollGuard: u32,\n sceneFeatureFlags: u32,\n sequenceSeed: u32,\n zSobolLogSPP: u32,\n sampleSequenceOffset: u32,\n // Shadow-catcher light table, relative to lightChoiceTexelOffset.\n shadowCatcherChoiceOffset: i32,\n shadowCatcherChoiceCount: i32,\n environmentRotation: mat4x4f,\n backgroundMapTransform: vec4f,\n backgroundMapRotation: mat4x4f,\n}\n\n// Buffers\n@group(0) @binding(0) var<storage, read> bvhBuffer: array<vec4f>;\n@group(0) @binding(1) var<storage, read> instancesBuffer: array<vec4f>;\n@group(0) @binding(2) var<storage, read> attrBuffers: array<${hasAnisotropyDirections ? /* wgsl */ `vec4f` : /* wgsl */ `vec3f`}>;\n@group(0) @binding(3) var<storage, read> materialsBuffer: array<MaterialBuffer>;\n\n// Textures\n@group(1) @binding(0) var mapSampler: sampler;\n@group(1) @binding(1) var map: texture_2d_array<f32>;\n// The first NUM_MAPS entries contain atlas placement; the second half stores\n// per-texture UV scale/offset; the third block stores the UV channel in x.\n@group(1) @binding(3) var<uniform> mapInfo: array<vec4f, NUM_MAPS * 3>;\n@group(1) @binding(4) var envMap: texture_2d<f32>;\n@group(1) @binding(5) var envMapDistribution: texture_2d<f32>;\n@group(1) @binding(6) var backgroundMap: texture_2d<f32>;\n@group(1) @binding(8) var lightSamplingData: texture_2d<f32>;\n@group(1) @binding(9) var openPbrEnergyLut: texture_2d<f32>;\n@group(1) @binding(10) var adaptiveSampleTargets: texture_2d<f32>;\n\nfn iesProfileScalar(baseTexel: i32, scalarIndex: i32) -> f32 {\n let texelIndex = baseTexel + scalarIndex / 4;\n let width = rtUniform.lightSamplingTextureWidth;\n let packed = textureLoad(lightSamplingData, vec2i(texelIndex % width, texelIndex / width), 0);\n return packed[scalarIndex % 4];\n}\n\nfn sampleIESProfile(baseTexel: i32, uv: vec2f) -> f32 {\n if (baseTexel < 0) { return 1.0; }\n let pixel = fract(uv) * 128.0 - vec2f(0.5);\n let x0 = i32(floor(pixel.x));\n let y0 = i32(floor(pixel.y));\n let fx = fract(pixel.x);\n let fy = fract(pixel.y);\n let xa = select(x0, 127, x0 < 0);\n let xb = select(x0 + 1, 0, x0 >= 127);\n let ya = select(y0, 127, y0 < 0);\n let yb = select(y0 + 1, 0, y0 >= 127);\n let a = iesProfileScalar(baseTexel, ya * 128 + xa);\n let b = iesProfileScalar(baseTexel, ya * 128 + xb);\n let c = iesProfileScalar(baseTexel, yb * 128 + xa);\n let d = iesProfileScalar(baseTexel, yb * 128 + xb);\n return mix(mix(a, b, fx), mix(c, d, fx), fy);\n}\n\nfn evaluateSpotEmissionMultiplier(light: Light, lightToSurface: vec3f) -> f32 {\n let axis = normalize(light.u);\n let cosTheta = dot(axis, lightToSurface);\n var cone = select(0.0, 1.0, cosTheta >= light.v.x);\n if (light.v.y > light.v.x + 1e-6) {\n cone = smoothstep(light.v.x, light.v.y, cosTheta);\n }\n if (cone <= 0.0 || light.textureIndex < 0.0) { return cone; }\n let xAxis = light.iesReference;\n let yAxis = cross(axis, xAxis);\n let vertical = acos(clamp(cosTheta, -1.0, 1.0));\n let horizontal = atan2(dot(lightToSurface, yAxis), dot(lightToSurface, xAxis));\n return cone * sampleIESProfile(i32(light.textureIndex), vec2f(vertical / PI, horizontal / TWOPI + 0.5));\n}\n\n\n \n// Uniforms\n@group(2) @binding(0) var<uniform> cameraUniform: CameraUniform;\n@group(2) @binding(1) var<uniform> rtUniform: RayTraceUniform;\n\n@group(2) @binding(2) var<uniform> analyticLights: array<Light, NUM_UNIFORM_LIGHTS>;\n// TODO uniform must be aligned to 16 bytes.\n\nfn initRay(ray: ptr<function, Ray>, origin: vec3f, direction: vec3f) {\n (*ray).o = origin;\n (*ray).d = direction;\n}\n`;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"rayTraceCore.wgsl.js","sourceRoot":"","sources":["../../../../src/renderer/wgsl/chunks/rayTraceCore.wgsl.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAC,6BAA6B,EAAE,yBAAyB,EAAC,MAAM,6BAA6B,CAAC;AACrG,OAAO,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC7E,OAAO,EACL,0BAA0B,EAC1B,mBAAmB,EACnB,qBAAqB,EACrB,mBAAmB,EACpB,MAAM,yBAAyB,CAAC;AAEjC,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,EACnC,uBAAuB,GAAG,IAAI,EAC9B,cAAc,GAAG,KAAK,EACtB,aAAa,GAAG,IAAI,EACpB,QAAQ,GAAG,KAAK,EAChB,iBAAiB,GAAG,6BAA6B,EAOlD;IACC,OAAO,QAAQ,CAAC;;;;;;gBAMF,aAAa;yBACJ,qBAAqB;;qBAEzB,mBAAmB;uBACjB,qBAAqB;4BAChB,0BAA0B;qBACjC,mBAAmB;iCACP,CAAC,iBAAiB,GAAG,yBAAyB,CAAC,WAAW,CAAC,KAAK,CAAC;+BACnE,CAAC,iBAAiB,GAAG,yBAAyB,CAAC,SAAS,CAAC,KAAK,CAAC;+BAC/D,CAAC,iBAAiB,GAAG,yBAAyB,CAAC,SAAS,CAAC,KAAK,CAAC;sCACxD,CAAC,iBAAiB,GAAG,yBAAyB,CAAC,gBAAgB,CAAC,KAAK,CAAC;mCACzE,CAAC,iBAAiB,GAAG,yBAAyB,CAAC,QAAQ,CAAC,KAAK,CAAC;;;;;;;;;;;;;;;EAe/F,cAAc,CAAC,CAAC,CAAC,UAAU,CAAC;;CAE7B,CAAC,CAAC,CAAC,EAAE;;;;;;;;EAQJ,uBAAuB,CAAC,CAAC,CAAC,UAAU,CAAC;;;;;CAKtC,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAiCU,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC;;2BAEpB,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4BhC,uBAAuB,CAAC,CAAC,CAAC,UAAU,CAAC;;;;EAIrC,uBAAuB,CAAC,CAAC,CAAC,UAAU,CAAC;;;;;CAKtC,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE;CAChB,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE;EACf,cAAc,CAAC,CAAC,CAAC,UAAU,CAAC;;;;CAI7B,CAAC,CAAC,CAAC,EAAE;;;;;;EAMF,aAAa,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;yBAuBf,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC;;;;;;2BAMpB,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+DhC,kBAAkB,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8DAmDwC,uBAAuB,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqE9H,CAAC;AACF,CAAC","sourcesContent":["import { materialBufferWgsl } from '../../materialLayoutSchema.js';\nimport {ALL_LIGHT_SHADER_CAPABILITIES, LIGHT_SHADER_CAPABILITIES} from '../../shaderCapabilities.js';\nimport { ShadowCatcherMaterial, UnlitMaterial } from '../../../constants.js';\nimport {\n CONSTANT_DIRECTIONAL_LIGHT,\n CONSTANT_RECT_LIGHT,\n CONSTANT_SPHERE_LIGHT,\n CONSTANT_SPOT_LIGHT\n} from '../../lightConstants.js';\n\nexport default function rayTraceCore({\n hasAnisotropyDirections = true,\n hasCoatNormals = false,\n hasSceneAlpha = true,\n caustics = false,\n lightCapabilities = ALL_LIGHT_SHADER_CAPABILITIES\n}: {\n hasAnisotropyDirections?: boolean;\n hasCoatNormals?: boolean;\n hasSceneAlpha?: boolean;\n caustics?: boolean;\n lightCapabilities?: number;\n}) {\n return /*wgsl*/ `\n// https://www.w3.org/WAI/GL/wiki/Relative_luminance\nconst luminance = vec3f(0.2126, 0.7152, 0.0722);\nconst RAY_MAX_DISTANCE = 9999.0;\n\nconst STANDARD = 0;\nconst UNLIT = ${UnlitMaterial};\nconst SHADOW_CATCHER = ${ShadowCatcherMaterial};\n\nconst RECT_LIGHT = ${CONSTANT_RECT_LIGHT};\nconst SPHERE_LIGHT = ${CONSTANT_SPHERE_LIGHT};\nconst DIRECTIONAL_LIGHT = ${CONSTANT_DIRECTIONAL_LIGHT};\nconst SPOT_LIGHT = ${CONSTANT_SPOT_LIGHT};\nconst HAS_SCENE_SPHERE_LIGHT = ${(lightCapabilities & LIGHT_SHADER_CAPABILITIES.SphereLight) !== 0};\nconst HAS_SCENE_RECT_LIGHT = ${(lightCapabilities & LIGHT_SHADER_CAPABILITIES.RectLight) !== 0};\nconst HAS_SCENE_SPOT_LIGHT = ${(lightCapabilities & LIGHT_SHADER_CAPABILITIES.SpotLight) !== 0};\nconst HAS_SCENE_DIRECTIONAL_LIGHT = ${(lightCapabilities & LIGHT_SHADER_CAPABILITIES.DirectionalLight) !== 0};\nconst HAS_SCENE_EMISSIVE_LIGHT = ${(lightCapabilities & LIGHT_SHADER_CAPABILITIES.emissive) !== 0};\n\nstruct Ray {\n o: vec3f,\n d: vec3f,\n};\n\nstruct SurfaceInteraction {\n position: vec3f,\n // For perfect specular or transmission surface\n // We use the albedo and normal of first diffuse or glossy surface hit instead for denoising\n // See albedo section in https://www.openimagedenoise.org/documentation.html\n albedoSampled: bool,\n\n normal: vec3f, // material shading normal\n${hasCoatNormals ? /* wgsl */ `\n coatNormal: vec3f, // independent, built before base normal mapping\n` : ''}\n vertexNormal: vec3f, // interpolated mesh normal before normal mapping\n shadowOffset: vec3f, // smooth-surface offset for direct-light shadow rays\n\n faceNormal: vec3f, // normal of the triangle\n hit: bool,\n\n tangent: vec3f,\n${hasAnisotropyDirections ? /* wgsl */ `\n directionTangent: vec3f,\n directionBitangent: vec3f,\n geometryTangent: vec3f,\n geometryBitangent: vec3f,\n` : /* wgsl */ ``}\n uv: vec2f,\n uv1: vec2f,\n vertexColor: vec3f,\n\n triangleIndex: i32,\n instanceIndex: i32,\n materialIndex: i32,\n barycentrics: vec2f,\n\n wavelength: f32,\n // RGB channel a spectral path carries, 1 to 3. Zero keeps full RGB.\n spectralChannel: i32,\n\n mediumType: i32,\n mediumExtinction: vec3f,\n mediumScattering: vec3f,\n mediumAnisotropy: f32,\n\n};\n\n// Texture-resolved OpenPBR inputs used by the surface integrator. The storage\n// buffer keeps its compact legacy layout; getMaterial() is the compatibility\n// boundary that maps it to these canonical names.\nstruct OpenPbrResolvedMaterial {\n baseColor: vec3f,\n transmissionWeight: f32,\n\n emission: vec3f,\n specularAnisotropy: f32,\n\n baseMetalness: f32,\n specularIor: f32,\n specularRoughness: f32,${caustics ? /* wgsl */ `\n causticRoughness: f32,\n causticNormalMapped: bool,` : ''}\n\n transmissionDispersionScale: f32,\n dispersionAbbeNumber: f32,\n thinFilmThickness: f32,\n thinFilmIor: f32,\n thinFilmWeight: f32,\n\n // Medium\n mediumType: i32,\n mediumExtinction: vec3f,\n mediumScattering: vec3f,\n mediumAnisotropy: f32,\n\n baseWeight: f32,\n diffuseRoughness: f32,\n specularWeight: f32,\n specularColor: vec3f,\n subsurfaceWeight: f32,\n subsurfaceColor: vec3f,\n transmissionColor: vec3f,\n fuzzWeight: f32,\n fuzzColor: vec3f,\n fuzzRoughness: f32,\n coatWeight: f32,\n coatColor: vec3f,\n coatRoughness: f32,\n coatAnisotropy: f32,\n${hasAnisotropyDirections ? /* wgsl */ `\n anisotropyDirection: vec2f,\n anisotropyDirectionEnabled: bool,\n coatAnisotropyRotation: f32,\n${hasAnisotropyDirections ? /* wgsl */ `\n directionTangent: vec3f,\n directionBitangent: vec3f,\n geometryTangent: vec3f,\n geometryBitangent: vec3f,\n` : /* wgsl */ ``}\n` : /* wgsl */ ``}\n${hasCoatNormals ? /* wgsl */ `\n coatNormal: vec3f,\n coatNormalEnabled: bool,\n geometricNormal: vec3f, // face normal oriented toward the view\n` : ''}\n coatIor: f32,\n coatDarkening: f32,\n\n // Alpha\n alpha: f32,\n ${hasSceneAlpha ? 'alphaMode: i32,' : ''}\n\n materialType: i32,\n\n bevel: f32,\n\n relativeIor: f32,\n inside: bool,\n\n alphaX: f32,\n alphaY: f32,\n thinWalled: bool,\n};\n\nstruct Path {\n ray: Ray,\n li: vec3f,\n alpha: f32,\n beta: vec3f,\n fromEye: bool,\n abort: bool,\n scatteringPdf: f32,\n scatteringIsDelta: bool,\n isNextRefraction: bool,${caustics ? /* wgsl */ `\n causticK: u32,\n causticSingleT: bool,\n causticReceiverPrimary: bool,\n causticHasReceiver: bool,\n causticPhotonReceiver:bool,\n causticMneeReceiver: bool,` : ''}\n};\n\nstruct LightSampleRec {\n normal: vec3f,\n emission: vec3f,\n direction: vec3f,\n dist: f32,\n pdf: f32,\n // Discrete probability of selecting this light before sampling its\n // conditional point/direction. Light RIS excludes this term from the target\n // and carries it in the unbiased contribution weight instead.\n selectionPmf: f32,\n isDelta: bool,\n // Light source type: environment=0, emissive triangle=1, analytic=2.\n sourceType: u32,\n sourceIndex: u32,\n};\n\nstruct Light {\n position: vec3f,\n litType: f32,\n\n emission: vec3f,\n area: f32,\n\n u: vec3f,\n // Radius for sphere light, spread for rect light\n radiusOrSpread: f32,\n\n v: vec3f,\n textureIndex: f32,\n\n selectionPmf: f32,\n _samplingPadding0: f32,\n _samplingPadding1: f32,\n _samplingPadding2: f32,\n iesReference: vec3f,\n _iesPadding: f32,\n};\n\nstruct EmissiveTriangle {\n p0: vec3f,\n selectionPmf: f32,\n p1: vec3f,\n area: f32,\n p2: vec3f,\n materialIndex: f32,\n uv0: vec2f,\n uv1: vec2f,\n uv2: vec2f,\n secondaryUv0: vec2f,\n secondaryUv1: vec2f,\n secondaryUv2: vec2f,\n};\n\nstruct LightChoice {\n probability: f32,\n aliasIndex: i32,\n sourceType: i32,\n sourceIndex: i32,\n};\n\n${materialBufferWgsl()}\n\nstruct CameraUniform {\n viewProjectionInv: mat4x4<f32>,\n viewInv: mat4x4<f32>,\n apertureRadius: f32,\n focusDistance: f32,\n};\n\nstruct RayTraceUniform {\n outputSize: vec2f,\n sampleCount: f32,\n scaleOffset: vec4f,\n lightsCount: i32,\n transmissiveOutputAlphaMin: f32,\n jitter: vec2f,\n backgroundColor: vec4f,\n groundedBackgroundParams: vec4f,\n groundedBackgroundCenter: vec2f,\n blasOffset: i32,\n isEmpty: i32,\n bevel: i32,\n dispersionWavelengths: i32,\n envLightPmf: f32,\n lightChoiceCount: i32,\n lightWeightTotal: f32,\n lightSamplingTextureWidth: i32,\n lightChoiceTexelOffset: i32,\n bounces: i32,\n varianceMoments: i32,\n adaptiveSampling: i32,\n clamping: f32,\n directLightCandidates: i32,\n backgroundFlags: i32,\n // Fixed at 4: runtime trip bounds discourage thin-film loop unrolling.\n loopUnrollGuard: u32,\n sceneFeatureFlags: u32,\n sequenceSeed: u32,\n zSobolLogSPP: u32,\n sampleSequenceOffset: u32,\n // Shadow-catcher light table, relative to lightChoiceTexelOffset.\n shadowCatcherChoiceOffset: i32,\n shadowCatcherChoiceCount: i32,\n environmentRotation: mat4x4f,\n backgroundMapTransform: vec4f,\n backgroundMapRotation: mat4x4f,\n}\n\n// Buffers\n@group(0) @binding(0) var<storage, read> bvhBuffer: array<vec4f>;\n@group(0) @binding(1) var<storage, read> instancesBuffer: array<vec4f>;\n@group(0) @binding(2) var<storage, read> attrBuffers: array<${hasAnisotropyDirections ? /* wgsl */ `vec4f` : /* wgsl */ `vec3f`}>;\n@group(0) @binding(3) var<storage, read> materialsBuffer: array<MaterialBuffer>;\n\n// Textures\n@group(1) @binding(0) var mapSampler: sampler;\n@group(1) @binding(1) var map: texture_2d_array<f32>;\n// The first NUM_MAPS entries contain atlas placement; the second half stores\n// per-texture UV scale/offset; the third block stores the UV channel in x.\n@group(1) @binding(3) var<uniform> mapInfo: array<vec4f, NUM_MAPS * 3>;\n@group(1) @binding(4) var envMap: texture_2d<f32>;\n@group(1) @binding(5) var envMapDistribution: texture_2d<f32>;\n@group(1) @binding(6) var backgroundMap: texture_2d<f32>;\n@group(1) @binding(8) var lightSamplingData: texture_2d<f32>;\n@group(1) @binding(9) var openPbrEnergyLut: texture_2d<f32>;\n@group(1) @binding(10) var adaptiveSampleTargets: texture_2d<f32>;\n\nfn iesProfileScalar(baseTexel: i32, scalarIndex: i32) -> f32 {\n let texelIndex = baseTexel + scalarIndex / 4;\n let width = rtUniform.lightSamplingTextureWidth;\n let packed = textureLoad(lightSamplingData, vec2i(texelIndex % width, texelIndex / width), 0);\n return packed[scalarIndex % 4];\n}\n\nfn sampleIESProfile(baseTexel: i32, uv: vec2f) -> f32 {\n if (baseTexel < 0) { return 1.0; }\n let pixel = fract(uv) * 128.0 - vec2f(0.5);\n let x0 = i32(floor(pixel.x));\n let y0 = i32(floor(pixel.y));\n let fx = fract(pixel.x);\n let fy = fract(pixel.y);\n let xa = select(x0, 127, x0 < 0);\n let xb = select(x0 + 1, 0, x0 >= 127);\n let ya = select(y0, 127, y0 < 0);\n let yb = select(y0 + 1, 0, y0 >= 127);\n let a = iesProfileScalar(baseTexel, ya * 128 + xa);\n let b = iesProfileScalar(baseTexel, ya * 128 + xb);\n let c = iesProfileScalar(baseTexel, yb * 128 + xa);\n let d = iesProfileScalar(baseTexel, yb * 128 + xb);\n return mix(mix(a, b, fx), mix(c, d, fx), fy);\n}\n\nfn evaluateSpotEmissionMultiplier(light: Light, lightToSurface: vec3f) -> f32 {\n let axis = normalize(light.u);\n let cosTheta = dot(axis, lightToSurface);\n var cone = select(0.0, 1.0, cosTheta >= light.v.x);\n if (light.v.y > light.v.x + 1e-6) {\n cone = smoothstep(light.v.x, light.v.y, cosTheta);\n }\n if (cone <= 0.0 || light.textureIndex < 0.0) { return cone; }\n let xAxis = light.iesReference;\n let yAxis = cross(axis, xAxis);\n let vertical = acos(clamp(cosTheta, -1.0, 1.0));\n let horizontal = atan2(dot(lightToSurface, yAxis), dot(lightToSurface, xAxis));\n return cone * sampleIESProfile(i32(light.textureIndex), vec2f(vertical / PI, horizontal / TWOPI + 0.5));\n}\n\n\n \n// Uniforms\n@group(2) @binding(0) var<uniform> cameraUniform: CameraUniform;\n@group(2) @binding(1) var<uniform> rtUniform: RayTraceUniform;\n\n@group(2) @binding(2) var<uniform> analyticLights: array<Light, NUM_UNIFORM_LIGHTS>;\n// TODO uniform must be aligned to 16 bytes.\n\nfn initRay(ray: ptr<function, Ray>, origin: vec3f, direction: vec3f) {\n (*ray).o = origin;\n (*ray).d = direction;\n}\n`;\n}\n"]}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: "\nfn light_sample_sphere(light: Light, scatterPos: vec3f, randomV2: vec2f, lightSample: ptr<function, LightSampleRec>) {\n let centerOffset = light.position - scatterPos;\n let centerDistance = length(centerOffset);\n if (light.radiusOrSpread <= 0.0) {\n // A zero-radius sphere is a point emitter. The stored emission is\n // luminous intensity, so convert it to incident radiance here rather\n // than approximating the delta source as a tiny area sphere.\n if (centerDistance <= 1e-6) {\n (*lightSample).direction = vec3f(0.0, 0.0, 1.0);\n (*lightSample).normal = vec3f(0.0, 0.0, -1.0);\n (*lightSample).dist = 0.0;\n (*lightSample).pdf = 1.0;\n (*lightSample).emission = vec3f(0.0);\n (*lightSample).isDelta = true;\n return;\n }\n (*lightSample).direction = centerOffset / centerDistance;\n (*lightSample).normal = -(*lightSample).direction;\n (*lightSample).dist = centerDistance;\n (*lightSample).pdf = 1.0;\n (*lightSample).emission = light.emission /\n max(centerDistance * centerDistance, 1e-8);\n (*lightSample).isDelta = true;\n return;\n }\n let radius = max(light.radiusOrSpread, 1e-6);\n (*lightSample).isDelta = false;\n var sampledDirection: vec3f;\n\n if (centerDistance <= radius) {\n let z = 1.0 - 2.0 * randomV2.x;\n let radial = sqrt(max(0.0, 1.0 - z * z));\n let azimuth = TWOPI * randomV2.y;\n sampledDirection = vec3f(\n radial * cos(azimuth),\n radial * sin(azimuth),\n z\n );\n (*lightSample).pdf = INV4PI;\n }\n else {\n let sphereAxis = centerOffset / centerDistance;\n let sinThetaMaxSquared = min(\n 1.0,\n radius * radius / (centerDistance * centerDistance)\n );\n let cosThetaMax = sqrt(max(0.0, 1.0 - sinThetaMaxSquared));\n let cosTheta = mix(1.0, cosThetaMax, randomV2.x);\n let sinTheta = sqrt(max(0.0, 1.0 - cosTheta * cosTheta));\n let azimuth = TWOPI * randomV2.y;\n var tangent: vec3f;\n var bitangent: vec3f;\n sampling_orthonormal_basis(sphereAxis, &tangent, &bitangent);\n sampledDirection = sphereAxis * cosTheta\n + tangent * (sinTheta * cos(azimuth))\n + bitangent * (sinTheta * sin(azimuth));\n (*lightSample).pdf = 1.0 / max(\n TWOPI * (1.0 - cosThetaMax),\n 1e-8\n );\n }\n\n let centerProjection = dot(sampledDirection, centerOffset);\n let centerOffsetSquared = dot(centerOffset, centerOffset);\n let discriminant = centerProjection * centerProjection\n - centerOffsetSquared + radius * radius;\n let nearDistance = centerProjection - sqrt(max(0.0, discriminant));\n let farDistance = centerProjection + sqrt(max(0.0, discriminant));\n (*lightSample).dist = select(farDistance, nearDistance, nearDistance > 1e-6);\n (*lightSample).direction = sampledDirection;\n let lightSurfacePos = scatterPos + sampledDirection * (*lightSample).dist;\n (*lightSample).normal = normalize(lightSurfacePos - light.position);\n (*lightSample).emission = light.emission;\n}\n\nfn light_apply_rect_texture(\n light: Light,\n surfacePoint: vec3f,\n lowerLeft: vec3f,\n result: ptr<function, LightSampleRec>\n) {\n if (light.textureIndex < 0.0) {\n return;\n }\n let width = length(light.u);\n let height = length(light.v);\n let relative = surfacePoint - lowerLeft;\n let uv = vec2f(\n dot(relative, light.u / width) / width,\n dot(relative, light.v / height) / height\n );\n (*result).emission *= sampleMap(i32(light.textureIndex), uv).rgb;\n}\n\nfn light_sample_rect(\n light: Light,\n shadingPoint: vec3f,\n samplePoint: vec2f,\n result: ptr<function, LightSampleRec>\n) {\n let normal = normalize(cross(light.u, light.v));\n let lowerLeft = light.position - 0.5 * (light.u + light.v);\n let spread = clamp(light.radiusOrSpread, 0.0, 1.0);\n\n if (spread <= 0.001) {\n let planeDistance = dot(normal, shadingPoint - light.position);\n let surfacePoint = shadingPoint - normal * planeDistance;\n let relative = surfacePoint - lowerLeft;\n let width = length(light.u);\n let height = length(light.v);\n let uv = vec2f(\n dot(relative, light.u / width) / width,\n dot(relative, light.v / height) / height\n );\n if (planeDistance <= 0.0 || any(uv < vec2f(0.0)) || any(uv > vec2f(1.0))) {\n (*result).emission = vec3f(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 let surfacePoint = lowerLeft\n + light.u * samplePoint.x\n + light.v * samplePoint.y;\n let offset = surfacePoint - shadingPoint;\n let distanceSquared = dot(offset, offset);\n (*result).dist = sqrt(distanceSquared);\n (*result).direction = offset / (*result).dist;\n (*result).normal = normal;\n let emitterCosine = dot(-(*result).direction, normal);\n let spreadCosine = cos(0.5 * PI * spread);\n if (emitterCosine <= 0.0 || emitterCosine < spreadCosine) {\n (*result).emission = vec3f(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\nfn light_sample_directional(\n light: Light,\n result: ptr<function, LightSampleRec>\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\nfn light_sample_spot(\n light: Light,\n shadingPoint: vec3f,\n samplePoint: vec2f,\n result: ptr<function, LightSampleRec>\n) {\n light_sample_sphere(light, shadingPoint, samplePoint, result);\n let surfacePoint = shadingPoint + (*result).direction * (*result).dist;\n let lightToSurface = normalize(shadingPoint - surfacePoint);\n (*result).emission *= evaluateSpotEmissionMultiplier(light, lightToSurface);\n}\n\nfn sampleAnalyticLight(\n light: Light,\n shadingPoint: vec3f,\n samplePoint: vec2f,\n result: ptr<function, LightSampleRec>\n) {\n let lightType = i32(light.litType);\n if (HAS_SCENE_RECT_LIGHT && lightType == RECT_LIGHT) {\n light_sample_rect(light, shadingPoint, samplePoint, result);\n return;\n }\n if (HAS_SCENE_SPHERE_LIGHT && lightType == SPHERE_LIGHT) {\n light_sample_sphere(light, shadingPoint, samplePoint, result);\n return;\n }\n if (HAS_SCENE_SPOT_LIGHT && lightType == SPOT_LIGHT) {\n light_sample_spot(light, shadingPoint, samplePoint, result);\n return;\n }\n if (HAS_SCENE_DIRECTIONAL_LIGHT && lightType == DIRECTIONAL_LIGHT) {\n light_sample_directional(light, result);\n }\n}\n\nfn sampleEnvLight(randomV2: vec2f, lightSample: ptr<function, LightSampleRec>) {\n var uv: vec2f;\n // Naga's SPIR-V writer cannot pass a struct-member pointer as a call argument.\n var pdf: f32;\n let direction = sampleEnvmap(randomV2, &uv, &pdf);\n (*lightSample).pdf = pdf;\n (*lightSample).direction = direction;\n (*lightSample).emission = textureLinear(envMap, uv).rgb;\n (*lightSample).dist = INF;\n}\n\nfn loadLightSamplingTexel(texelIndex: i32) -> vec4f {\n let width = rtUniform.lightSamplingTextureWidth;\n return textureLoad(\n lightSamplingData,\n vec2i(texelIndex % width, texelIndex / width),\n 0\n );\n}\n\nfn getEmissiveTriangle(index: i32) -> EmissiveTriangle {\n let offset = index * 6;\n let a = loadLightSamplingTexel(offset);\n let b = loadLightSamplingTexel(offset + 1);\n let c = loadLightSamplingTexel(offset + 2);\n let d = loadLightSamplingTexel(offset + 3);\n let e = loadLightSamplingTexel(offset + 4);\n let f = loadLightSamplingTexel(offset + 5);\n return EmissiveTriangle(\n a.xyz, a.w,\n b.xyz, b.w,\n c.xyz, c.w,\n d.xy, d.zw, e.xy,\n e.zw, f.xy, f.zw\n );\n}\n\nfn getLightChoice(index: i32) -> LightChoice {\n let data = loadLightSamplingTexel(rtUniform.lightChoiceTexelOffset + index);\n return LightChoice(\n data.x,\n bitcast<i32>(data.y),\n bitcast<i32>(data.z),\n bitcast<i32>(data.w)\n );\n}\n\nfn getLightChoiceFromTable(tableOffset: i32, index: i32) -> LightChoice {\n return getLightChoice(tableOffset + index);\n}\n\nfn stratifyLightChoiceRandom(\n rnd: vec3f,\n candidateIndex: u32,\n candidateCount: u32\n) -> vec3f {\n var stratified = rnd;\n let count = max(candidateCount, 1u);\n stratified.z = (rnd.z + f32(min(candidateIndex, count - 1u))) /\n f32(count);\n return stratified;\n}\n\nfn sampleEmissiveTriangleLight(\n triangle: EmissiveTriangle,\n scatterPos: vec3f,\n randomV2: vec2f,\n lightSample: ptr<function, LightSampleRec>\n) {\n let sqrtU = sqrt(randomV2.x);\n let barycentric = vec3f(\n 1.0 - sqrtU,\n sqrtU * (1.0 - randomV2.y),\n sqrtU * randomV2.y\n );\n let lightPosition =\n barycentric.x * triangle.p0 +\n barycentric.y * triangle.p1 +\n barycentric.z * triangle.p2;\n let uv =\n barycentric.x * triangle.uv0 +\n barycentric.y * triangle.uv1 +\n barycentric.z * triangle.uv2;\n let secondaryUv =\n barycentric.x * triangle.secondaryUv0 +\n barycentric.y * triangle.secondaryUv1 +\n barycentric.z * triangle.secondaryUv2;\n let normal = normalize(cross(triangle.p1 - triangle.p0, triangle.p2 - triangle.p0));\n (*lightSample).direction = lightPosition - scatterPos;\n (*lightSample).dist = length((*lightSample).direction);\n if ((*lightSample).dist <= EPS) {\n (*lightSample).emission = vec3f(0.0);\n (*lightSample).pdf = 0.0;\n return;\n }\n (*lightSample).direction /= (*lightSample).dist;\n (*lightSample).normal = normal;\n let cosLight = dot(normal, -(*lightSample).direction);\n if (cosLight <= 0.0) {\n (*lightSample).emission = vec3f(0.0);\n (*lightSample).pdf = 0.0;\n return;\n }\n (*lightSample).emission = getMaterialEmission(\n i32(triangle.materialIndex), uv, secondaryUv\n );\n (*lightSample).selectionPmf = triangle.selectionPmf;\n (*lightSample).pdf = triangle.selectionPmf *\n ((*lightSample).dist * (*lightSample).dist) /\n max(triangle.area * cosLight, 1e-8);\n}\n\nfn sampleLightChoiceTable(\n scatterPos: vec3f,\n rnd: vec3f,\n tableOffset: i32,\n choiceCount: i32,\n selectionPmfScale: f32,\n lightSample: ptr<function, LightSampleRec>\n) {\n (*lightSample).emission = vec3f(0.0);\n (*lightSample).pdf = 0.0;\n (*lightSample).selectionPmf = 0.0;\n (*lightSample).dist = INF;\n (*lightSample).isDelta = false;\n (*lightSample).sourceType = 0u;\n (*lightSample).sourceIndex = 0xffffffffu;\n if (choiceCount <= 0) {\n return;\n }\n\n let scaledChoice = rnd.z * f32(choiceCount);\n let column = min(i32(scaledChoice), choiceCount - 1);\n let columnChoice = getLightChoiceFromTable(tableOffset, column);\n let selectedIndex = select(\n columnChoice.aliasIndex,\n column,\n fract(scaledChoice) < columnChoice.probability\n );\n let choice = getLightChoiceFromTable(tableOffset, selectedIndex);\n if (USE_ENVMAP && choice.sourceType == 1) {\n (*lightSample).sourceType = 0u;\n (*lightSample).sourceIndex = u32(choice.sourceIndex);\n sampleEnvLight(rnd.xy, lightSample);\n (*lightSample).selectionPmf = rtUniform.envLightPmf;\n (*lightSample).pdf *= rtUniform.envLightPmf;\n }\n else if (choice.sourceType == 2) {\n (*lightSample).sourceType = 2u;\n (*lightSample).sourceIndex = u32(choice.sourceIndex);\n let light = analyticLights[choice.sourceIndex];\n sampleAnalyticLight(light, scatterPos, rnd.xy, lightSample);\n (*lightSample).selectionPmf = light.selectionPmf;\n (*lightSample).pdf *= light.selectionPmf;\n }\n else if (HAS_SCENE_EMISSIVE_LIGHT && choice.sourceType == 3) {\n (*lightSample).sourceType = 1u;\n (*lightSample).sourceIndex = u32(choice.sourceIndex);\n sampleEmissiveTriangleLight(\n getEmissiveTriangle(choice.sourceIndex),\n scatterPos,\n rnd.xy,\n lightSample\n );\n }\n (*lightSample).selectionPmf *= selectionPmfScale;\n (*lightSample).pdf *= selectionPmfScale;\n}\n\nfn sampleLight(\n scatterPos: vec3f,\n rnd: vec3f,\n lightSample: ptr<function, LightSampleRec>,\n distByIntensity: bool\n) {\n sampleLightChoiceTable(\n scatterPos,\n rnd,\n 0,\n rtUniform.lightChoiceCount,\n 1.0,\n lightSample\n );\n}\n\n// Light choice for one of the resampled NEE candidates. The selection random\n// number is stratified across the candidates.\nfn sampleLightForNEECandidate(\n scatterPos: vec3f,\n rnd: vec3f,\n candidateIndex: u32,\n candidateCount: u32,\n lightSample: ptr<function, LightSampleRec>\n) {\n sampleLightChoiceTable(\n scatterPos,\n stratifyLightChoiceRandom(rnd, candidateIndex, candidateCount),\n 0,\n rtUniform.lightChoiceCount,\n 1.0,\n lightSample\n );\n}\n";
|
|
1
|
+
declare const _default: "\nfn light_sample_sphere(light: Light, scatterPos: vec3f, randomV2: vec2f, lightSample: ptr<function, LightSampleRec>) {\n let centerOffset = light.position - scatterPos;\n let centerDistance = length(centerOffset);\n if (light.radiusOrSpread <= 0.0) {\n // A zero-radius sphere is a point emitter. The stored emission is\n // luminous intensity, so convert it to incident radiance here rather\n // than approximating the delta source as a tiny area sphere.\n if (centerDistance <= 1e-6) {\n (*lightSample).direction = vec3f(0.0, 0.0, 1.0);\n (*lightSample).normal = vec3f(0.0, 0.0, -1.0);\n (*lightSample).dist = 0.0;\n (*lightSample).pdf = 1.0;\n (*lightSample).emission = vec3f(0.0);\n (*lightSample).isDelta = true;\n return;\n }\n (*lightSample).direction = centerOffset / centerDistance;\n (*lightSample).normal = -(*lightSample).direction;\n (*lightSample).dist = centerDistance;\n (*lightSample).pdf = 1.0;\n (*lightSample).emission = light.emission /\n max(centerDistance * centerDistance, 1e-8);\n (*lightSample).isDelta = true;\n return;\n }\n let radius = max(light.radiusOrSpread, 1e-6);\n (*lightSample).isDelta = false;\n var sampledDirection: vec3f;\n\n if (centerDistance <= radius) {\n let z = 1.0 - 2.0 * randomV2.x;\n let radial = sqrt(max(0.0, 1.0 - z * z));\n let azimuth = TWOPI * randomV2.y;\n sampledDirection = vec3f(\n radial * cos(azimuth),\n radial * sin(azimuth),\n z\n );\n (*lightSample).pdf = INV4PI;\n }\n else {\n let sphereAxis = centerOffset / centerDistance;\n let sinThetaMaxSquared = min(\n 1.0,\n radius * radius / (centerDistance * centerDistance)\n );\n let cosThetaMax = sqrt(max(0.0, 1.0 - sinThetaMaxSquared));\n // Rationalize 1 - cos(thetaMax): subtracting nearly equal f32 values\n // quantizes small emitters' solid angles into visible irradiance bands.\n let oneMinusCosThetaMax = sinThetaMaxSquared / (1.0 + cosThetaMax);\n let oneMinusCosTheta = randomV2.x * oneMinusCosThetaMax;\n let cosTheta = 1.0 - oneMinusCosTheta;\n let sinTheta = sqrt(max(0.0, oneMinusCosTheta * (2.0 - oneMinusCosTheta)));\n let azimuth = TWOPI * randomV2.y;\n var tangent: vec3f;\n var bitangent: vec3f;\n sampling_orthonormal_basis(sphereAxis, &tangent, &bitangent);\n sampledDirection = sphereAxis * cosTheta\n + tangent * (sinTheta * cos(azimuth))\n + bitangent * (sinTheta * sin(azimuth));\n (*lightSample).pdf = 1.0 / max(\n TWOPI * oneMinusCosThetaMax,\n 1e-8\n );\n }\n\n let centerProjection = dot(sampledDirection, centerOffset);\n let centerOffsetSquared = dot(centerOffset, centerOffset);\n let discriminant = centerProjection * centerProjection\n - centerOffsetSquared + radius * radius;\n let nearDistance = centerProjection - sqrt(max(0.0, discriminant));\n let farDistance = centerProjection + sqrt(max(0.0, discriminant));\n (*lightSample).dist = select(farDistance, nearDistance, nearDistance > 1e-6);\n (*lightSample).direction = sampledDirection;\n let lightSurfacePos = scatterPos + sampledDirection * (*lightSample).dist;\n (*lightSample).normal = normalize(lightSurfacePos - light.position);\n (*lightSample).emission = light.emission;\n}\n\nfn light_apply_rect_texture(\n light: Light,\n surfacePoint: vec3f,\n lowerLeft: vec3f,\n result: ptr<function, LightSampleRec>\n) {\n if (light.textureIndex < 0.0) {\n return;\n }\n let width = length(light.u);\n let height = length(light.v);\n let relative = surfacePoint - lowerLeft;\n let uv = vec2f(\n dot(relative, light.u / width) / width,\n dot(relative, light.v / height) / height\n );\n (*result).emission *= sampleMap(i32(light.textureIndex), uv).rgb;\n}\n\nfn light_sample_rect(\n light: Light,\n shadingPoint: vec3f,\n samplePoint: vec2f,\n result: ptr<function, LightSampleRec>\n) {\n let normal = normalize(cross(light.u, light.v));\n let lowerLeft = light.position - 0.5 * (light.u + light.v);\n let spread = clamp(light.radiusOrSpread, 0.0, 1.0);\n\n if (spread <= 0.001) {\n let planeDistance = dot(normal, shadingPoint - light.position);\n let surfacePoint = shadingPoint - normal * planeDistance;\n let relative = surfacePoint - lowerLeft;\n let width = length(light.u);\n let height = length(light.v);\n let uv = vec2f(\n dot(relative, light.u / width) / width,\n dot(relative, light.v / height) / height\n );\n if (planeDistance <= 0.0 || any(uv < vec2f(0.0)) || any(uv > vec2f(1.0))) {\n (*result).emission = vec3f(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 let surfacePoint = lowerLeft\n + light.u * samplePoint.x\n + light.v * samplePoint.y;\n let offset = surfacePoint - shadingPoint;\n let distanceSquared = dot(offset, offset);\n (*result).dist = sqrt(distanceSquared);\n (*result).direction = offset / (*result).dist;\n (*result).normal = normal;\n let emitterCosine = dot(-(*result).direction, normal);\n let spreadCosine = cos(0.5 * PI * spread);\n if (emitterCosine <= 0.0 || emitterCosine < spreadCosine) {\n (*result).emission = vec3f(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\nfn light_sample_directional(\n light: Light,\n result: ptr<function, LightSampleRec>\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\nfn light_sample_spot(\n light: Light,\n shadingPoint: vec3f,\n samplePoint: vec2f,\n result: ptr<function, LightSampleRec>\n) {\n light_sample_sphere(light, shadingPoint, samplePoint, result);\n let surfacePoint = shadingPoint + (*result).direction * (*result).dist;\n let lightToSurface = normalize(shadingPoint - surfacePoint);\n (*result).emission *= evaluateSpotEmissionMultiplier(light, lightToSurface);\n}\n\nfn sampleAnalyticLight(\n light: Light,\n shadingPoint: vec3f,\n samplePoint: vec2f,\n result: ptr<function, LightSampleRec>\n) {\n let lightType = i32(light.litType);\n if (HAS_SCENE_RECT_LIGHT && lightType == RECT_LIGHT) {\n light_sample_rect(light, shadingPoint, samplePoint, result);\n return;\n }\n if (HAS_SCENE_SPHERE_LIGHT && lightType == SPHERE_LIGHT) {\n light_sample_sphere(light, shadingPoint, samplePoint, result);\n return;\n }\n if (HAS_SCENE_SPOT_LIGHT && lightType == SPOT_LIGHT) {\n light_sample_spot(light, shadingPoint, samplePoint, result);\n return;\n }\n if (HAS_SCENE_DIRECTIONAL_LIGHT && lightType == DIRECTIONAL_LIGHT) {\n light_sample_directional(light, result);\n }\n}\n\nfn sampleEnvLight(randomV2: vec2f, lightSample: ptr<function, LightSampleRec>) {\n var uv: vec2f;\n // Naga's SPIR-V writer cannot pass a struct-member pointer as a call argument.\n var pdf: f32;\n let direction = sampleEnvmap(randomV2, &uv, &pdf);\n (*lightSample).pdf = pdf;\n (*lightSample).direction = direction;\n (*lightSample).emission = textureLinear(envMap, uv).rgb;\n (*lightSample).dist = INF;\n}\n\nfn loadLightSamplingTexel(texelIndex: i32) -> vec4f {\n let width = rtUniform.lightSamplingTextureWidth;\n return textureLoad(\n lightSamplingData,\n vec2i(texelIndex % width, texelIndex / width),\n 0\n );\n}\n\nfn getEmissiveTriangle(index: i32) -> EmissiveTriangle {\n let offset = index * 6;\n let a = loadLightSamplingTexel(offset);\n let b = loadLightSamplingTexel(offset + 1);\n let c = loadLightSamplingTexel(offset + 2);\n let d = loadLightSamplingTexel(offset + 3);\n let e = loadLightSamplingTexel(offset + 4);\n let f = loadLightSamplingTexel(offset + 5);\n return EmissiveTriangle(\n a.xyz, a.w,\n b.xyz, b.w,\n c.xyz, c.w,\n d.xy, d.zw, e.xy,\n e.zw, f.xy, f.zw\n );\n}\n\nfn getLightChoice(index: i32) -> LightChoice {\n let data = loadLightSamplingTexel(rtUniform.lightChoiceTexelOffset + index);\n return LightChoice(\n data.x,\n bitcast<i32>(data.y),\n bitcast<i32>(data.z),\n bitcast<i32>(data.w)\n );\n}\n\nfn getLightChoiceFromTable(tableOffset: i32, index: i32) -> LightChoice {\n return getLightChoice(tableOffset + index);\n}\n\nfn stratifyLightChoiceRandom(\n rnd: vec3f,\n candidateIndex: u32,\n candidateCount: u32\n) -> vec3f {\n var stratified = rnd;\n let count = max(candidateCount, 1u);\n stratified.z = (rnd.z + f32(min(candidateIndex, count - 1u))) /\n f32(count);\n return stratified;\n}\n\nfn sampleEmissiveTriangleLight(\n triangle: EmissiveTriangle,\n scatterPos: vec3f,\n randomV2: vec2f,\n lightSample: ptr<function, LightSampleRec>\n) {\n let sqrtU = sqrt(randomV2.x);\n let barycentric = vec3f(\n 1.0 - sqrtU,\n sqrtU * (1.0 - randomV2.y),\n sqrtU * randomV2.y\n );\n let lightPosition =\n barycentric.x * triangle.p0 +\n barycentric.y * triangle.p1 +\n barycentric.z * triangle.p2;\n let uv =\n barycentric.x * triangle.uv0 +\n barycentric.y * triangle.uv1 +\n barycentric.z * triangle.uv2;\n let secondaryUv =\n barycentric.x * triangle.secondaryUv0 +\n barycentric.y * triangle.secondaryUv1 +\n barycentric.z * triangle.secondaryUv2;\n let normal = normalize(cross(triangle.p1 - triangle.p0, triangle.p2 - triangle.p0));\n (*lightSample).direction = lightPosition - scatterPos;\n (*lightSample).dist = length((*lightSample).direction);\n if ((*lightSample).dist <= EPS) {\n (*lightSample).emission = vec3f(0.0);\n (*lightSample).pdf = 0.0;\n return;\n }\n (*lightSample).direction /= (*lightSample).dist;\n (*lightSample).normal = normal;\n let cosLight = dot(normal, -(*lightSample).direction);\n if (cosLight <= 0.0) {\n (*lightSample).emission = vec3f(0.0);\n (*lightSample).pdf = 0.0;\n return;\n }\n (*lightSample).emission = getMaterialEmission(\n i32(triangle.materialIndex), uv, secondaryUv\n );\n (*lightSample).selectionPmf = triangle.selectionPmf;\n (*lightSample).pdf = triangle.selectionPmf *\n ((*lightSample).dist * (*lightSample).dist) /\n max(triangle.area * cosLight, 1e-8);\n}\n\nfn sampleLightChoiceTable(\n scatterPos: vec3f,\n rnd: vec3f,\n tableOffset: i32,\n choiceCount: i32,\n selectionPmfScale: f32,\n lightSample: ptr<function, LightSampleRec>\n) {\n (*lightSample).emission = vec3f(0.0);\n (*lightSample).pdf = 0.0;\n (*lightSample).selectionPmf = 0.0;\n (*lightSample).dist = INF;\n (*lightSample).isDelta = false;\n (*lightSample).sourceType = 0u;\n (*lightSample).sourceIndex = 0xffffffffu;\n if (choiceCount <= 0) {\n return;\n }\n\n let scaledChoice = rnd.z * f32(choiceCount);\n let column = min(i32(scaledChoice), choiceCount - 1);\n let columnChoice = getLightChoiceFromTable(tableOffset, column);\n let selectedIndex = select(\n columnChoice.aliasIndex,\n column,\n fract(scaledChoice) < columnChoice.probability\n );\n let choice = getLightChoiceFromTable(tableOffset, selectedIndex);\n if (USE_ENVMAP && choice.sourceType == 1) {\n (*lightSample).sourceType = 0u;\n (*lightSample).sourceIndex = u32(choice.sourceIndex);\n sampleEnvLight(rnd.xy, lightSample);\n (*lightSample).selectionPmf = rtUniform.envLightPmf;\n (*lightSample).pdf *= rtUniform.envLightPmf;\n }\n else if (choice.sourceType == 2) {\n (*lightSample).sourceType = 2u;\n (*lightSample).sourceIndex = u32(choice.sourceIndex);\n let light = analyticLights[choice.sourceIndex];\n sampleAnalyticLight(light, scatterPos, rnd.xy, lightSample);\n (*lightSample).selectionPmf = light.selectionPmf;\n (*lightSample).pdf *= light.selectionPmf;\n }\n else if (HAS_SCENE_EMISSIVE_LIGHT && choice.sourceType == 3) {\n (*lightSample).sourceType = 1u;\n (*lightSample).sourceIndex = u32(choice.sourceIndex);\n sampleEmissiveTriangleLight(\n getEmissiveTriangle(choice.sourceIndex),\n scatterPos,\n rnd.xy,\n lightSample\n );\n }\n (*lightSample).selectionPmf *= selectionPmfScale;\n (*lightSample).pdf *= selectionPmfScale;\n}\n\nfn sampleLight(\n scatterPos: vec3f,\n rnd: vec3f,\n lightSample: ptr<function, LightSampleRec>,\n distByIntensity: bool\n) {\n sampleLightChoiceTable(\n scatterPos,\n rnd,\n 0,\n rtUniform.lightChoiceCount,\n 1.0,\n lightSample\n );\n}\n\n// Light choice for one of the resampled NEE candidates. The selection random\n// number is stratified across the candidates.\nfn sampleLightForNEECandidate(\n scatterPos: vec3f,\n rnd: vec3f,\n candidateIndex: u32,\n candidateCount: u32,\n lightSample: ptr<function, LightSampleRec>\n) {\n sampleLightChoiceTable(\n scatterPos,\n stratifyLightChoiceRandom(rnd, candidateIndex, candidateCount),\n 0,\n rtUniform.lightChoiceCount,\n 1.0,\n lightSample\n );\n}\n";
|
|
2
2
|
export default _default;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { LIGHT_CHOICE_ANALYTIC, LIGHT_CHOICE_EMISSIVE_TRIANGLE, LIGHT_CHOICE_ENVIRONMENT } from '../../lightConstants.js';
|
|
2
2
|
export default /*wgsl */ `
|
|
3
|
-
fn
|
|
4
|
-
let
|
|
5
|
-
let
|
|
3
|
+
fn eH(light: Light, fk: vec3f, iY: vec2f, lightSample: ptr<function, LightSampleRec>) {
|
|
4
|
+
let iz = light.position - fk;
|
|
5
|
+
let ao = length(iz);
|
|
6
6
|
if (light.radiusOrSpread <= 0.0) {
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
if (
|
|
10
|
+
if (ao <= 1e-6) {
|
|
11
11
|
(*lightSample).direction = vec3f(0.0, 0.0, 1.0);
|
|
12
12
|
(*lightSample).normal = vec3f(0.0, 0.0, -1.0);
|
|
13
13
|
(*lightSample).dist = 0.0;
|
|
@@ -16,66 +16,70 @@ if (ak <= 1e-6) {
|
|
|
16
16
|
(*lightSample).isDelta = true;
|
|
17
17
|
return;
|
|
18
18
|
}
|
|
19
|
-
(*lightSample).direction =
|
|
19
|
+
(*lightSample).direction = iz / ao;
|
|
20
20
|
(*lightSample).normal = -(*lightSample).direction;
|
|
21
|
-
(*lightSample).dist =
|
|
21
|
+
(*lightSample).dist = ao;
|
|
22
22
|
(*lightSample).pdf = 1.0;
|
|
23
23
|
(*lightSample).emission = light.emission /
|
|
24
|
-
max(
|
|
24
|
+
max(ao * ao, 1e-8);
|
|
25
25
|
(*lightSample).isDelta = true;
|
|
26
26
|
return;
|
|
27
27
|
}
|
|
28
28
|
let radius = max(light.radiusOrSpread, 1e-6);
|
|
29
29
|
(*lightSample).isDelta = false;
|
|
30
|
-
var
|
|
30
|
+
var gG: vec3f;
|
|
31
31
|
|
|
32
|
-
if (
|
|
33
|
-
let z = 1.0 - 2.0 *
|
|
34
|
-
let
|
|
35
|
-
let azimuth = TWOPI *
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
32
|
+
if (ao <= radius) {
|
|
33
|
+
let z = 1.0 - 2.0 * iY.x;
|
|
34
|
+
let dr = sqrt(max(0.0, 1.0 - z * z));
|
|
35
|
+
let azimuth = TWOPI * iY.y;
|
|
36
|
+
gG = vec3f(
|
|
37
|
+
dr * cos(azimuth),
|
|
38
|
+
dr * sin(azimuth),
|
|
39
39
|
z
|
|
40
40
|
);
|
|
41
41
|
(*lightSample).pdf = INV4PI;
|
|
42
42
|
}
|
|
43
43
|
else {
|
|
44
|
-
let
|
|
45
|
-
let
|
|
44
|
+
let uk = iz / ao;
|
|
45
|
+
let sinThetaMaxSquared = min(
|
|
46
46
|
1.0,
|
|
47
|
-
radius * radius / (
|
|
47
|
+
radius * radius / (ao * ao)
|
|
48
48
|
);
|
|
49
|
-
let cosThetaMax = sqrt(max(0.0, 1.0 -
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
let
|
|
49
|
+
let cosThetaMax = sqrt(max(0.0, 1.0 - sinThetaMaxSquared));
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
let oneMinusCosThetaMax = sinThetaMaxSquared / (1.0 + cosThetaMax);
|
|
53
|
+
let kZ = iY.x * oneMinusCosThetaMax;
|
|
54
|
+
let ct = 1.0 - kZ;
|
|
55
|
+
let sinTheta = sqrt(max(0.0, kZ * (2.0 - kZ)));
|
|
56
|
+
let azimuth = TWOPI * iY.y;
|
|
53
57
|
var tangent: vec3f;
|
|
54
58
|
var bitangent: vec3f;
|
|
55
|
-
|
|
56
|
-
|
|
59
|
+
sampling_orthonormal_basis(uk, &tangent, &bitangent);
|
|
60
|
+
gG = uk * ct
|
|
57
61
|
+ tangent * (sinTheta * cos(azimuth))
|
|
58
62
|
+ bitangent * (sinTheta * sin(azimuth));
|
|
59
63
|
(*lightSample).pdf = 1.0 / max(
|
|
60
|
-
TWOPI *
|
|
64
|
+
TWOPI * oneMinusCosThetaMax,
|
|
61
65
|
1e-8
|
|
62
66
|
);
|
|
63
67
|
}
|
|
64
68
|
|
|
65
|
-
let
|
|
66
|
-
let
|
|
67
|
-
let
|
|
68
|
-
-
|
|
69
|
-
let
|
|
70
|
-
let
|
|
71
|
-
(*lightSample).dist = select(
|
|
72
|
-
(*lightSample).direction =
|
|
73
|
-
let tl =
|
|
69
|
+
let iA = dot(gG, iz);
|
|
70
|
+
let qT = dot(iz, iz);
|
|
71
|
+
let bj = iA * iA
|
|
72
|
+
- qT + radius * radius;
|
|
73
|
+
let cI = iA - sqrt(max(0.0, bj));
|
|
74
|
+
let cw = iA + sqrt(max(0.0, bj));
|
|
75
|
+
(*lightSample).dist = select(cw, cI, cI > 1e-6);
|
|
76
|
+
(*lightSample).direction = gG;
|
|
77
|
+
let tl = fk + gG * (*lightSample).dist;
|
|
74
78
|
(*lightSample).normal = normalize(tl - light.position);
|
|
75
79
|
(*lightSample).emission = light.emission;
|
|
76
80
|
}
|
|
77
81
|
|
|
78
|
-
fn
|
|
82
|
+
fn bC(
|
|
79
83
|
light: Light,
|
|
80
84
|
surfacePoint: vec3f,
|
|
81
85
|
lowerLeft: vec3f,
|
|
@@ -86,15 +90,15 @@ return;
|
|
|
86
90
|
}
|
|
87
91
|
let width = length(light.u);
|
|
88
92
|
let height = length(light.v);
|
|
89
|
-
let
|
|
93
|
+
let dU = surfacePoint - lowerLeft;
|
|
90
94
|
let uv = vec2f(
|
|
91
|
-
dot(
|
|
92
|
-
dot(
|
|
95
|
+
dot(dU, light.u / width) / width,
|
|
96
|
+
dot(dU, light.v / height) / height
|
|
93
97
|
);
|
|
94
98
|
(*result).emission *= sampleMap(i32(light.textureIndex), uv).rgb;
|
|
95
99
|
}
|
|
96
100
|
|
|
97
|
-
fn
|
|
101
|
+
fn jZ(
|
|
98
102
|
light: Light,
|
|
99
103
|
shadingPoint: vec3f,
|
|
100
104
|
samplePoint: vec2f,
|
|
@@ -105,27 +109,27 @@ let lowerLeft = light.position - 0.5 * (light.u + light.v);
|
|
|
105
109
|
let spread = clamp(light.radiusOrSpread, 0.0, 1.0);
|
|
106
110
|
|
|
107
111
|
if (spread <= 0.001) {
|
|
108
|
-
let
|
|
109
|
-
let surfacePoint = shadingPoint - normal *
|
|
110
|
-
let
|
|
112
|
+
let gg = dot(normal, shadingPoint - light.position);
|
|
113
|
+
let surfacePoint = shadingPoint - normal * gg;
|
|
114
|
+
let dU = surfacePoint - lowerLeft;
|
|
111
115
|
let width = length(light.u);
|
|
112
116
|
let height = length(light.v);
|
|
113
117
|
let uv = vec2f(
|
|
114
|
-
dot(
|
|
115
|
-
dot(
|
|
118
|
+
dot(dU, light.u / width) / width,
|
|
119
|
+
dot(dU, light.v / height) / height
|
|
116
120
|
);
|
|
117
|
-
if (
|
|
121
|
+
if (gg <= 0.0 || any(uv < vec2f(0.0)) || any(uv > vec2f(1.0))) {
|
|
118
122
|
(*result).emission = vec3f(0.0);
|
|
119
123
|
(*result).pdf = 0.0;
|
|
120
124
|
return;
|
|
121
125
|
}
|
|
122
126
|
(*result).direction = -normal;
|
|
123
|
-
(*result).dist =
|
|
127
|
+
(*result).dist = gg;
|
|
124
128
|
(*result).normal = normal;
|
|
125
129
|
(*result).emission = light.emission;
|
|
126
130
|
(*result).pdf = 1.0;
|
|
127
131
|
(*result).isDelta = true;
|
|
128
|
-
|
|
132
|
+
bC(light, surfacePoint, lowerLeft, result);
|
|
129
133
|
return;
|
|
130
134
|
}
|
|
131
135
|
|
|
@@ -133,23 +137,23 @@ let surfacePoint = lowerLeft
|
|
|
133
137
|
+ light.u * samplePoint.x
|
|
134
138
|
+ light.v * samplePoint.y;
|
|
135
139
|
let offset = surfacePoint - shadingPoint;
|
|
136
|
-
let
|
|
137
|
-
(*result).dist = sqrt(
|
|
140
|
+
let bG = dot(offset, offset);
|
|
141
|
+
(*result).dist = sqrt(bG);
|
|
138
142
|
(*result).direction = offset / (*result).dist;
|
|
139
143
|
(*result).normal = normal;
|
|
140
|
-
let
|
|
141
|
-
let
|
|
142
|
-
if (
|
|
144
|
+
let fY = dot(-(*result).direction, normal);
|
|
145
|
+
let pp = cos(0.5 * PI * spread);
|
|
146
|
+
if (fY <= 0.0 || fY < pp) {
|
|
143
147
|
(*result).emission = vec3f(0.0);
|
|
144
148
|
(*result).pdf = 0.0;
|
|
145
149
|
return;
|
|
146
150
|
}
|
|
147
151
|
(*result).emission = light.emission;
|
|
148
|
-
(*result).pdf =
|
|
149
|
-
|
|
152
|
+
(*result).pdf = bG / max(light.area * fY, 1e-8);
|
|
153
|
+
bC(light, surfacePoint, lowerLeft, result);
|
|
150
154
|
}
|
|
151
155
|
|
|
152
|
-
fn
|
|
156
|
+
fn gc(
|
|
153
157
|
light: Light,
|
|
154
158
|
result: ptr<function, LightSampleRec>
|
|
155
159
|
) {
|
|
@@ -161,70 +165,70 @@ result: ptr<function, LightSampleRec>
|
|
|
161
165
|
(*result).isDelta = true;
|
|
162
166
|
}
|
|
163
167
|
|
|
164
|
-
fn
|
|
168
|
+
fn ka(
|
|
165
169
|
light: Light,
|
|
166
170
|
shadingPoint: vec3f,
|
|
167
171
|
samplePoint: vec2f,
|
|
168
172
|
result: ptr<function, LightSampleRec>
|
|
169
173
|
) {
|
|
170
|
-
|
|
174
|
+
eH(light, shadingPoint, samplePoint, result);
|
|
171
175
|
let surfacePoint = shadingPoint + (*result).direction * (*result).dist;
|
|
172
|
-
let
|
|
173
|
-
(*result).emission *=
|
|
176
|
+
let dI = normalize(shadingPoint - surfacePoint);
|
|
177
|
+
(*result).emission *= evaluateSpotEmissionMultiplier(light, dI);
|
|
174
178
|
}
|
|
175
179
|
|
|
176
|
-
fn
|
|
180
|
+
fn sampleAnalyticLight(
|
|
177
181
|
light: Light,
|
|
178
182
|
shadingPoint: vec3f,
|
|
179
183
|
samplePoint: vec2f,
|
|
180
184
|
result: ptr<function, LightSampleRec>
|
|
181
185
|
) {
|
|
182
|
-
let
|
|
183
|
-
if (HAS_SCENE_RECT_LIGHT &&
|
|
184
|
-
|
|
186
|
+
let dO = i32(light.litType);
|
|
187
|
+
if (HAS_SCENE_RECT_LIGHT && dO == RECT_LIGHT) {
|
|
188
|
+
jZ(light, shadingPoint, samplePoint, result);
|
|
185
189
|
return;
|
|
186
190
|
}
|
|
187
|
-
if (HAS_SCENE_SPHERE_LIGHT &&
|
|
188
|
-
|
|
191
|
+
if (HAS_SCENE_SPHERE_LIGHT && dO == SPHERE_LIGHT) {
|
|
192
|
+
eH(light, shadingPoint, samplePoint, result);
|
|
189
193
|
return;
|
|
190
194
|
}
|
|
191
|
-
if (HAS_SCENE_SPOT_LIGHT &&
|
|
192
|
-
|
|
195
|
+
if (HAS_SCENE_SPOT_LIGHT && dO == SPOT_LIGHT) {
|
|
196
|
+
ka(light, shadingPoint, samplePoint, result);
|
|
193
197
|
return;
|
|
194
198
|
}
|
|
195
|
-
if (HAS_SCENE_DIRECTIONAL_LIGHT &&
|
|
196
|
-
|
|
199
|
+
if (HAS_SCENE_DIRECTIONAL_LIGHT && dO == DIRECTIONAL_LIGHT) {
|
|
200
|
+
gc(light, result);
|
|
197
201
|
}
|
|
198
202
|
}
|
|
199
203
|
|
|
200
|
-
fn
|
|
204
|
+
fn ig(iY: vec2f, lightSample: ptr<function, LightSampleRec>) {
|
|
201
205
|
var uv: vec2f;
|
|
202
206
|
|
|
203
207
|
var pdf: f32;
|
|
204
|
-
let direction =
|
|
208
|
+
let direction = pn(iY, &uv, &pdf);
|
|
205
209
|
(*lightSample).pdf = pdf;
|
|
206
210
|
(*lightSample).direction = direction;
|
|
207
211
|
(*lightSample).emission = textureLinear(envMap, uv).rgb;
|
|
208
212
|
(*lightSample).dist = INF;
|
|
209
213
|
}
|
|
210
214
|
|
|
211
|
-
fn
|
|
215
|
+
fn loadLightSamplingTexel(im: i32) -> vec4f {
|
|
212
216
|
let width = rtUniform.lightSamplingTextureWidth;
|
|
213
217
|
return textureLoad(
|
|
214
218
|
lightSamplingData,
|
|
215
|
-
vec2i(
|
|
219
|
+
vec2i(im % width, im / width),
|
|
216
220
|
0
|
|
217
221
|
);
|
|
218
222
|
}
|
|
219
223
|
|
|
220
|
-
fn
|
|
224
|
+
fn getEmissiveTriangle(index: i32) -> EmissiveTriangle {
|
|
221
225
|
let offset = index * 6;
|
|
222
|
-
let a =
|
|
223
|
-
let b =
|
|
224
|
-
let c =
|
|
225
|
-
let d =
|
|
226
|
-
let e =
|
|
227
|
-
let f =
|
|
226
|
+
let a = loadLightSamplingTexel(offset);
|
|
227
|
+
let b = loadLightSamplingTexel(offset + 1);
|
|
228
|
+
let c = loadLightSamplingTexel(offset + 2);
|
|
229
|
+
let d = loadLightSamplingTexel(offset + 3);
|
|
230
|
+
let e = loadLightSamplingTexel(offset + 4);
|
|
231
|
+
let f = loadLightSamplingTexel(offset + 5);
|
|
228
232
|
return EmissiveTriangle(
|
|
229
233
|
a.xyz, a.w,
|
|
230
234
|
b.xyz, b.w,
|
|
@@ -234,9 +238,9 @@ e.zw, f.xy, f.zw
|
|
|
234
238
|
);
|
|
235
239
|
}
|
|
236
240
|
|
|
237
|
-
fn
|
|
238
|
-
let data =
|
|
239
|
-
return
|
|
241
|
+
fn tJ(index: i32) -> pW {
|
|
242
|
+
let data = loadLightSamplingTexel(rtUniform.lightChoiceTexelOffset + index);
|
|
243
|
+
return pW(
|
|
240
244
|
data.x,
|
|
241
245
|
bitcast<i32>(data.y),
|
|
242
246
|
bitcast<i32>(data.z),
|
|
@@ -244,35 +248,35 @@ bitcast<i32>(data.w)
|
|
|
244
248
|
);
|
|
245
249
|
}
|
|
246
250
|
|
|
247
|
-
fn
|
|
248
|
-
return
|
|
251
|
+
fn jG(nP: i32, index: i32) -> pW {
|
|
252
|
+
return tJ(nP + index);
|
|
249
253
|
}
|
|
250
254
|
|
|
251
|
-
fn
|
|
255
|
+
fn nG(
|
|
252
256
|
rnd: vec3f,
|
|
253
|
-
|
|
257
|
+
mE: u32,
|
|
254
258
|
candidateCount: u32
|
|
255
259
|
) -> vec3f {
|
|
256
|
-
var
|
|
260
|
+
var um = rnd;
|
|
257
261
|
let count = max(candidateCount, 1u);
|
|
258
|
-
|
|
262
|
+
um.z = (rnd.z + f32(min(mE, count - 1u))) /
|
|
259
263
|
f32(count);
|
|
260
|
-
return
|
|
264
|
+
return um;
|
|
261
265
|
}
|
|
262
266
|
|
|
263
|
-
fn
|
|
267
|
+
fn mr(
|
|
264
268
|
triangle: EmissiveTriangle,
|
|
265
|
-
|
|
266
|
-
|
|
269
|
+
fk: vec3f,
|
|
270
|
+
iY: vec2f,
|
|
267
271
|
lightSample: ptr<function, LightSampleRec>
|
|
268
272
|
) {
|
|
269
|
-
let
|
|
273
|
+
let xJ = sqrt(iY.x);
|
|
270
274
|
let barycentric = vec3f(
|
|
271
|
-
1.0 -
|
|
272
|
-
|
|
273
|
-
|
|
275
|
+
1.0 - xJ,
|
|
276
|
+
xJ * (1.0 - iY.y),
|
|
277
|
+
xJ * iY.y
|
|
274
278
|
);
|
|
275
|
-
let
|
|
279
|
+
let ut =
|
|
276
280
|
barycentric.x * triangle.p0 +
|
|
277
281
|
barycentric.y * triangle.p1 +
|
|
278
282
|
barycentric.z * triangle.p2;
|
|
@@ -280,12 +284,12 @@ let uv =
|
|
|
280
284
|
barycentric.x * triangle.uv0 +
|
|
281
285
|
barycentric.y * triangle.uv1 +
|
|
282
286
|
barycentric.z * triangle.uv2;
|
|
283
|
-
let
|
|
287
|
+
let cQ =
|
|
284
288
|
barycentric.x * triangle.secondaryUv0 +
|
|
285
289
|
barycentric.y * triangle.secondaryUv1 +
|
|
286
290
|
barycentric.z * triangle.secondaryUv2;
|
|
287
291
|
let normal = normalize(cross(triangle.p1 - triangle.p0, triangle.p2 - triangle.p0));
|
|
288
|
-
(*lightSample).direction =
|
|
292
|
+
(*lightSample).direction = ut - fk;
|
|
289
293
|
(*lightSample).dist = length((*lightSample).direction);
|
|
290
294
|
if ((*lightSample).dist <= EPS) {
|
|
291
295
|
(*lightSample).emission = vec3f(0.0);
|
|
@@ -294,27 +298,27 @@ return;
|
|
|
294
298
|
}
|
|
295
299
|
(*lightSample).direction /= (*lightSample).dist;
|
|
296
300
|
(*lightSample).normal = normal;
|
|
297
|
-
let
|
|
298
|
-
if (
|
|
301
|
+
let om = dot(normal, -(*lightSample).direction);
|
|
302
|
+
if (om <= 0.0) {
|
|
299
303
|
(*lightSample).emission = vec3f(0.0);
|
|
300
304
|
(*lightSample).pdf = 0.0;
|
|
301
305
|
return;
|
|
302
306
|
}
|
|
303
307
|
(*lightSample).emission = getMaterialEmission(
|
|
304
|
-
i32(triangle.materialIndex), uv,
|
|
308
|
+
i32(triangle.materialIndex), uv, cQ
|
|
305
309
|
);
|
|
306
310
|
(*lightSample).selectionPmf = triangle.selectionPmf;
|
|
307
311
|
(*lightSample).pdf = triangle.selectionPmf *
|
|
308
312
|
((*lightSample).dist * (*lightSample).dist) /
|
|
309
|
-
max(triangle.area *
|
|
313
|
+
max(triangle.area * om, 1e-8);
|
|
310
314
|
}
|
|
311
315
|
|
|
312
|
-
fn
|
|
313
|
-
|
|
316
|
+
fn hb(
|
|
317
|
+
fk: vec3f,
|
|
314
318
|
rnd: vec3f,
|
|
315
|
-
|
|
319
|
+
nP: i32,
|
|
316
320
|
choiceCount: i32,
|
|
317
|
-
|
|
321
|
+
nN: f32,
|
|
318
322
|
lightSample: ptr<function, LightSampleRec>
|
|
319
323
|
) {
|
|
320
324
|
(*lightSample).emission = vec3f(0.0);
|
|
@@ -328,52 +332,52 @@ if (choiceCount <= 0) {
|
|
|
328
332
|
return;
|
|
329
333
|
}
|
|
330
334
|
|
|
331
|
-
let
|
|
332
|
-
let column = min(i32(
|
|
333
|
-
let
|
|
334
|
-
let
|
|
335
|
-
|
|
335
|
+
let sk = rnd.z * f32(choiceCount);
|
|
336
|
+
let column = min(i32(sk), choiceCount - 1);
|
|
337
|
+
let rS = jG(nP, column);
|
|
338
|
+
let jc = select(
|
|
339
|
+
rS.aliasIndex,
|
|
336
340
|
column,
|
|
337
|
-
fract(
|
|
341
|
+
fract(sk) < rS.probability
|
|
338
342
|
);
|
|
339
|
-
let
|
|
340
|
-
if (USE_ENVMAP &&
|
|
343
|
+
let choice = jG(nP, jc);
|
|
344
|
+
if (USE_ENVMAP && choice.sourceType == ${LIGHT_CHOICE_ENVIRONMENT}) {
|
|
341
345
|
(*lightSample).sourceType = 0u;
|
|
342
|
-
(*lightSample).sourceIndex = u32(
|
|
343
|
-
|
|
346
|
+
(*lightSample).sourceIndex = u32(choice.sourceIndex);
|
|
347
|
+
ig(rnd.xy, lightSample);
|
|
344
348
|
(*lightSample).selectionPmf = rtUniform.envLightPmf;
|
|
345
349
|
(*lightSample).pdf *= rtUniform.envLightPmf;
|
|
346
350
|
}
|
|
347
|
-
else if (
|
|
351
|
+
else if (choice.sourceType == ${LIGHT_CHOICE_ANALYTIC}) {
|
|
348
352
|
(*lightSample).sourceType = 2u;
|
|
349
|
-
(*lightSample).sourceIndex = u32(
|
|
350
|
-
let light = analyticLights[
|
|
351
|
-
|
|
353
|
+
(*lightSample).sourceIndex = u32(choice.sourceIndex);
|
|
354
|
+
let light = analyticLights[choice.sourceIndex];
|
|
355
|
+
sampleAnalyticLight(light, fk, rnd.xy, lightSample);
|
|
352
356
|
(*lightSample).selectionPmf = light.selectionPmf;
|
|
353
357
|
(*lightSample).pdf *= light.selectionPmf;
|
|
354
358
|
}
|
|
355
|
-
else if (HAS_SCENE_EMISSIVE_LIGHT &&
|
|
359
|
+
else if (HAS_SCENE_EMISSIVE_LIGHT && choice.sourceType == ${LIGHT_CHOICE_EMISSIVE_TRIANGLE}) {
|
|
356
360
|
(*lightSample).sourceType = 1u;
|
|
357
|
-
(*lightSample).sourceIndex = u32(
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
+
(*lightSample).sourceIndex = u32(choice.sourceIndex);
|
|
362
|
+
mr(
|
|
363
|
+
getEmissiveTriangle(choice.sourceIndex),
|
|
364
|
+
fk,
|
|
361
365
|
rnd.xy,
|
|
362
366
|
lightSample
|
|
363
367
|
);
|
|
364
368
|
}
|
|
365
|
-
(*lightSample).selectionPmf *=
|
|
366
|
-
(*lightSample).pdf *=
|
|
369
|
+
(*lightSample).selectionPmf *= nN;
|
|
370
|
+
(*lightSample).pdf *= nN;
|
|
367
371
|
}
|
|
368
372
|
|
|
369
373
|
fn sampleLight(
|
|
370
|
-
|
|
374
|
+
fk: vec3f,
|
|
371
375
|
rnd: vec3f,
|
|
372
376
|
lightSample: ptr<function, LightSampleRec>,
|
|
373
377
|
tk: bool
|
|
374
378
|
) {
|
|
375
|
-
|
|
376
|
-
|
|
379
|
+
hb(
|
|
380
|
+
fk,
|
|
377
381
|
rnd,
|
|
378
382
|
0,
|
|
379
383
|
rtUniform.lightChoiceCount,
|
|
@@ -384,16 +388,16 @@ lightSample
|
|
|
384
388
|
|
|
385
389
|
|
|
386
390
|
|
|
387
|
-
fn
|
|
388
|
-
|
|
391
|
+
fn nk(
|
|
392
|
+
fk: vec3f,
|
|
389
393
|
rnd: vec3f,
|
|
390
|
-
|
|
394
|
+
mE: u32,
|
|
391
395
|
candidateCount: u32,
|
|
392
396
|
lightSample: ptr<function, LightSampleRec>
|
|
393
397
|
) {
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
398
|
+
hb(
|
|
399
|
+
fk,
|
|
400
|
+
nG(rnd, mE, candidateCount),
|
|
397
401
|
0,
|
|
398
402
|
rtUniform.lightChoiceCount,
|
|
399
403
|
1.0,
|