@meimu/mutracer 0.1.3 → 0.1.5

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.
Files changed (125) hide show
  1. package/dist/assets/bvh.worker.js +1 -1
  2. package/dist/mutracer.umd.js +4155 -4052
  3. package/docs/api.md +13 -10
  4. package/docs/materials.md +17 -26
  5. package/docs/threejs.md +35 -9
  6. package/docs/viewer.md +36 -3
  7. package/lib/Engine.js +18 -1
  8. package/lib/Engine.js.map +1 -1
  9. package/lib/main.d.ts +1 -1
  10. package/lib/main.js.map +1 -1
  11. package/lib/oidn.d.ts +1 -1
  12. package/lib/oidnBundledWeights.cdn.d.ts +2 -2
  13. package/lib/renderer/MaterialTable.d.ts +1 -0
  14. package/lib/renderer/MaterialTable.js +10 -4
  15. package/lib/renderer/MaterialTable.js.map +1 -1
  16. package/lib/renderer/WGPUBloomPass.js +18 -18
  17. package/lib/renderer/WGPUFullQuadPass.js +6 -6
  18. package/lib/renderer/WGPUJNLMDenoiser.js +69 -69
  19. package/lib/renderer/WGPURayTraceOutput.js +14 -14
  20. package/lib/renderer/WGPURayTracePass.d.ts +2 -0
  21. package/lib/renderer/WGPURayTracePass.js +17 -9
  22. package/lib/renderer/WGPURayTracePass.js.map +1 -1
  23. package/lib/renderer/WGPURenderingPipeline.js +15 -15
  24. package/lib/renderer/WebGLJNLMDenoiser.js +69 -69
  25. package/lib/renderer/WebGLRayTraceOutputPass.js +4 -4
  26. package/lib/renderer/WebGLRayTracePass.d.ts +1 -0
  27. package/lib/renderer/WebGLRayTracePass.js +8 -1
  28. package/lib/renderer/WebGLRayTracePass.js.map +1 -1
  29. package/lib/renderer/envMapCreation.d.ts +5 -1
  30. package/lib/renderer/envMapCreation.js +42 -5
  31. package/lib/renderer/envMapCreation.js.map +1 -1
  32. package/lib/renderer/geometryUpdates.js +1 -1
  33. package/lib/renderer/geometryUpdates.js.map +1 -1
  34. package/lib/renderer/glsl/chunks/cameraRay.glsl.js +12 -12
  35. package/lib/renderer/glsl/chunks/envMap.glsl.js +66 -54
  36. package/lib/renderer/glsl/chunks/envMap.glsl.js.map +1 -1
  37. package/lib/renderer/glsl/chunks/intersect.glsl.js +323 -315
  38. package/lib/renderer/glsl/chunks/intersect.glsl.js.map +1 -1
  39. package/lib/renderer/glsl/chunks/materialBuffer.glsl.js +154 -121
  40. package/lib/renderer/glsl/chunks/materialBuffer.glsl.js.map +1 -1
  41. package/lib/renderer/glsl/chunks/openPbrBsdf.glsl.js +434 -434
  42. package/lib/renderer/glsl/chunks/openPbrBsdf.glsl.js.map +1 -1
  43. package/lib/renderer/glsl/chunks/rand.glsl.js +3 -3
  44. package/lib/renderer/glsl/chunks/random.glsl.js +3 -3
  45. package/lib/renderer/glsl/chunks/rayTraceCore.glsl.js +42 -41
  46. package/lib/renderer/glsl/chunks/rayTraceCore.glsl.js.map +1 -1
  47. package/lib/renderer/glsl/chunks/sampleLight.glsl.js +69 -69
  48. package/lib/renderer/glsl/chunks/sampleMaterial.glsl.js +84 -84
  49. package/lib/renderer/glsl/chunks/sampleMaterial.glsl.js.map +1 -1
  50. package/lib/renderer/glsl/chunks/sampleShadowCatcher.glsl.js +12 -12
  51. package/lib/renderer/glsl/chunks/sampling.glsl.js +75 -75
  52. package/lib/renderer/glsl/chunks/sobol.glsl.js +61 -61
  53. package/lib/renderer/glsl/chunks/textureLinear.glsl.js +5 -5
  54. package/lib/renderer/glsl/chunks/uvProjection.glsl.js +11 -11
  55. package/lib/renderer/glsl/depthQuery.frag.js +5 -5
  56. package/lib/renderer/glsl/depthQuery.frag.js.map +1 -1
  57. package/lib/renderer/glsl/normalizeRayTraceOutput.frag.js +8 -8
  58. package/lib/renderer/glsl/rayTrace.frag.js +133 -133
  59. package/lib/renderer/glsl/rayTrace.frag.js.map +1 -1
  60. package/lib/renderer/glsl/shadowCatcher.frag.js +9 -9
  61. package/lib/renderer/glsl/shadowCatcher.frag.js.map +1 -1
  62. package/lib/renderer/glsl/webglPipeline.frag.js +52 -52
  63. package/lib/renderer/lightsUtil.js +6 -4
  64. package/lib/renderer/lightsUtil.js.map +1 -1
  65. package/lib/renderer/materialChanges.js +1 -1
  66. package/lib/renderer/materialChanges.js.map +1 -1
  67. package/lib/renderer/materialComparison.generated.js +36 -18
  68. package/lib/renderer/materialComparison.generated.js.map +1 -1
  69. package/lib/renderer/prepareMeshBVH.js +2 -2
  70. package/lib/renderer/prepareMeshBVH.js.map +1 -1
  71. package/lib/renderer/sceneChangeDetector.js +4 -1
  72. package/lib/renderer/sceneChangeDetector.js.map +1 -1
  73. package/lib/renderer/sceneLightChanges.js +3 -2
  74. package/lib/renderer/sceneLightChanges.js.map +1 -1
  75. package/lib/renderer/scratchSampling.js +18 -18
  76. package/lib/renderer/wgsl/chunks/common.wgsl.js +4 -4
  77. package/lib/renderer/wgsl/chunks/envMap.wgsl.d.ts +1 -1
  78. package/lib/renderer/wgsl/chunks/envMap.wgsl.js +39 -31
  79. package/lib/renderer/wgsl/chunks/envMap.wgsl.js.map +1 -1
  80. package/lib/renderer/wgsl/chunks/intersect.wgsl.js +476 -470
  81. package/lib/renderer/wgsl/chunks/intersect.wgsl.js.map +1 -1
  82. package/lib/renderer/wgsl/chunks/intersectionAlpha.wgsl.js +8 -8
  83. package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.js +95 -60
  84. package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.js.map +1 -1
  85. package/lib/renderer/wgsl/chunks/openPbrBsdf.wgsl.js +469 -469
  86. package/lib/renderer/wgsl/chunks/pdm_displacement.wgsl.d.ts +1 -1
  87. package/lib/renderer/wgsl/chunks/pdm_displacement.wgsl.js +117 -120
  88. package/lib/renderer/wgsl/chunks/pdm_displacement.wgsl.js.map +1 -1
  89. package/lib/renderer/wgsl/chunks/rand.wgsl.js +3 -3
  90. package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.js +25 -22
  91. package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.js.map +1 -1
  92. package/lib/renderer/wgsl/chunks/sampleLight.wgsl.js +127 -127
  93. package/lib/renderer/wgsl/chunks/sampleMaterial.wgsl.js +136 -136
  94. package/lib/renderer/wgsl/chunks/sampleShadowCatcher.wgsl.js +6 -6
  95. package/lib/renderer/wgsl/chunks/sampling.wgsl.js +73 -73
  96. package/lib/renderer/wgsl/chunks/sobol.wgsl.js +62 -62
  97. package/lib/renderer/wgsl/chunks/uvProjection.wgsl.js +11 -11
  98. package/lib/renderer/wgsl/compose.frag.wgsl.js +105 -105
  99. package/lib/renderer/wgsl/customDenoise.wgsl.js +10 -10
  100. package/lib/renderer/wgsl/depthQuery.wgsl.d.ts +1 -1
  101. package/lib/renderer/wgsl/depthQuery.wgsl.js +5 -5
  102. package/lib/renderer/wgsl/depthQuery.wgsl.js.map +1 -1
  103. package/lib/renderer/wgsl/offlineAdaptive.compute.js +28 -28
  104. package/lib/renderer/wgsl/rayTrace.compute.js +251 -248
  105. package/lib/renderer/wgsl/rayTrace.compute.js.map +1 -1
  106. package/lib/scene/EnvironmentLight.d.ts +9 -3
  107. package/lib/scene/EnvironmentLight.js +9 -2
  108. package/lib/scene/EnvironmentLight.js.map +1 -1
  109. package/lib/scene/OpenPBRMaterial.d.ts +1 -1
  110. package/lib/scene/OpenPBRMaterial.js +1 -1
  111. package/lib/scene/OpenPBRMaterial.js.map +1 -1
  112. package/lib/scene/Scene.d.ts +4 -0
  113. package/lib/scene/Scene.js.map +1 -1
  114. package/lib/scene/SpotLight.d.ts +2 -2
  115. package/lib/scene/SpotLight.js +1 -1
  116. package/lib/scene/SpotLight.js.map +1 -1
  117. package/lib/scene/Texture.d.ts +17 -6
  118. package/lib/scene/Texture.js +13 -4
  119. package/lib/scene/Texture.js.map +1 -1
  120. package/lib/util/fromTHREE.js +151 -29
  121. package/lib/util/fromTHREE.js.map +1 -1
  122. package/lib/version.d.ts +1 -1
  123. package/lib/version.js +1 -1
  124. package/lib/version.js.map +1 -1
  125. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"sampleMaterial.glsl.js","sourceRoot":"","sources":["../../../../src/renderer/glsl/chunks/sampleMaterial.glsl.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,iIAAiI;AAEjI,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACvC,eAAe,IAAI,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkRlB,CAAC","sourcesContent":["// Estimate the direct lighting integral using multiple importance sampling\n// http://www.pbr-book.org/3ed-2018/Light_Transport_I_Surface_Reflection/Direct_Lighting.html#EstimatingtheDirectLightingIntegral\n\nimport { glsl } from '../../shader.js';\nexport default glsl`\nvec3 DirectLight(SurfaceInteraction si, OpenPbrResolvedMaterial mat, OpenPbrPreparedBsdf prepared, inout Path path, vec3 ffnormal, bool isSurface) {\n float occluded = 1.0;\n vec3 lightRnd = vec3(sample2D(bounceDim(LIGHT_POSITION)), sample1D(bounceDim(LIGHT_SELECT)));\n\n LightSampleRec lightSample;\n sampleLight(si.position, lightRnd, lightSample, false);\n lightSample.emission = sampling_spectral_rgb_filter(lightSample.emission, pathWavelength);\n\n vec3 lightDir = lightSample.direction;\n vec3 viewDir = -path.ray.d;\n float lightPdf = lightSample.pdf;\n // Opaque surfaces are rendered two-sided by the core renderer. Use the\n // face-forward shading normal here as well, otherwise the early-out rejects\n // every direct-light sample seen from the back of a triangle (for example\n // the inside of an imported room wall).\n float cosThetaL = dot(ffnormal, lightDir);\n#ifdef NUM_COAT_NORMAL_MAPS\n if (isSurface && mat.coatNormalEnabled) { cosThetaL = dot(mat.geometricNormal, lightDir); }\n#endif\n\n if (lightPdf <= 0.0 || max(max(lightSample.emission.x, lightSample.emission.y), lightSample.emission.z) <= 0.0) {\n return vec3(0.0);\n }\n\n float scatteringPdf = 0.0;\n vec3 f = vec3(0.0);\n if (isSurface) {\n if (cosThetaL <= 0.0 && mat.transmissionWeight <= 0.0 && mat.subsurfaceWeight <= 0.0) {\n return vec3(0.0);\n }\n f = openpbr_eval_prepared(prepared, lightDir, scatteringPdf);\n }\n else {\n scatteringPdf = sampling_henyey_greenstein_phase(\n dot(viewDir, lightDir),\n si.mediumAnisotropy\n );\n f = vec3(scatteringPdf);\n }\n\n if (scatteringPdf <= 0.0 || max(max(f.x, f.y), f.z) <= 0.0) {\n return vec3(0.0);\n }\n\n Ray lightRay;\n vec3 shadowOrigin = si.position + EPS * lightDir;\n if (isSurface) {\n const float shadowTerminatorCutoff = 0.1;\n float normalLight = dot(si.normal, lightDir);\n#ifdef NUM_COAT_NORMAL_MAPS\n if (mat.coatNormalEnabled) { normalLight = dot(si.faceNormal, lightDir); }\n#endif\n vec3 geometricNormal = normalLight < 0.0 ? -si.faceNormal : si.faceNormal;\n normalLight = abs(normalLight);\n float geometricLight = dot(geometricNormal, lightDir);\n float offsetAmount = normalLight < shadowTerminatorCutoff\n ? clamp(\n 2.0 - (geometricLight + normalLight) / shadowTerminatorCutoff,\n 0.0,\n 1.0\n )\n : clamp(1.0 - geometricLight / shadowTerminatorCutoff, 0.0, 1.0);\n shadowOrigin += si.shadowOffset * offsetAmount;\n }\n initRay(lightRay, shadowOrigin, lightDir);\n if (intersectSceneShadow(lightRay, lightSample.dist - EPS, si.triangleIndex)) {\n return vec3(0.0);\n }\n\n#ifdef USE_ENVMAP\n // Match the endpoint used by a BSDF-sampled surface transmission, including\n // a separately displayed or grounded background and its coverage.\n if (isSurface && cosThetaL < 0.0 && lightRnd.z < envLightSelectionPmf) {\n vec4 background = sampleBackgroundFromRay(lightRay.o, lightDir);\n lightSample.emission = sampling_spectral_rgb_filter(background.rgb * background.a, pathWavelength);\n }\n#endif\n\n // Delta lights cannot be sampled by the BSDF strategy, so their MIS weight\n // is exactly one even when their light-selection PMF is small.\n float misWeight = lightSample.isDelta\n ? 1.0\n : sampling_power_heuristic(lightPdf, scatteringPdf);\n return misWeight > 0.0\n ? misWeight * lightSample.emission * f / lightPdf\n : vec3(0.0);\n}\n\n#ifdef NUM_COAT_NORMAL_MAPS\nvec3 coat_frame_normal(vec3 inputNormal, vec3 face, vec3 view) {\n bool front = dot(face, view) >= 0.0;\n vec3 ffFace = front ? face : -face;\n vec3 ffInput = front ? inputNormal : -inputNormal;\n if (dot(inputNormal, face) <= 0.0 || dot(ffInput, view) <= 1e-6) { return ffFace; }\n return ffInput;\n}\n#endif\nvoid SampleMaterial(inout SurfaceInteraction si, OpenPbrResolvedMaterial mat, inout Path path) {\n vec3 matRnd = vec3(sample2D(bounceDim(BSDF_DIRECTION)), sample1D(bounceDim(BSDF_LOBE)));\n#ifdef NUM_COAT_NORMAL_MAPS\n vec3 originalFace = si.faceNormal;\n vec3 originalNormal = si.normal;\n#endif\n float ndv1 = -dot(si.faceNormal, path.ray.d);\n float ndv2 = -dot(si.normal, path.ray.d);\n if ((mat.transmissionWeight > 0.0 || mat.subsurfaceWeight > 0.0) && mat.thinWalled) {\n // Always treat thin material as entering medium\n if (ndv1 < 0.0) {\n si.faceNormal = -si.faceNormal;\n ndv1 = -ndv1;\n }\n if (ndv2 < 0.0) {\n si.normal = -si.normal;\n ndv2 = -ndv2;\n }\n }\n // In same edge cases normal is not torwards the camera while we can still see the face.\n // We need to choose faceNormal in this case.\n bool useFaceN = ndv1 >= 0.0 && ndv2 < 0.0;\n float ndv = useFaceN ? ndv1 : ndv2;\n vec3 normal = useFaceN ? si.faceNormal : si.normal;\n\n mat.inside = ndv <= 0.0 && !mat.thinWalled;\n // In or out\n mat.relativeIor = ndv > 0.0 ? (1.0 / mat.specularIor) : mat.specularIor;\n vec3 ffnormal = ndv >= 0.0 ? normal : -normal;\n#ifdef NUM_COAT_NORMAL_MAPS\n if (mat.coatNormalEnabled) {\n vec3 view = -path.ray.d;\n float geometricView = dot(originalFace, view);\n mat.geometricNormal = geometricView >= 0.0 ? originalFace : -originalFace;\n ffnormal = coat_frame_normal(originalNormal, originalFace, view);\n mat.coatNormal = coat_frame_normal(si.coatNormal, originalFace, view);\n mat.inside = geometricView <= 0.0 && !mat.thinWalled;\n mat.relativeIor = (geometricView > 0.0 || mat.thinWalled) ? 1.0 / mat.specularIor : mat.specularIor;\n }\n#endif\n\n\n float scatteringPdf;\n vec3 scatterDir;\n path.scatteringIsDelta = false;\n bool mediumSampled = false;\n bool crossedBoundary = false;\n OpenPbrPreparedBsdf prepared;\n\n#ifdef HAS_MEDIUM\n int mediumType = si.mediumType;\n float d = distance(si.position, path.ray.o);\n vec3 segmentOrigin = path.ray.o;\n vec3 extinction = si.mediumExtinction;\n vec3 scattering = min(si.mediumScattering, extinction);\n float majorant = max(max(extinction.x, extinction.y), extinction.z);\n if (mediumType > 0 && majorant > 0.0) {\n // Sample one RGB extinction channel and divide by the mixture PDF. This\n // is the homogeneous-medium estimator used by PBRT and avoids the very\n // large exp((majorant - extinction) * distance) weights produced by\n // majorant tracking when OpenPBR SSS radii differ strongly by channel.\n int mediumChannel = min(int(sample1D(bounceDim(MEDIUM_CHANNEL)) * 3.0), 2);\n float channelExtinction = extinction[mediumChannel];\n float scatterDist = channelExtinction > 0.0\n ? min(-log(max(sample1D(bounceDim(MEDIUM_DISTANCE)), 1e-7)) / channelExtinction, d)\n : d;\n mediumSampled = scatterDist < d;\n vec3 transmittance = exp(-extinction * scatterDist);\n vec3 density = mediumSampled\n ? extinction * transmittance\n : transmittance;\n float mediumPdf = max(\n (density.x + density.y + density.z) / 3.0,\n 1e-8\n );\n if (mediumSampled) {\n path.beta *= transmittance * scattering / mediumPdf;\n // Move from the start of the segment, not from its end surface.\n path.ray.o = segmentOrigin + scatterDist * path.ray.d;\n si.position = path.ray.o;\n path.li += DirectLight(si, mat, prepared, path, ffnormal, false) * path.beta;\n\n // Pick a new direction based on the phase function\n scatterDir = sampling_henyey_greenstein(\n -path.ray.d,\n si.mediumAnisotropy,\n sample2D(bounceDim(PHASE_DIRECTION))\n );\n scatteringPdf = sampling_henyey_greenstein_phase(\n dot(scatterDir, -path.ray.d),\n si.mediumAnisotropy\n );\n }\n else {\n path.beta *= transmittance / mediumPdf;\n }\n }\n#endif\n\n // Direct lighting\n if (!mediumSampled) {\n path.li += mat.emission * path.beta;\n if (mat.materialType == UNLIT) {\n path.abort = true;\n return;\n }\n vec3 surfaceTangent = vec3(0.0);\n#ifdef USE_TANGENT\n surfaceTangent = si.tangent;\n#endif\n mat.directionTangent = si.directionTangent;\n mat.directionBitangent = si.directionBitangent;\n mat.geometryTangent = si.geometryTangent;\n mat.geometryBitangent = si.geometryBitangent;\n prepared = openpbr_prepare(surfaceTangent, mat, -path.ray.d, ffnormal);\n path.li += DirectLight(si, mat, prepared, path, ffnormal, true) * path.beta;\n // Sample BSDF for color and outgoing direction\n bool isNextRefraction;\n vec3 f = openpbr_sample_prepared(\n prepared,\n matRnd,\n scatterDir,\n scatteringPdf,\n isNextRefraction\n );\n // Null-boundary transmission is discrete and has no NEE competitor.\n path.scatteringIsDelta = !prepared.material.thinWalled &&\n abs(prepared.material.relativeIor - 1.0) <= 1e-6 &&\n prepared.probabilities[OPENPBR_LOBE_TRANSMISSION] >= 1.0 - 1e-6;\n // Match WebGPU: rejected VNDF/refraction proposals have no continuation.\n // Tracing their fallback direction with the incoming throughput invents\n // light paths, especially after total internal reflection inside glass.\n if (!(scatteringPdf > 0.0) || any(isnan(f)) || any(isinf(f)) ||\n dot(scatterDir, scatterDir) < 0.5) {\n path.scatteringPdf = 0.0;\n path.abort = true;\n return;\n }\n path.beta *= f / scatteringPdf;\n crossedBoundary = !mat.thinWalled &&\n isNextRefraction;\n path.isNextRefraction = isNextRefraction;\n // TODO prefer the opaque surface when transmission surface and opaque surface are overlapped.\n // Or the ray go out from transmission material will miss the opque surface.\n path.ray.o = si.position + EPS * scatterDir;\n#ifdef NUM_COAT_NORMAL_MAPS\n if (mat.coatNormalEnabled) { path.ray.o = si.position + EPS * (dot(originalFace, scatterDir) >= 0.0 ? originalFace : -originalFace); }\n#endif\n }\n\n path.scatteringPdf = scatteringPdf;\n initRay(path.ray, path.ray.o, scatterDir);\n if (mediumSampled) {\n path.isNextRefraction = false;\n }\n path.fromEye = false;\n\n#ifdef HAS_MEDIUM\n // A reflected ray stays in its current medium. Only a sampled transmission\n // event crosses the boundary of a medium-bearing closed mesh.\n if (!mediumSampled && crossedBoundary && mat.mediumType > 0) {\n if (ndv1 >= 0.0) {\n si.mediumType = mat.mediumType;\n si.mediumExtinction = mat.mediumExtinction;\n si.mediumScattering = mat.mediumScattering;\n si.mediumAnisotropy = mat.mediumAnisotropy;\n }\n else {\n si.mediumType = 0;\n si.mediumExtinction = vec3(0.0);\n si.mediumScattering = vec3(0.0);\n si.mediumAnisotropy = 0.0;\n }\n }\n#endif\n}\n`;\n"]}
1
+ {"version":3,"file":"sampleMaterial.glsl.js","sourceRoot":"","sources":["../../../../src/renderer/glsl/chunks/sampleMaterial.glsl.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,iIAAiI;AAEjI,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACvC,eAAe,IAAI,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkRlB,CAAC","sourcesContent":["// Estimate the direct lighting integral using multiple importance sampling\n// http://www.pbr-book.org/3ed-2018/Light_Transport_I_Surface_Reflection/Direct_Lighting.html#EstimatingtheDirectLightingIntegral\n\nimport { glsl } from '../../shader.js';\nexport default glsl`\nvec3 DirectLight(SurfaceInteraction si, OpenPbrResolvedMaterial mat, OpenPbrPreparedBsdf prepared, inout Path path, vec3 ffnormal, bool isSurface) {\n float occluded = 1.0;\n vec3 lightRnd = vec3(sample2D(bounceDim(LIGHT_POSITION)), sample1D(bounceDim(LIGHT_SELECT)));\n\n LightSampleRec lightSample;\n sampleLight(si.position, lightRnd, lightSample, false);\n lightSample.emission = sampling_spectral_rgb_filter(lightSample.emission, pathWavelength);\n\n vec3 lightDir = lightSample.direction;\n vec3 viewDir = -path.ray.d;\n float lightPdf = lightSample.pdf;\n // Opaque surfaces are rendered two-sided by the core renderer. Use the\n // face-forward shading normal here as well, otherwise the early-out rejects\n // every direct-light sample seen from the back of a triangle (for example\n // the inside of an imported room wall).\n float cosThetaL = dot(ffnormal, lightDir);\n#ifdef USE_COAT_NORMAL_FRAMES\n if (isSurface && mat.coatNormalEnabled) { cosThetaL = dot(mat.geometricNormal, lightDir); }\n#endif\n\n if (lightPdf <= 0.0 || max(max(lightSample.emission.x, lightSample.emission.y), lightSample.emission.z) <= 0.0) {\n return vec3(0.0);\n }\n\n float scatteringPdf = 0.0;\n vec3 f = vec3(0.0);\n if (isSurface) {\n if (cosThetaL <= 0.0 && mat.transmissionWeight <= 0.0 && mat.subsurfaceWeight <= 0.0) {\n return vec3(0.0);\n }\n f = openpbr_eval_prepared(prepared, lightDir, scatteringPdf);\n }\n else {\n scatteringPdf = sampling_henyey_greenstein_phase(\n dot(viewDir, lightDir),\n si.mediumAnisotropy\n );\n f = vec3(scatteringPdf);\n }\n\n if (scatteringPdf <= 0.0 || max(max(f.x, f.y), f.z) <= 0.0) {\n return vec3(0.0);\n }\n\n Ray lightRay;\n vec3 shadowOrigin = si.position + EPS * lightDir;\n if (isSurface) {\n const float shadowTerminatorCutoff = 0.1;\n float normalLight = dot(si.normal, lightDir);\n#ifdef USE_COAT_NORMAL_FRAMES\n if (mat.coatNormalEnabled) { normalLight = dot(si.faceNormal, lightDir); }\n#endif\n vec3 geometricNormal = normalLight < 0.0 ? -si.faceNormal : si.faceNormal;\n normalLight = abs(normalLight);\n float geometricLight = dot(geometricNormal, lightDir);\n float offsetAmount = normalLight < shadowTerminatorCutoff\n ? clamp(\n 2.0 - (geometricLight + normalLight) / shadowTerminatorCutoff,\n 0.0,\n 1.0\n )\n : clamp(1.0 - geometricLight / shadowTerminatorCutoff, 0.0, 1.0);\n shadowOrigin += si.shadowOffset * offsetAmount;\n }\n initRay(lightRay, shadowOrigin, lightDir);\n if (intersectSceneShadow(lightRay, lightSample.dist - EPS, si.triangleIndex)) {\n return vec3(0.0);\n }\n\n#ifdef USE_ENVMAP\n // Match the endpoint used by a BSDF-sampled surface transmission, including\n // a separately displayed or grounded background and its coverage.\n if (isSurface && cosThetaL < 0.0 && lightRnd.z < envLightSelectionPmf) {\n vec4 background = sampleBackgroundFromRay(lightRay.o, lightDir);\n lightSample.emission = sampling_spectral_rgb_filter(background.rgb * background.a, pathWavelength);\n }\n#endif\n\n // Delta lights cannot be sampled by the BSDF strategy, so their MIS weight\n // is exactly one even when their light-selection PMF is small.\n float misWeight = lightSample.isDelta\n ? 1.0\n : sampling_power_heuristic(lightPdf, scatteringPdf);\n return misWeight > 0.0\n ? misWeight * lightSample.emission * f / lightPdf\n : vec3(0.0);\n}\n\n#ifdef USE_COAT_NORMAL_FRAMES\nvec3 coat_frame_normal(vec3 inputNormal, vec3 face, vec3 view) {\n bool front = dot(face, view) >= 0.0;\n vec3 ffFace = front ? face : -face;\n vec3 ffInput = front ? inputNormal : -inputNormal;\n if (dot(inputNormal, face) <= 0.0 || dot(ffInput, view) <= 1e-6) { return ffFace; }\n return ffInput;\n}\n#endif\nvoid SampleMaterial(inout SurfaceInteraction si, OpenPbrResolvedMaterial mat, inout Path path) {\n vec3 matRnd = vec3(sample2D(bounceDim(BSDF_DIRECTION)), sample1D(bounceDim(BSDF_LOBE)));\n#ifdef USE_COAT_NORMAL_FRAMES\n vec3 originalFace = si.faceNormal;\n vec3 originalNormal = si.normal;\n#endif\n float ndv1 = -dot(si.faceNormal, path.ray.d);\n float ndv2 = -dot(si.normal, path.ray.d);\n if ((mat.transmissionWeight > 0.0 || mat.subsurfaceWeight > 0.0) && mat.thinWalled) {\n // Always treat thin material as entering medium\n if (ndv1 < 0.0) {\n si.faceNormal = -si.faceNormal;\n ndv1 = -ndv1;\n }\n if (ndv2 < 0.0) {\n si.normal = -si.normal;\n ndv2 = -ndv2;\n }\n }\n // In same edge cases normal is not torwards the camera while we can still see the face.\n // We need to choose faceNormal in this case.\n bool useFaceN = ndv1 >= 0.0 && ndv2 < 0.0;\n float ndv = useFaceN ? ndv1 : ndv2;\n vec3 normal = useFaceN ? si.faceNormal : si.normal;\n\n mat.inside = ndv <= 0.0 && !mat.thinWalled;\n // In or out\n mat.relativeIor = ndv > 0.0 ? (1.0 / mat.specularIor) : mat.specularIor;\n vec3 ffnormal = ndv >= 0.0 ? normal : -normal;\n#ifdef USE_COAT_NORMAL_FRAMES\n if (mat.coatNormalEnabled) {\n vec3 view = -path.ray.d;\n float geometricView = dot(originalFace, view);\n mat.geometricNormal = geometricView >= 0.0 ? originalFace : -originalFace;\n ffnormal = coat_frame_normal(originalNormal, originalFace, view);\n mat.coatNormal = coat_frame_normal(si.coatNormal, originalFace, view);\n mat.inside = geometricView <= 0.0 && !mat.thinWalled;\n mat.relativeIor = (geometricView > 0.0 || mat.thinWalled) ? 1.0 / mat.specularIor : mat.specularIor;\n }\n#endif\n\n\n float scatteringPdf;\n vec3 scatterDir;\n path.scatteringIsDelta = false;\n bool mediumSampled = false;\n bool crossedBoundary = false;\n OpenPbrPreparedBsdf prepared;\n\n#ifdef HAS_MEDIUM\n int mediumType = si.mediumType;\n float d = distance(si.position, path.ray.o);\n vec3 segmentOrigin = path.ray.o;\n vec3 extinction = si.mediumExtinction;\n vec3 scattering = min(si.mediumScattering, extinction);\n float majorant = max(max(extinction.x, extinction.y), extinction.z);\n if (mediumType > 0 && majorant > 0.0) {\n // Sample one RGB extinction channel and divide by the mixture PDF. This\n // is the homogeneous-medium estimator used by PBRT and avoids the very\n // large exp((majorant - extinction) * distance) weights produced by\n // majorant tracking when OpenPBR SSS radii differ strongly by channel.\n int mediumChannel = min(int(sample1D(bounceDim(MEDIUM_CHANNEL)) * 3.0), 2);\n float channelExtinction = extinction[mediumChannel];\n float scatterDist = channelExtinction > 0.0\n ? min(-log(max(sample1D(bounceDim(MEDIUM_DISTANCE)), 1e-7)) / channelExtinction, d)\n : d;\n mediumSampled = scatterDist < d;\n vec3 transmittance = exp(-extinction * scatterDist);\n vec3 density = mediumSampled\n ? extinction * transmittance\n : transmittance;\n float mediumPdf = max(\n (density.x + density.y + density.z) / 3.0,\n 1e-8\n );\n if (mediumSampled) {\n path.beta *= transmittance * scattering / mediumPdf;\n // Move from the start of the segment, not from its end surface.\n path.ray.o = segmentOrigin + scatterDist * path.ray.d;\n si.position = path.ray.o;\n path.li += DirectLight(si, mat, prepared, path, ffnormal, false) * path.beta;\n\n // Pick a new direction based on the phase function\n scatterDir = sampling_henyey_greenstein(\n -path.ray.d,\n si.mediumAnisotropy,\n sample2D(bounceDim(PHASE_DIRECTION))\n );\n scatteringPdf = sampling_henyey_greenstein_phase(\n dot(scatterDir, -path.ray.d),\n si.mediumAnisotropy\n );\n }\n else {\n path.beta *= transmittance / mediumPdf;\n }\n }\n#endif\n\n // Direct lighting\n if (!mediumSampled) {\n path.li += mat.emission * path.beta;\n if (mat.materialType == UNLIT) {\n path.abort = true;\n return;\n }\n vec3 surfaceTangent = vec3(0.0);\n#ifdef USE_TANGENT\n surfaceTangent = si.tangent;\n#endif\n mat.directionTangent = si.directionTangent;\n mat.directionBitangent = si.directionBitangent;\n mat.geometryTangent = si.geometryTangent;\n mat.geometryBitangent = si.geometryBitangent;\n prepared = openpbr_prepare(surfaceTangent, mat, -path.ray.d, ffnormal);\n path.li += DirectLight(si, mat, prepared, path, ffnormal, true) * path.beta;\n // Sample BSDF for color and outgoing direction\n bool isNextRefraction;\n vec3 f = openpbr_sample_prepared(\n prepared,\n matRnd,\n scatterDir,\n scatteringPdf,\n isNextRefraction\n );\n // Null-boundary transmission is discrete and has no NEE competitor.\n path.scatteringIsDelta = !prepared.material.thinWalled &&\n abs(prepared.material.relativeIor - 1.0) <= 1e-6 &&\n prepared.probabilities[OPENPBR_LOBE_TRANSMISSION] >= 1.0 - 1e-6;\n // Match WebGPU: rejected VNDF/refraction proposals have no continuation.\n // Tracing their fallback direction with the incoming throughput invents\n // light paths, especially after total internal reflection inside glass.\n if (!(scatteringPdf > 0.0) || any(isnan(f)) || any(isinf(f)) ||\n dot(scatterDir, scatterDir) < 0.5) {\n path.scatteringPdf = 0.0;\n path.abort = true;\n return;\n }\n path.beta *= f / scatteringPdf;\n crossedBoundary = !mat.thinWalled &&\n isNextRefraction;\n path.isNextRefraction = isNextRefraction;\n // TODO prefer the opaque surface when transmission surface and opaque surface are overlapped.\n // Or the ray go out from transmission material will miss the opque surface.\n path.ray.o = si.position + EPS * scatterDir;\n#ifdef USE_COAT_NORMAL_FRAMES\n if (mat.coatNormalEnabled) { path.ray.o = si.position + EPS * (dot(originalFace, scatterDir) >= 0.0 ? originalFace : -originalFace); }\n#endif\n }\n\n path.scatteringPdf = scatteringPdf;\n initRay(path.ray, path.ray.o, scatterDir);\n if (mediumSampled) {\n path.isNextRefraction = false;\n }\n path.fromEye = false;\n\n#ifdef HAS_MEDIUM\n // A reflected ray stays in its current medium. Only a sampled transmission\n // event crosses the boundary of a medium-bearing closed mesh.\n if (!mediumSampled && crossedBoundary && mat.mediumType > 0) {\n if (ndv1 >= 0.0) {\n si.mediumType = mat.mediumType;\n si.mediumExtinction = mat.mediumExtinction;\n si.mediumScattering = mat.mediumScattering;\n si.mediumAnisotropy = mat.mediumAnisotropy;\n }\n else {\n si.mediumType = 0;\n si.mediumExtinction = vec3(0.0);\n si.mediumScattering = vec3(0.0);\n si.mediumAnisotropy = 0.0;\n }\n }\n#endif\n}\n`;\n"]}
@@ -11,33 +11,33 @@ export default glsl `
11
11
 
12
12
  const uint SHADOW_CATCHER_LIGHT_SAMPLES = 4u;
13
13
 
14
- uint ko(uint candidate, uint slot) {
14
+ uint ky(uint candidate, uint slot) {
15
15
  return candidate == 0u ? cw(slot) : cw(9u + (candidate - 1u) * 3u + slot);
16
16
  }
17
17
 
18
18
  void sampleShadowCatcher(ad si, int bounce, inout Path aa) {
19
- vec3 oK = -aa.ray.d;
19
+ vec3 oS = -aa.ray.d;
20
20
 
21
21
  #if defined(NUM_LIGHTS) || defined(USE_ENVMAP)
22
22
  float visibility = 0.0;
23
23
  for (uint candidate = 0u; candidate < SHADOW_CATCHER_LIGHT_SAMPLES; candidate++) {
24
24
  LightSampleRec lightSample;
25
- vec3 lc = vec3(
26
- fk(ko(candidate, LIGHT_POSITION)),
27
- dz(ko(candidate, LIGHT_SELECT))
25
+ vec3 ln = vec3(
26
+ fp(ky(candidate, LIGHT_POSITION)),
27
+ dz(ky(candidate, LIGHT_SELECT))
28
28
  );
29
- sampleLight(si.position, lc, lightSample, false);
29
+ sampleLight(si.position, ln, lightSample, false);
30
30
 
31
31
  vec3 lightDir = lightSample.direction;
32
32
  float cosThetaL = dot(si.normal, lightDir);
33
- float pv = dot(si.normal, oK) * cosThetaL;
34
- bool mt = false;
35
- if (pv >= 0.0) {
33
+ float pM = dot(si.normal, oS) * cosThetaL;
34
+ bool mC = false;
35
+ if (pM >= 0.0) {
36
36
  Ray ray;
37
- iw(ray, si.position + EPS * lightDir, lightDir);
38
- mt = ex(ray, lightSample.dist - EPS, si.triangleIndex);
37
+ iC(ray, si.position + EPS * lightDir, lightDir);
38
+ mC = ex(ray, lightSample.dist - EPS, si.triangleIndex);
39
39
  }
40
- visibility += mt ? 0.0 : 1.0;
40
+ visibility += mC ? 0.0 : 1.0;
41
41
  }
42
42
 
43
43
  aa.alpha = visibility / float(SHADOW_CATCHER_LIGHT_SAMPLES);
@@ -5,70 +5,70 @@ export default glsl `
5
5
 
6
6
 
7
7
  vec3 aQ(vec3 view, vec2 alpha, vec2 samplePoint) {
8
- vec3 rc = vec3(alpha, 1.0);
9
- vec3 gf = normalize(rc * view);
10
- float ua = min(gf.z, 1.0);
11
- float qH = 1.0 + ua;
12
- float qX = (1.0 - samplePoint.y) * qH;
13
- float rJ = samplePoint.y * qH;
14
- float sA = qX + (1.0 - ua);
15
- float fi = sqrt(max(0.0, sA * rJ));
8
+ vec3 rm = vec3(alpha, 1.0);
9
+ vec3 gk = normalize(rm * view);
10
+ float uh = min(gk.z, 1.0);
11
+ float qQ = 1.0 + uh;
12
+ float rh = (1.0 - samplePoint.y) * qQ;
13
+ float rR = samplePoint.y * qQ;
14
+ float sI = rh + (1.0 - uh);
15
+ float fl = sqrt(max(0.0, sI * rR));
16
16
  float br = TWOPI * samplePoint.x;
17
- vec3 lw = vec3(
18
- gf.x + fi * cos(br),
19
- gf.y + fi * sin(br),
20
- qX
17
+ vec3 lI = vec3(
18
+ gk.x + fl * cos(br),
19
+ gk.y + fl * sin(br),
20
+ rh
21
21
  );
22
- return normalize(rc * lw);
22
+ return normalize(rm * lI);
23
23
  }
24
24
 
25
- float gG(vec3 od, vec2 alpha) {
26
- vec3 hm = vec3(
27
- od.x / alpha.x,
28
- od.y / alpha.y,
29
- od.z
25
+ float gL(vec3 oo, vec2 alpha) {
26
+ vec3 hr = vec3(
27
+ oo.x / alpha.x,
28
+ oo.y / alpha.y,
29
+ oo.z
30
30
  );
31
- float ap = dot(hm, hm);
31
+ float ap = dot(hr, hr);
32
32
  return 1.0 / (
33
33
  PI * alpha.x * alpha.y * ap * ap
34
34
  );
35
35
  }
36
36
 
37
37
  float bk(vec3 direction, vec2 alpha) {
38
- float eE = abs(direction.z);
39
- if (eE <= 1e-8) {
38
+ float eF = abs(direction.z);
39
+ if (eF <= 1e-8) {
40
40
  return 0.0;
41
41
  }
42
- vec2 hY = alpha * direction.xy;
43
- float lA = dot(hY, hY)
44
- / (eE * eE);
45
- return 2.0 / (1.0 + sqrt(1.0 + lA));
42
+ vec2 ic = alpha * direction.xy;
43
+ float lJ = dot(ic, ic)
44
+ / (eF * eF);
45
+ return 2.0 / (1.0 + sqrt(1.0 + lJ));
46
46
  }
47
47
 
48
48
  float aE(float au) {
49
- float dg = clamp(1.0 - au, 0.0, 1.0);
50
- return pow(dg, 5.0);
49
+ float di = clamp(1.0 - au, 0.0, 1.0);
50
+ return pow(di, 5.0);
51
51
  }
52
52
 
53
53
  float cu(float L, float cJ) {
54
- float iu = clamp(abs(L), 0.0, 1.0);
55
- float ke = cJ * cJ
56
- * max(0.0, 1.0 - iu * iu);
57
- if (ke >= 1.0) {
54
+ float iA = clamp(abs(L), 0.0, 1.0);
55
+ float kl = cJ * cJ
56
+ * max(0.0, 1.0 - iA * iA);
57
+ if (kl >= 1.0) {
58
58
  return 1.0;
59
59
  }
60
60
 
61
- float lK = sqrt(max(0.0, 1.0 - ke));
62
- float ba = (iu - cJ * lK)
63
- / max(iu + cJ * lK, 1e-8);
64
- float pw = (cJ * iu - lK)
65
- / max(cJ * iu + lK, 1e-8);
61
+ float lT = sqrt(max(0.0, 1.0 - kl));
62
+ float ba = (iA - cJ * lT)
63
+ / max(iA + cJ * lT, 1e-8);
64
+ float pN = (cJ * iA - lT)
65
+ / max(cJ * iA + lT, 1e-8);
66
66
  return 0.5 * (
67
- ba * ba + pw * pw
67
+ ba * ba + pN * pN
68
68
  );
69
69
  }
70
70
 
71
- vec2 gd(vec2 samplePoint) {
71
+ vec2 gi(vec2 samplePoint) {
72
72
  vec2 offset = 2.0 * samplePoint - vec2(1.0);
73
73
  if (offset.x == 0.0 && offset.y == 0.0) {
74
74
  return vec2(0.0);
@@ -88,35 +88,35 @@ return radius * vec2(cos(angle), sin(angle));
88
88
  }
89
89
 
90
90
  vec3 bi(vec2 samplePoint) {
91
- vec2 kx = gd(samplePoint);
91
+ vec2 kF = gi(samplePoint);
92
92
  return vec3(
93
- kx,
94
- sqrt(max(0.0, 1.0 - dot(kx, kx)))
93
+ kF,
94
+ sqrt(max(0.0, 1.0 - dot(kF, kF)))
95
95
  );
96
96
  }
97
97
 
98
- float aG(float pi, float nD) {
99
- float scale = max(pi, nD);
98
+ float aG(float pr, float nN) {
99
+ float scale = max(pr, nN);
100
100
  if (scale <= 0.0) {
101
101
  return 0.0;
102
102
  }
103
- vec2 normalized = vec2(pi, nD) / scale;
104
- vec2 oG = normalized * normalized;
105
- return oG.x / (oG.x + oG.y);
103
+ vec2 normalized = vec2(pr, nN) / scale;
104
+ vec2 oO = normalized * normalized;
105
+ return oO.x / (oO.x + oO.y);
106
106
  }
107
107
 
108
108
  void aL(in vec3 normal, out vec3 tangent, out vec3 bitangent) {
109
- float ie = normal.z >= 0.0 ? 1.0 : -1.0;
110
- float dW = -1.0 / (ie + normal.z);
109
+ float ik = normal.z >= 0.0 ? 1.0 : -1.0;
110
+ float dW = -1.0 / (ik + normal.z);
111
111
  float xy = normal.x * normal.y * dW;
112
112
  tangent = vec3(
113
- 1.0 + ie * normal.x * normal.x * dW,
114
- ie * xy,
115
- -ie * normal.x
113
+ 1.0 + ik * normal.x * normal.x * dW,
114
+ ik * xy,
115
+ -ik * normal.x
116
116
  );
117
117
  bitangent = vec3(
118
118
  xy,
119
- ie + normal.y * normal.y * dW,
119
+ ik + normal.y * normal.y * dW,
120
120
  -normal.y
121
121
  );
122
122
  }
@@ -125,40 +125,40 @@ vec3 ai(vec3 rgb, float wavelength) {
125
125
  if (wavelength == 0.0) {
126
126
  return rgb;
127
127
  }
128
- vec3 tG = wavelength > 600.0
128
+ vec3 tN = wavelength > 600.0
129
129
  ? vec3(1.0, 0.0, 0.0)
130
130
  : wavelength > 500.0
131
131
  ? vec3(0.0, 1.0, 0.0)
132
132
  : vec3(0.0, 0.0, 1.0);
133
- return rgb * tG;
133
+ return rgb * tN;
134
134
  }
135
135
 
136
- float eK(
136
+ float eN(
137
137
  float wavelength,
138
- float hb,
139
- float hk,
140
- float qk
138
+ float hh,
139
+ float hp,
140
+ float qs
141
141
  ) {
142
- if (wavelength == 0.0 || hk <= 0.0) {
143
- return hb;
142
+ if (wavelength == 0.0 || hp <= 0.0) {
143
+ return hh;
144
144
  }
145
145
 
146
146
  const float FRAUNHOFER_C = 656.3;
147
147
  const float FRAUNHOFER_D = 587.6;
148
148
  const float FRAUNHOFER_F = 486.1;
149
- float jK = 1.0 / (
149
+ float jR = 1.0 / (
150
150
  1.0 / (FRAUNHOFER_F * FRAUNHOFER_F)
151
151
  - 1.0 / (FRAUNHOFER_C * FRAUNHOFER_C)
152
152
  );
153
- float mT = max(qk / hk, 1e-6);
154
- float qI = (hb - 1.0) * jK / mT;
155
- float td = hb
156
- - qI / (FRAUNHOFER_D * FRAUNHOFER_D);
157
- return td + qI / (wavelength * wavelength);
153
+ float ng = max(qs / hp, 1e-6);
154
+ float qR = (hh - 1.0) * jR / ng;
155
+ float tl = hh
156
+ - qR / (FRAUNHOFER_D * FRAUNHOFER_D);
157
+ return tl + qR / (wavelength * wavelength);
158
158
  }
159
159
 
160
- vec3 fl(
161
- vec3 gu,
160
+ vec3 fq(
161
+ vec3 gz,
162
162
  float anisotropy,
163
163
  vec2 samplePoint
164
164
  ) {
@@ -167,21 +167,21 @@ if (abs(anisotropy) < 0.001) {
167
167
  au = 1.0 - 2.0 * samplePoint.y;
168
168
  }
169
169
  else {
170
- float iV = (1.0 - anisotropy * anisotropy)
170
+ float ja = (1.0 - anisotropy * anisotropy)
171
171
  / (1.0 + anisotropy - 2.0 * anisotropy * samplePoint.y);
172
172
  au = (
173
- iV * iV - 1.0 - anisotropy * anisotropy
173
+ ja * ja - 1.0 - anisotropy * anisotropy
174
174
  ) / (2.0 * anisotropy);
175
175
  }
176
176
 
177
- float tW = sqrt(max(0.0, 1.0 - au * au));
177
+ float ud = sqrt(max(0.0, 1.0 - au * au));
178
178
  float br = TWOPI * samplePoint.x;
179
179
  vec3 tangent;
180
180
  vec3 bitangent;
181
- aL(gu, tangent, bitangent);
182
- return tangent * (tW * cos(br))
183
- + bitangent * (tW * sin(br))
184
- + gu * au;
181
+ aL(gz, tangent, bitangent);
182
+ return tangent * (ud * cos(br))
183
+ + bitangent * (ud * sin(br))
184
+ + gz * au;
185
185
  }
186
186
 
187
187
  float bD(float au, float anisotropy) {
@@ -28,8 +28,8 @@ uvec2 bc;
28
28
  uint bd;
29
29
  uint cF = 0u;
30
30
  uint em = 0u;
31
- uint eg(uint kk) {
32
- uint x = kk;
31
+ uint eg(uint kt) {
32
+ uint x = kt;
33
33
  x ^= x >> 16u; x *= 0x7feb352du;
34
34
  x ^= x >> 15u; x *= 0x846ca68bu;
35
35
  return x ^ (x >> 16u);
@@ -37,28 +37,28 @@ return x ^ (x >> 16u);
37
37
  uint aq(uint a, uint b) {
38
38
  return eg(a ^ eg(b + 0x9e3779b9u));
39
39
  }
40
- uint iA(uint kk, uint ic) {
41
- uint x = kk + ic;
40
+ uint iE(uint kt, uint ij) {
41
+ uint x = kt + ij;
42
42
  x ^= x * 0x6c50b47cu; x ^= x * 0xb82f1e52u;
43
43
  x ^= x * 0xc7afe638u; x ^= x * 0x8d22f6e6u;
44
44
  return x;
45
45
  }
46
- uint sC(uint x, uint ic) {
47
- return reverseBits(iA(reverseBits(x), ic));
46
+ uint sK(uint x, uint ij) {
47
+ return reverseBits(iE(reverseBits(x), ij));
48
48
  }
49
49
 
50
- uint rb(uint kk) {
51
- uint r = reverseBits(kk);
50
+ uint rl(uint kt) {
51
+ uint r = reverseBits(kt);
52
52
  ${sobolD1Steps.map(([shift, mask]) => `r ^= (r << ${shift}u) & 0x${mask.toString(16)}u;`).join("\n ")}
53
53
  return r;
54
54
  }
55
- vec2 vI(uint index, uint ic) {
56
- uint i = sC(index, aq(ic, 0u));
57
- uint x = reverseBits(iA(i, aq(ic, 1u)));
58
- uint y = sC(rb(i), aq(ic, 2u));
55
+ vec2 vP(uint index, uint ij) {
56
+ uint i = sK(index, aq(ij, 0u));
57
+ uint x = reverseBits(iE(i, aq(ij, 1u)));
58
+ uint y = sK(rl(i), aq(ij, 2u));
59
59
  return vec2(float(x >> 8u), float(y >> 8u)) * (1.0 / 16777216.0);
60
60
  }
61
- uint tp(uvec2 p) {
61
+ uint tB(uvec2 p) {
62
62
  uvec2 v = p & uvec2(255u);
63
63
  v = (v | (v << uvec2(4u))) & uvec2(0x0f0fu);
64
64
  v = (v | (v << uvec2(2u))) & uvec2(0x3333u);
@@ -66,27 +66,27 @@ v = (v | (v << uvec2(1u))) & uvec2(0x5555u);
66
66
  return v.x | (v.y << 1u);
67
67
  }
68
68
  ${zSobolPackedPermutations.map((v, i) => `const uint Z_PERM_${i} = ${v}u;`).join("\n")}
69
- uint km(uint tu) {
70
- uint group = tu >> 2u;
69
+ uint kw(uint tE) {
70
+ uint group = tE >> 2u;
71
71
  uint word = Z_PERM_5;
72
72
  ${[0, 1, 2, 3, 4].map(i => `word = group == ${i}u ? Z_PERM_${i} : word;`).join("\n ")}
73
- return (word >> ((tu & 3u) * 8u)) & 255u;
73
+ return (word >> ((tE & 3u) * 8u)) & 255u;
74
74
  }
75
- uint pO(uint kE, uint dim, uint logSPP) {
75
+ uint pW(uint kN, uint dim, uint logSPP) {
76
76
  uint odd = logSPP & 1u;
77
- uint uf = 8u + ((logSPP + 1u) >> 1u);
77
+ uint um = 8u + ((logSPP + 1u) >> 1u);
78
78
  uint result = 0u;
79
- for (int digit = int(uf) - 1; digit >= int(odd); digit--) {
79
+ for (int digit = int(um) - 1; digit >= int(odd); digit--) {
80
80
  uint shift = 2u*uint(digit) - odd;
81
81
 
82
- uint sj = 0u;
83
- if (shift < 30u) { sj = kE >> (shift + 2u); }
84
- uint tu = (eg(sj ^ (0x55555555u * dim)) >> 24u) % 24u;
85
- uint d = (kE >> shift) & 3u;
86
- result |= ((km(tu) >> (2u*d)) & 3u) << shift;
82
+ uint st = 0u;
83
+ if (shift < 30u) { st = kN >> (shift + 2u); }
84
+ uint tE = (eg(st ^ (0x55555555u * dim)) >> 24u) % 24u;
85
+ uint d = (kN >> shift) & 3u;
86
+ result |= ((kw(tE) >> (2u*d)) & 3u) << shift;
87
87
  }
88
88
  if (odd != 0u) {
89
- result |= (kE & 1u) ^ (eg((kE >> 1u) ^ (0x55555555u * dim)) & 1u);
89
+ result |= (kN & 1u) ^ (eg((kN >> 1u) ^ (0x55555555u * dim)) & 1u);
90
90
  }
91
91
  return result;
92
92
  }
@@ -97,62 +97,62 @@ uint cw(uint slot) {
97
97
  return CAMERA_BEVEL_BASE + uint(BEVEL_SAMPLES) + cF * BOUNCE_STRIDE + slot;
98
98
  }
99
99
 
100
- uvec4 hh;
101
- uint hi;
102
- bool fv = false;
103
- bool df = false;
104
- uint dE;
105
- uint gq;
106
- vec2 eN;
100
+ uvec4 hl;
101
+ uint hm;
102
+ bool fC = false;
103
+ bool dg = false;
104
+ uint dF;
105
+ uint gv;
106
+ vec2 eQ;
107
107
  void dw(uint dim) {
108
108
 
109
- uint jW = bc.x + bc.y * uint(round(1.0 / pixelSize.x));
110
- uvec4 key = uvec4(dim, bd, jW, uint(sequenceSeed));
111
- if (fv && all(equal(hh, key)) && hi == uint(zSobolLogSPP)) { return; }
112
- hh = key; hi = uint(zSobolLogSPP);
113
- fv = true; df = false;
114
- uint ic = aq(aq(jW, dim), uint(sequenceSeed));
109
+ uint kd = bc.x + bc.y * uint(round(1.0 / pixelSize.x));
110
+ uvec4 key = uvec4(dim, bd, kd, uint(sequenceSeed));
111
+ if (fC && all(equal(hl, key)) && hm == uint(zSobolLogSPP)) { return; }
112
+ hl = key; hm = uint(zSobolLogSPP);
113
+ fC = true; dg = false;
114
+ uint ij = aq(aq(kd, dim), uint(sequenceSeed));
115
115
  uint index = bd;
116
116
  if (samplingPattern == 1) {
117
117
  uint logSPP = uint(zSobolLogSPP);
118
118
  if (index == 0u) { logSPP = 0u; }
119
119
  else { index -= 1u; }
120
120
 
121
- uint iW = index >> logSPP;
121
+ uint jb = index >> logSPP;
122
122
  uint mask = (1u << logSPP) - 1u;
123
- uint kE = (tp(bc) << logSPP) | (index & mask);
124
- index = pO(kE, dim, logSPP);
123
+ uint kN = (tB(bc) << logSPP) | (index & mask);
124
+ index = pW(kN, dim, logSPP);
125
125
  uvec2 tile = bc >> uvec2(8u);
126
- ic = aq(aq(dim, uint(sequenceSeed)), aq(tile.x, tile.y));
126
+ ij = aq(aq(dim, uint(sequenceSeed)), aq(tile.x, tile.y));
127
127
 
128
- if (bd != 0u) { iW += 1u; }
129
- ic = aq(ic, iW);
128
+ if (bd != 0u) { jb += 1u; }
129
+ ij = aq(ij, jb);
130
130
  }
131
- dE = sC(index, aq(ic, 0u));
132
- gq = ic;
133
- uint x = reverseBits(iA(dE, aq(ic, 1u)));
134
- eN.x = float(x >> 8u) * (1.0 / 16777216.0);
131
+ dF = sK(index, aq(ij, 0u));
132
+ gv = ij;
133
+ uint x = reverseBits(iE(dF, aq(ij, 1u)));
134
+ eQ.x = float(x >> 8u) * (1.0 / 16777216.0);
135
135
  }
136
- vec2 kJ(uint dim) {
136
+ vec2 kS(uint dim) {
137
137
  dw(dim);
138
- if (!df) {
139
- uint y = sC(rb(dE), aq(gq, 2u));
140
- eN.y = float(y >> 8u) * (1.0 / 16777216.0);
141
- df = true;
138
+ if (!dg) {
139
+ uint y = sK(rl(dF), aq(gv, 2u));
140
+ eQ.y = float(y >> 8u) * (1.0 / 16777216.0);
141
+ dg = true;
142
142
  }
143
- return EPS + (1.0 - 2.0*EPS) * eN;
143
+ return EPS + (1.0 - 2.0*EPS) * eQ;
144
144
  }
145
145
  float dz(uint dim) {
146
146
  if (samplingPattern == 2) { return EPS + (1.0 - 2.0*EPS)*rand(); }
147
147
  dw(dim);
148
- return EPS + (1.0 - 2.0*EPS) * eN.x;
148
+ return EPS + (1.0 - 2.0*EPS) * eQ.x;
149
149
  }
150
- vec2 fk(uint dim) {
150
+ vec2 fp(uint dim) {
151
151
  if (samplingPattern == 2) {
152
152
  float x = dz(dim); float y = dz(dim);
153
153
  return vec2(x,y);
154
154
  }
155
- return kJ(dim);
155
+ return kS(dim);
156
156
  }
157
157
 
158
158
  float eo(uint slot) {
@@ -160,10 +160,10 @@ uint dim = aq(aq(cF, slot), em) | 0x80000000u;
160
160
  em += 1u;
161
161
  if (samplingPattern == 2) { return EPS + (1.0 - 2.0*EPS)*rand(); }
162
162
 
163
- uint jW = bc.x + bc.y * uint(round(1.0 / pixelSize.x));
164
- uint ic = aq(aq(jW, dim), uint(sequenceSeed));
165
- uint i = sC(bd, aq(ic, 0u));
166
- uint x = reverseBits(iA(i, aq(ic, 1u)));
163
+ uint kd = bc.x + bc.y * uint(round(1.0 / pixelSize.x));
164
+ uint ij = aq(aq(kd, dim), uint(sequenceSeed));
165
+ uint i = sK(bd, aq(ij, 0u));
166
+ uint x = reverseBits(iE(i, aq(ij, 1u)));
167
167
  return EPS + (1.0 - 2.0*EPS) * (float(x >> 8u) * (1.0 / 16777216.0));
168
168
  }
169
169
  `;
@@ -9,16 +9,16 @@ vec4 textureLinear(sampler2D map, vec2 uv) {
9
9
  return texture(map, uv);
10
10
  #else
11
11
  vec2 size = vec2(textureSize(map, 0));
12
- vec2 pS = 1.0 / size;
12
+ vec2 qa = 1.0 / size;
13
13
 
14
14
  uv = uv * size - 0.5;
15
15
  vec2 f = fract(uv);
16
16
  uv = floor(uv) + 0.5;
17
17
 
18
- vec4 s1 = texture(map, (uv + vec2(0, 0)) * pS);
19
- vec4 s2 = texture(map, (uv + vec2(1, 0)) * pS);
20
- vec4 s3 = texture(map, (uv + vec2(0, 1)) * pS);
21
- vec4 s4 = texture(map, (uv + vec2(1, 1)) * pS);
18
+ vec4 s1 = texture(map, (uv + vec2(0, 0)) * qa);
19
+ vec4 s2 = texture(map, (uv + vec2(1, 0)) * qa);
20
+ vec4 s3 = texture(map, (uv + vec2(0, 1)) * qa);
21
+ vec4 s4 = texture(map, (uv + vec2(1, 1)) * qa);
22
22
 
23
23
  return mix(mix(s1, s2, f.x), mix(s3, s4, f.x), f.y);
24
24
  #endif
@@ -8,12 +8,12 @@ float phi = acos(n.y) / PI;
8
8
  return vec2(theta, 1.0 - phi);
9
9
  }
10
10
 
11
- vec2 iM(vec3 pos, vec3 normal, vec2 uvScale) {
12
- vec3 dm = abs(normal);
11
+ vec2 iR(vec3 pos, vec3 normal, vec2 uvScale) {
12
+ vec3 dn = abs(normal);
13
13
  vec2 uv = vec2(0.0);
14
- if (dm.x > dm.y && dm.x > dm.z) {
14
+ if (dn.x > dn.y && dn.x > dn.z) {
15
15
  uv = pos.yz;
16
- } else if (dm.y > dm.x && dm.y > dm.z) {
16
+ } else if (dn.y > dn.x && dn.y > dn.z) {
17
17
  uv = pos.xz;
18
18
  } else {
19
19
  uv = pos.xy;
@@ -53,18 +53,18 @@ return fract(uv * uvScale);
53
53
 
54
54
 
55
55
 
56
- vec2 hz(vec3 pos, vec3 normal) {
56
+ vec2 hD(vec3 pos, vec3 normal) {
57
57
  float theta = atan(pos.z, pos.x) / (2.0 * PI) + 0.5;
58
58
  return vec2(theta, pos.y);
59
59
  }
60
60
 
61
- vec2 gC(int fh, vec3 pos, vec3 normal, vec2 uvScale) {
62
- if (fh == ${uvProjectionConstants.triplanar + ''}) {
63
- return iM(pos, normal, uvScale);
64
- } else if (fh == ${uvProjectionConstants.spherical + ''}) {
61
+ vec2 gI(int fk, vec3 pos, vec3 normal, vec2 uvScale) {
62
+ if (fk == ${uvProjectionConstants.triplanar + ''}) {
63
+ return iR(pos, normal, uvScale);
64
+ } else if (fk == ${uvProjectionConstants.spherical + ''}) {
65
65
  return sphericalProjection(pos) * uvScale;
66
- } else if (fh == ${uvProjectionConstants.cylindrical + ''}) {
67
- return hz(pos, normal) * uvScale;
66
+ } else if (fk == ${uvProjectionConstants.cylindrical + ''}) {
67
+ return hD(pos, normal) * uvScale;
68
68
  }
69
69
  return vec2(0.0);
70
70
  }
@@ -33,18 +33,18 @@ if (any(lessThan(uv, vec2(0.0))) || any(greaterThan(uv, vec2(1.0)))) return;
33
33
  vec4 origin = viewProjectionInv * vec4(uv * 2.0 - 1.0, -1.0, 1.0);
34
34
  vec4 target = viewProjectionInv * vec4(uv * 2.0 - 1.0, 1.0, 1.0);
35
35
  Ray ray;
36
- iw(ray, origin.xyz / origin.w, normalize(target.xyz * origin.w - origin.xyz * target.w));
36
+ iC(ray, origin.xyz / origin.w, normalize(target.xyz * origin.w - origin.xyz * target.w));
37
37
  vec3 eye = viewInv[3].xyz;
38
- vec3 nY = -normalize(viewInv[2].xyz);
38
+ vec3 oj = -normalize(viewInv[2].xyz);
39
39
  ad si;
40
40
  si.triangleIndex = -1;
41
41
  for (int layer = 0; layer < 32; layer++) {
42
- cY(ray, si, false);
42
+ cZ(ray, si, false);
43
43
  if (!si.hit) return;
44
44
  J material;
45
- eT(material, si.materialIndex, si.uv, si.uv1, si.instanceIndex);
45
+ eX(material, si.materialIndex, si.uv, si.uv1, si.instanceIndex, si.vertexColor);
46
46
  if (material.materialType != SHADOW_CATCHER && material.alpha > 0.0) {
47
- out_depth.r = max(dot(si.position - eye, nY), 0.0);
47
+ out_depth.r = max(dot(si.position - eye, oj), 0.0);
48
48
  return;
49
49
  }
50
50
  ray.o = si.position + ray.d * (EPS * 0.02);
@@ -1 +1 @@
1
- {"version":3,"file":"depthQuery.frag.js","sourceRoot":"","sources":["../../../src/renderer/glsl/depthQuery.frag.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,MAAM,MAAM,yBAAyB,CAAC;AAC7C,OAAO,IAAI,MAAM,+BAA+B,CAAC;AACjD,OAAO,SAAS,MAAM,iCAAiC,CAAC;AACxD,OAAO,SAAS,MAAM,4BAA4B,CAAC;AACnD,OAAO,YAAY,MAAM,+BAA+B,CAAC;AACzD,OAAO,MAAM,MAAM,yBAAyB,CAAC;AAC7C,OAAO,IAAI,MAAM,uBAAuB,CAAC;AAEzC,eAAe,IAAI,cAAc,CAAC;IAChC,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC,OAAO,CAAC;IACtC,OAAO,EAAE,EAAE,gBAAgB,EAAE,IAAI,EAAE;IACnC,QAAQ,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,CAAC;IAC9C,QAAQ,EAAE;QACR,SAAS,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;QACjC,iBAAiB,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;QACzC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;KAChC;IACD,IAAI,EAAE,UAAU,CAAC;EACjB,MAAM;EACN,IAAI;EACJ,MAAM,CAAC,IAAI;EACX,IAAI,CAAC,IAAI;EACT,YAAY;EACZ,SAAS,CAAC,IAAI;EACd,SAAS,CAAC,IAAI;;;yCAG2B,iBAAiB,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;CAwB/D;CACA,CAAC,CAAC","sourcesContent":["import { FragmentShader, Shader } from '../shader.js';\nimport { DEPTH_SAMPLE_GRID } from '../depthQuery.js';\nimport common from './chunks/common.glsl.js';\nimport core from './chunks/rayTraceCore.glsl.js';\nimport materials from './chunks/materialBuffer.glsl.js';\nimport intersect from './chunks/intersect.glsl.js';\nimport uvProjection from './chunks/uvProjection.glsl.js';\nimport random from './chunks/random.glsl.js';\nimport rand from './chunks/rand.glsl.js';\n\nexport default new FragmentShader({\n name: 'depthQuery', outputs: ['depth'],\n defines: { DEPTH_QUERY_MODE: true },\n includes: [core, materials, intersect, random],\n uniforms: {\n depthArea: Shader.uniform('vec4'),\n viewProjectionInv: Shader.uniform('mat4'),\n viewInv: Shader.uniform('mat4')\n },\n main: /* glsl */ `\n${common}\n${rand}\n${random.main}\n${core.main}\n${uvProjection}\n${materials.main}\n${intersect.main}\n\nvoid main() {\n vec2 offset = floor(gl_FragCoord.xy) / ${DEPTH_SAMPLE_GRID - 1}.0 * 2.0 - 1.0;\n vec2 uv = depthArea.xy + depthArea.zw * offset * vec2(1.0, -1.0);\n out_depth = vec4(0.0);\n if (any(lessThan(uv, vec2(0.0))) || any(greaterThan(uv, vec2(1.0)))) return;\n vec4 origin = viewProjectionInv * vec4(uv * 2.0 - 1.0, -1.0, 1.0);\n vec4 target = viewProjectionInv * vec4(uv * 2.0 - 1.0, 1.0, 1.0);\n Ray ray;\n initRay(ray, origin.xyz / origin.w, normalize(target.xyz * origin.w - origin.xyz * target.w));\n vec3 eye = viewInv[3].xyz;\n vec3 forward = -normalize(viewInv[2].xyz);\n SurfaceInteraction si;\n si.triangleIndex = -1;\n for (int layer = 0; layer < 32; layer++) {\n intersectScene(ray, si, false);\n if (!si.hit) return;\n OpenPbrResolvedMaterial material;\n getMaterial(material, si.materialIndex, si.uv, si.uv1, si.instanceIndex);\n if (material.materialType != SHADOW_CATCHER && material.alpha > 0.0) {\n out_depth.r = max(dot(si.position - eye, forward), 0.0);\n return;\n }\n ray.o = si.position + ray.d * (EPS * 0.02);\n }\n}\n`\n});\n"]}
1
+ {"version":3,"file":"depthQuery.frag.js","sourceRoot":"","sources":["../../../src/renderer/glsl/depthQuery.frag.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,MAAM,MAAM,yBAAyB,CAAC;AAC7C,OAAO,IAAI,MAAM,+BAA+B,CAAC;AACjD,OAAO,SAAS,MAAM,iCAAiC,CAAC;AACxD,OAAO,SAAS,MAAM,4BAA4B,CAAC;AACnD,OAAO,YAAY,MAAM,+BAA+B,CAAC;AACzD,OAAO,MAAM,MAAM,yBAAyB,CAAC;AAC7C,OAAO,IAAI,MAAM,uBAAuB,CAAC;AAEzC,eAAe,IAAI,cAAc,CAAC;IAChC,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC,OAAO,CAAC;IACtC,OAAO,EAAE,EAAE,gBAAgB,EAAE,IAAI,EAAE;IACnC,QAAQ,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,CAAC;IAC9C,QAAQ,EAAE;QACR,SAAS,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;QACjC,iBAAiB,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;QACzC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;KAChC;IACD,IAAI,EAAE,UAAU,CAAC;EACjB,MAAM;EACN,IAAI;EACJ,MAAM,CAAC,IAAI;EACX,IAAI,CAAC,IAAI;EACT,YAAY;EACZ,SAAS,CAAC,IAAI;EACd,SAAS,CAAC,IAAI;;;yCAG2B,iBAAiB,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;CAwB/D;CACA,CAAC,CAAC","sourcesContent":["import { FragmentShader, Shader } from '../shader.js';\nimport { DEPTH_SAMPLE_GRID } from '../depthQuery.js';\nimport common from './chunks/common.glsl.js';\nimport core from './chunks/rayTraceCore.glsl.js';\nimport materials from './chunks/materialBuffer.glsl.js';\nimport intersect from './chunks/intersect.glsl.js';\nimport uvProjection from './chunks/uvProjection.glsl.js';\nimport random from './chunks/random.glsl.js';\nimport rand from './chunks/rand.glsl.js';\n\nexport default new FragmentShader({\n name: 'depthQuery', outputs: ['depth'],\n defines: { DEPTH_QUERY_MODE: true },\n includes: [core, materials, intersect, random],\n uniforms: {\n depthArea: Shader.uniform('vec4'),\n viewProjectionInv: Shader.uniform('mat4'),\n viewInv: Shader.uniform('mat4')\n },\n main: /* glsl */ `\n${common}\n${rand}\n${random.main}\n${core.main}\n${uvProjection}\n${materials.main}\n${intersect.main}\n\nvoid main() {\n vec2 offset = floor(gl_FragCoord.xy) / ${DEPTH_SAMPLE_GRID - 1}.0 * 2.0 - 1.0;\n vec2 uv = depthArea.xy + depthArea.zw * offset * vec2(1.0, -1.0);\n out_depth = vec4(0.0);\n if (any(lessThan(uv, vec2(0.0))) || any(greaterThan(uv, vec2(1.0)))) return;\n vec4 origin = viewProjectionInv * vec4(uv * 2.0 - 1.0, -1.0, 1.0);\n vec4 target = viewProjectionInv * vec4(uv * 2.0 - 1.0, 1.0, 1.0);\n Ray ray;\n initRay(ray, origin.xyz / origin.w, normalize(target.xyz * origin.w - origin.xyz * target.w));\n vec3 eye = viewInv[3].xyz;\n vec3 forward = -normalize(viewInv[2].xyz);\n SurfaceInteraction si;\n si.triangleIndex = -1;\n for (int layer = 0; layer < 32; layer++) {\n intersectScene(ray, si, false);\n if (!si.hit) return;\n OpenPbrResolvedMaterial material;\n getMaterial(material, si.materialIndex, si.uv, si.uv1, si.instanceIndex, si.vertexColor);\n if (material.materialType != SHADOW_CATCHER && material.alpha > 0.0) {\n out_depth.r = max(dot(si.position - eye, forward), 0.0);\n return;\n }\n ray.o = si.position + ray.d * (EPS * 0.02);\n }\n}\n`\n});\n"]}