@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
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"causticEmission.js","sourceRoot":"","sources":["../../src/renderer/causticEmission.ts"],"names":[],"mappings":"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","sourcesContent":["import type {AnalyticLightState} from '../scene/lightState.js';\nimport {buildLightAliasTable,colorLuminance,estimateAnalyticLightPower,type EmissiveTriangle} from './lightSampling.js';\nimport {getSpotLightArea,getSpotLightRadiance} from './lightsData.js';\n\n/** Emitted flux, independent of the NEE selection heuristic. */\nexport function causticEmissionPower(light:AnalyticLightState,radius=1) {\n if(light.type==='DirectionalLight')return colorLuminance(light.color)*light.intensity*Math.PI*radius*radius;\n if(light.type==='RectLight')return estimateAnalyticLightPower(light)*(light.spread<=.001?1/Math.PI:Math.sin(Math.PI*.5*light.spread)**2);\n if(light.type!=='SpotLight')return estimateAnalyticLightPower(light);\n const outer=Math.cos(light.outerAngle*Math.PI/180),inner=Math.cos(Math.min(light.innerAngle,light.outerAngle)*Math.PI/180);\n const rows=128,columns=128;let integral=0;\n for(let y=0;y<rows;y++)for(let x=0;x<columns;x++){\n const cosine=1-(1-outer)*(y+.5)/rows;\n const t=inner>outer?Math.min(1,Math.max(0,(cosine-outer)/(inner-outer))):1;\n const ies=light.iesProfile?.sampleBaked(Math.acos(cosine),2*Math.PI*(x+.5)/columns-Math.PI)??1;\n integral+=t*t*(3-2*t)*ies;\n }\n integral*=2*Math.PI*(1-outer)/(rows*columns);\n // A sphere projects to one quarter of its surface area in any direction.\n const intensity=colorLuminance(light.color)*(light.radius===0?light.intensity:getSpotLightRadiance(light)*getSpotLightArea(light)/4);\n return intensity*integral;\n}\n/** Two texels per alias choice: probability/alias/type/index, then its PMF. */\nexport function causticEmissionTable(lights:readonly AnalyticLightState[],triangles:readonly EmissiveTriangle[],radius=1,environmentPower=0) {\n const entries=lights.map((light,sourceIndex)=>({sourceType:2,sourceIndex,weight:causticEmissionPower(light,radius)}));\n triangles.forEach((triangle,sourceIndex)=>entries.push({sourceType:3,sourceIndex,weight:Math.PI*triangle.area*triangle.samplingLuminance}));\n if(environmentPower>0)entries.push({sourceType:1,sourceIndex:0,weight:environmentPower*Math.PI*radius*radius});\n const distribution=buildLightAliasTable(entries),count=distribution.pmfs.length;\n const data=new Float32Array(count*8),words=new Uint32Array(data.buffer);\n for(let i=0;i<count;i++){words.set(distribution.choices.subarray(i*4,i*4+4),i*8);data[i*8+4]=distribution.pmfs[i];}\n return {data,count,totalPower:distribution.totalWeight};\n}\n"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface CausticLightUniformOptions {
|
|
2
|
+
casterSphere: readonly number[];
|
|
3
|
+
viewProjection: Float32Array | Float64Array | number[];
|
|
4
|
+
photons: number;
|
|
5
|
+
batch: number;
|
|
6
|
+
cameraScale: number;
|
|
7
|
+
casterCount?: number;
|
|
8
|
+
choiceCount?: number;
|
|
9
|
+
orthographic?: boolean;
|
|
10
|
+
experiments?: number;
|
|
11
|
+
}
|
|
12
|
+
export declare function packCausticLightUniform(options: CausticLightUniformOptions): ArrayBuffer;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { researchTransport } from './researchTransport.js';
|
|
2
|
+
import { matrixStorage } from '../math/storage.js';
|
|
3
|
+
import { CAUSTIC_UNIFORM_BYTES } from './wgsl/causticLight.compute.js';
|
|
4
|
+
export function packCausticLightUniform(options) {
|
|
5
|
+
const data = new ArrayBuffer(CAUSTIC_UNIFORM_BYTES), f = new Float32Array(data), u = new Uint32Array(data);
|
|
6
|
+
const matrix = matrixStorage(options.viewProjection);
|
|
7
|
+
for (let i = 0; i < 4; i++)
|
|
8
|
+
f[i] = options.casterSphere[i];
|
|
9
|
+
for (let i = 0; i < 16; i++)
|
|
10
|
+
f[i + 4] = matrix[i];
|
|
11
|
+
u[20] = options.photons;
|
|
12
|
+
u[21] = options.batch;
|
|
13
|
+
u[22] = 0;
|
|
14
|
+
f[23] = options.cameraScale;
|
|
15
|
+
u[24] = options.casterCount ?? 0;
|
|
16
|
+
u[25] = options.choiceCount ?? 0;
|
|
17
|
+
u[26] = +!!options.orthographic;
|
|
18
|
+
u[27] = options.experiments ?? 0;
|
|
19
|
+
researchTransport()?.packUniform(data, options);
|
|
20
|
+
return data;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=causticUniform.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"causticUniform.js","sourceRoot":"","sources":["../../src/renderer/causticUniform.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,iBAAiB,EAAC,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAC,aAAa,EAAC,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAC,qBAAqB,EAAC,MAAM,gCAAgC,CAAC;AAErE,MAAM,UAAU,uBAAuB,CAAC,OAAkC;IACxE,MAAM,IAAI,GAAC,IAAI,WAAW,CAAC,qBAAqB,CAAC,EAAC,CAAC,GAAC,IAAI,YAAY,CAAC,IAAI,CAAC,EAAC,CAAC,GAAC,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC;IACnG,MAAM,MAAM,GAAC,aAAa,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IAAA,KAAI,IAAI,CAAC,GAAC,CAAC,EAAC,CAAC,GAAC,CAAC,EAAC,CAAC,EAAE;QAAC,CAAC,CAAC,CAAC,CAAC,GAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAAA,KAAI,IAAI,CAAC,GAAC,CAAC,EAAC,CAAC,GAAC,EAAE,EAAC,CAAC,EAAE;QAAC,CAAC,CAAC,CAAC,GAAC,CAAC,CAAC,GAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAC1I,CAAC,CAAC,EAAE,CAAC,GAAC,OAAO,CAAC,OAAO,CAAC;IAAA,CAAC,CAAC,EAAE,CAAC,GAAC,OAAO,CAAC,KAAK,CAAC;IAAA,CAAC,CAAC,EAAE,CAAC,GAAC,CAAC,CAAC;IAAA,CAAC,CAAC,EAAE,CAAC,GAAC,OAAO,CAAC,WAAW,CAAC;IAAA,CAAC,CAAC,EAAE,CAAC,GAAC,OAAO,CAAC,WAAW,IAAE,CAAC,CAAC;IAAA,CAAC,CAAC,EAAE,CAAC,GAAC,OAAO,CAAC,WAAW,IAAE,CAAC,CAAC;IAAA,CAAC,CAAC,EAAE,CAAC,GAAC,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC;IACpK,CAAC,CAAC,EAAE,CAAC,GAAC,OAAO,CAAC,WAAW,IAAE,CAAC,CAAC;IAC7B,iBAAiB,EAAE,EAAE,WAAW,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAChD,OAAO,IAAI,CAAC;AACd,CAAC","sourcesContent":["import {researchTransport} from './researchTransport.js';\nimport {matrixStorage} from '../math/storage.js';\nimport {CAUSTIC_UNIFORM_BYTES} from './wgsl/causticLight.compute.js';\nexport interface CausticLightUniformOptions {casterSphere:readonly number[];viewProjection:Float32Array|Float64Array|number[];photons:number;batch:number;cameraScale:number;casterCount?:number;choiceCount?:number;orthographic?:boolean;experiments?:number}\nexport function packCausticLightUniform(options:CausticLightUniformOptions) {\n const data=new ArrayBuffer(CAUSTIC_UNIFORM_BYTES),f=new Float32Array(data),u=new Uint32Array(data);\n const matrix=matrixStorage(options.viewProjection);for(let i=0;i<4;i++)f[i]=options.casterSphere[i];for(let i=0;i<16;i++)f[i+4]=matrix[i];\n u[20]=options.photons;u[21]=options.batch;u[22]=0;f[23]=options.cameraScale;u[24]=options.casterCount??0;u[25]=options.choiceCount??0;u[26]=+!!options.orthographic;\n u[27]=options.experiments??0;\n researchTransport()?.packUniform(data, options);\n return data;\n}\n"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type Mesh from '../scene/MeshState.js';
|
|
2
|
+
import type OpenPBRMaterial from '../scene/MaterialState.js';
|
|
3
|
+
export declare const CAUSTIC_ROUGHNESS_MAX = 0.1;
|
|
4
|
+
/** Material-only classification, shared by caster collection and GPU estimators. */
|
|
5
|
+
export declare function isCausticSpecular(m: Pick<OpenPBRMaterial, 'baseWeight' | 'baseMetalness' | 'transmissionWeight' | 'subsurfaceWeight' | 'fuzzWeight' | 'coatWeight' | 'specularRoughness'>): boolean;
|
|
6
|
+
export type CasterSphere = [number, number, number, number];
|
|
7
|
+
/** One conservative world-space sphere per smooth mesh instance. */
|
|
8
|
+
export declare function causticCasterSpheres(meshes: readonly Mesh[]): CasterSphere[];
|
|
9
|
+
/** Conservative sphere enclosing the caster mixture. */
|
|
10
|
+
export declare function causticCasterSphere(meshes: readonly Mesh[]): CasterSphere;
|
|
11
|
+
/** CPU reference for the solid-angle mixture, including overlapping cones. */
|
|
12
|
+
export declare function casterDirectionPdf(origin: readonly number[], direction: readonly number[], spheres: readonly CasterSphere[], weights?: readonly number[]): number;
|
|
13
|
+
/** Stochastic smooth coverage currently disagrees with PT energy.
|
|
14
|
+
* Keep those scenes on PT until transport and endpoint weights are verified.
|
|
15
|
+
*/
|
|
16
|
+
export declare function hasStochasticCausticCaster(meshes: readonly Mesh[]): boolean;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { computeGeometryBounds } from './geometryBvhBounds.js';
|
|
2
|
+
import { matrixStorage } from '../math/storage.js';
|
|
3
|
+
import { read, write } from '../math/access.js';
|
|
4
|
+
import { meshInstanceCount, meshInstanceTransform } from './meshInstances.js';
|
|
5
|
+
import { mat4, vec3 } from '../math.js';
|
|
6
|
+
import { resolveMaterialAlphaMode } from '../scene/MaterialState.js';
|
|
7
|
+
export const CAUSTIC_ROUGHNESS_MAX = 0.1;
|
|
8
|
+
/** Material-only classification, shared by caster collection and GPU estimators. */
|
|
9
|
+
export function isCausticSpecular(m) {
|
|
10
|
+
return m.baseWeight * (1 - m.baseMetalness) * (1 - m.transmissionWeight) <= 1e-6 &&
|
|
11
|
+
m.subsurfaceWeight <= 0 && m.fuzzWeight <= 0 && m.coatWeight <= 0 && m.specularRoughness <= CAUSTIC_ROUGHNESS_MAX;
|
|
12
|
+
}
|
|
13
|
+
const casterBounds = new WeakMap();
|
|
14
|
+
function localCasterBounds(geometry) {
|
|
15
|
+
const cached = casterBounds.get(geometry), positions = geometry.position.array;
|
|
16
|
+
if (cached && cached.version === geometry.version && cached.positions === positions)
|
|
17
|
+
return cached.bounds;
|
|
18
|
+
const value = computeGeometryBounds(geometry), bounds = [matrixStorage(value[0]), matrixStorage(value[1])];
|
|
19
|
+
casterBounds.set(geometry, { version: geometry.version, positions, bounds });
|
|
20
|
+
return bounds;
|
|
21
|
+
}
|
|
22
|
+
/** One conservative world-space sphere per smooth mesh instance. */
|
|
23
|
+
export function causticCasterSpheres(meshes) {
|
|
24
|
+
const spheres = [];
|
|
25
|
+
const matrix = mat4.create(), point = vec3.create();
|
|
26
|
+
for (const mesh of meshes) {
|
|
27
|
+
if (!mesh.materials.some(isCausticSpecular))
|
|
28
|
+
continue;
|
|
29
|
+
// Geometry.boundingBox is optional caller metadata and starts at zero.
|
|
30
|
+
// Caster collection must also work for a raw public Geometry descriptor.
|
|
31
|
+
const bounds = localCasterBounds(mesh.geometry), minCorner = bounds[0], maxCorner = bounds[1];
|
|
32
|
+
if (!Number.isFinite(minCorner[0]) || !Number.isFinite(maxCorner[0]))
|
|
33
|
+
continue;
|
|
34
|
+
let expansion = 0;
|
|
35
|
+
for (const material of mesh.materials)
|
|
36
|
+
if (isCausticSpecular(material))
|
|
37
|
+
expansion = Math.max(expansion, Math.abs(material.displacementBias) + (material.displacementMap ? Math.abs(material.displacementScale) : 0));
|
|
38
|
+
for (let instance = 0; instance < meshInstanceCount(mesh); instance++) {
|
|
39
|
+
const min = [Infinity, Infinity, Infinity], max = [-Infinity, -Infinity, -Infinity];
|
|
40
|
+
meshInstanceTransform(mesh, instance, matrix);
|
|
41
|
+
for (let corner = 0; corner < 8; corner++) {
|
|
42
|
+
for (let axis = 0; axis < 3; axis++)
|
|
43
|
+
write(point, axis, ((corner & (1 << axis)) ? maxCorner[axis] + expansion : minCorner[axis] - expansion));
|
|
44
|
+
vec3.transformMat4(point, point, matrix);
|
|
45
|
+
for (let axis = 0; axis < 3; axis++) {
|
|
46
|
+
min[axis] = Math.min(min[axis], read(point, axis));
|
|
47
|
+
max[axis] = Math.max(max[axis], read(point, axis));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
spheres.push([(min[0] + max[0]) * .5, (min[1] + max[1]) * .5, (min[2] + max[2]) * .5, Math.hypot(max[0] - min[0], max[1] - min[1], max[2] - min[2]) * .501]);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return spheres;
|
|
54
|
+
}
|
|
55
|
+
/** Conservative sphere enclosing the caster mixture. */
|
|
56
|
+
export function causticCasterSphere(meshes) {
|
|
57
|
+
const spheres = causticCasterSpheres(meshes);
|
|
58
|
+
if (!spheres.length)
|
|
59
|
+
return [0, 0, 0, 0];
|
|
60
|
+
const min = [Infinity, Infinity, Infinity], max = [-Infinity, -Infinity, -Infinity];
|
|
61
|
+
for (const s of spheres) {
|
|
62
|
+
const components = [s[0], s[1], s[2]];
|
|
63
|
+
for (let i = 0; i < 3; i++) {
|
|
64
|
+
min[i] = Math.min(min[i], components[i] - s[3]);
|
|
65
|
+
max[i] = Math.max(max[i], components[i] + s[3]);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
const center = min.map((v, i) => (v + max[i]) * .5);
|
|
69
|
+
let radius = 0;
|
|
70
|
+
for (const s of spheres)
|
|
71
|
+
radius = Math.max(radius, Math.hypot(s[0] - center[0], s[1] - center[1], s[2] - center[2]) + s[3]);
|
|
72
|
+
return [center[0], center[1], center[2], radius];
|
|
73
|
+
}
|
|
74
|
+
/** CPU reference for the solid-angle mixture, including overlapping cones. */
|
|
75
|
+
export function casterDirectionPdf(origin, direction, spheres, weights = []) {
|
|
76
|
+
let total = 0, overlaps = 0;
|
|
77
|
+
for (const [index, s] of spheres.entries()) {
|
|
78
|
+
const weight = weights[index] ?? 1;
|
|
79
|
+
const d = Math.hypot(s[0] - origin[0], s[1] - origin[1], s[2] - origin[2]);
|
|
80
|
+
const cosine = d > s[3] ? Math.sqrt(Math.max(0, 1 - (s[3] / d) ** 2)) : -1;
|
|
81
|
+
total += 2 * Math.PI * (1 - cosine) * weight;
|
|
82
|
+
if (d <= s[3] || ((s[0] - origin[0]) * direction[0] + (s[1] - origin[1]) * direction[1] + (s[2] - origin[2]) * direction[2]) / d >= cosine)
|
|
83
|
+
overlaps += weight;
|
|
84
|
+
}
|
|
85
|
+
return total > 0 ? overlaps / total : 0;
|
|
86
|
+
}
|
|
87
|
+
/** Stochastic smooth coverage currently disagrees with PT energy.
|
|
88
|
+
* Keep those scenes on PT until transport and endpoint weights are verified.
|
|
89
|
+
*/
|
|
90
|
+
export function hasStochasticCausticCaster(meshes) {
|
|
91
|
+
return meshes.some(mesh => mesh.materials.some(m => isCausticSpecular(m) && resolveMaterialAlphaMode(m) === 'blend'));
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=caustics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"caustics.js","sourceRoot":"","sources":["../../src/renderer/caustics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,qBAAqB,EAAC,MAAM,wBAAwB,CAAC;AAE7D,OAAO,EAAC,aAAa,EAAC,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAC,IAAI,EAAC,KAAK,EAAC,MAAM,mBAAmB,CAAC;AAE7C,OAAO,EAAC,iBAAiB,EAAC,qBAAqB,EAAC,MAAM,oBAAoB,CAAC;AAC3E,OAAO,EAAC,IAAI,EAAC,IAAI,EAAC,MAAM,YAAY,CAAC;AAErC,OAAO,EAAC,wBAAwB,EAAC,MAAM,2BAA2B,CAAC;AAEnE,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAAG,CAAC;AACzC,oFAAoF;AACpF,MAAM,UAAU,iBAAiB,CAAC,CAAwJ;IACxL,OAAO,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,kBAAkB,CAAC,IAAI,IAAI;QAC9E,CAAC,CAAC,gBAAgB,IAAI,CAAC,IAAI,CAAC,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,CAAC,iBAAiB,IAAI,qBAAqB,CAAC;AACtH,CAAC;AAGD,MAAM,YAAY,GAAC,IAAI,OAAO,EAAuF,CAAC;AACtH,SAAS,iBAAiB,CAAC,QAAiB;IAC3C,MAAM,MAAM,GAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAC,SAAS,GAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC;IAC1E,IAAG,MAAM,IAAE,MAAM,CAAC,OAAO,KAAG,QAAQ,CAAC,OAAO,IAAE,MAAM,CAAC,SAAS,KAAG,SAAS;QAAC,OAAO,MAAM,CAAC,MAAM,CAAC;IAChG,MAAM,KAAK,GAAC,qBAAqB,CAAC,QAAQ,CAAC,EAAC,MAAM,GAA6B,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACjI,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAC,EAAC,OAAO,EAAC,QAAQ,CAAC,OAAO,EAAC,SAAS,EAAC,MAAM,EAAC,CAAC,CAAC;IAAA,OAAO,MAAM,CAAC;AACtF,CAAC;AACD,oEAAoE;AACpE,MAAM,UAAU,oBAAoB,CAAC,MAAuB;IAC1D,MAAM,OAAO,GAAgB,EAAE,CAAC;IAChC,MAAM,MAAM,GAAC,IAAI,CAAC,MAAM,EAAE,EAAC,KAAK,GAAC,IAAI,CAAC,MAAM,EAAE,CAAC;IAC/C,KAAI,MAAM,IAAI,IAAI,MAAM,EAAE,CAAC;QACzB,IAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,iBAAiB,CAAC;YAAC,SAAS;QACpD,uEAAuE;QACvE,yEAAyE;QACzE,MAAM,MAAM,GAAC,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAC,SAAS,GAAC,MAAM,CAAC,CAAC,CAAC,EAAC,SAAS,GAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACtF,IAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;YAAC,SAAS;QAC3E,IAAI,SAAS,GAAC,CAAC,CAAC;QAChB,KAAI,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS;YAAC,IAAG,iBAAiB,CAAC,QAAQ,CAAC;gBAAC,SAAS,GAAC,IAAI,CAAC,GAAG,CAAC,SAAS,EAC9F,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,gBAAgB,CAAC,GAAC,CAAC,QAAQ,CAAC,eAAe,CAAA,CAAC,CAAA,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAA,CAAC,CAAA,CAAC,CAAC,CAAC,CAAC;QACzG,KAAI,IAAI,QAAQ,GAAC,CAAC,EAAC,QAAQ,GAAC,iBAAiB,CAAC,IAAI,CAAC,EAAC,QAAQ,EAAE,EAAE,CAAC;YAC/D,MAAM,GAAG,GAAC,CAAC,QAAQ,EAAC,QAAQ,EAAC,QAAQ,CAAC,EAAC,GAAG,GAAC,CAAC,CAAC,QAAQ,EAAC,CAAC,QAAQ,EAAC,CAAC,QAAQ,CAAC,CAAC;YAC3E,qBAAqB,CAAC,IAAI,EAAC,QAAQ,EAAC,MAAM,CAAC,CAAC;YAC5C,KAAI,IAAI,MAAM,GAAC,CAAC,EAAC,MAAM,GAAC,CAAC,EAAC,MAAM,EAAE,EAAE,CAAC;gBACnC,KAAI,IAAI,IAAI,GAAC,CAAC,EAAC,IAAI,GAAC,CAAC,EAAC,IAAI,EAAE;oBAAC,KAAK,CAAC,KAAK,EAAC,IAAI,EAAC,CAAC,CAAC,MAAM,GAAC,CAAC,CAAC,IAAE,IAAI,CAAC,CAAC,CAAA,CAAC,CAAA,SAAS,CAAC,IAAI,CAAC,GAAC,SAAS,CAAA,CAAC,CAAA,SAAS,CAAC,IAAI,CAAC,GAAC,SAAS,CAAC,CAAC,CAAC;gBACxH,IAAI,CAAC,aAAa,CAAC,KAAK,EAAC,KAAK,EAAC,MAAM,CAAC,CAAC;gBACvC,KAAI,IAAI,IAAI,GAAC,CAAC,EAAC,IAAI,GAAC,CAAC,EAAC,IAAI,EAAE,EAAC,CAAC;oBAAA,GAAG,CAAC,IAAI,CAAC,GAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAC,IAAI,CAAC,KAAK,EAAC,IAAI,CAAC,CAAC,CAAC;oBAAA,GAAG,CAAC,IAAI,CAAC,GAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAC,IAAI,CAAC,KAAK,EAAC,IAAI,CAAC,CAAC,CAAC;gBAAA,CAAC;YAC/H,CAAC;YACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAC,EAAE,EAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAC,EAAE,EAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAC,EAAE,EAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,GAAC,GAAG,CAAC,CAAC,CAAC,EAAC,GAAG,CAAC,CAAC,CAAC,GAAC,GAAG,CAAC,CAAC,CAAC,EAAC,GAAG,CAAC,CAAC,CAAC,GAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAC,IAAI,CAAC,CAAC,CAAC;QACtI,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AACD,wDAAwD;AACxD,MAAM,UAAU,mBAAmB,CAAC,MAAsB;IACxD,MAAM,OAAO,GAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAAA,IAAG,CAAC,OAAO,CAAC,MAAM;QAAC,OAAO,CAAC,CAAC,EAAC,CAAC,EAAC,CAAC,EAAC,CAAC,CAAC,CAAC;IAC/E,MAAM,GAAG,GAAC,CAAC,QAAQ,EAAC,QAAQ,EAAC,QAAQ,CAAC,EAAC,GAAG,GAAC,CAAC,CAAC,QAAQ,EAAC,CAAC,QAAQ,EAAC,CAAC,QAAQ,CAAC,CAAC;IAC3E,KAAI,MAAM,CAAC,IAAI,OAAO,EAAC,CAAC;QAAA,MAAM,UAAU,GAAU,CAAC,CAAC,CAAC,CAAC,CAAC,EAAC,CAAC,CAAC,CAAC,CAAC,EAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAAA,KAAI,IAAI,CAAC,GAAC,CAAC,EAAC,CAAC,GAAC,CAAC,EAAC,CAAC,EAAE,EAAC,CAAC;YAAA,GAAG,CAAC,CAAC,CAAC,GAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAC,UAAU,CAAC,CAAC,CAAC,GAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAAA,GAAG,CAAC,CAAC,CAAC,GAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAC,UAAU,CAAC,CAAC,CAAC,GAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAAA,CAAC;IAAA,CAAC;IAChL,MAAM,MAAM,GAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAC,CAAC,EAAC,EAAE,CAAA,CAAC,CAAC,GAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAC,EAAE,CAAC,CAAC;IAC3C,IAAI,MAAM,GAAC,CAAC,CAAC;IAAA,KAAI,MAAM,CAAC,IAAI,OAAO;QAAC,MAAM,GAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAC,MAAM,CAAC,CAAC,CAAC,EAAC,CAAC,CAAC,CAAC,CAAC,GAAC,MAAM,CAAC,CAAC,CAAC,EAAC,CAAC,CAAC,CAAC,CAAC,GAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1H,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAC,MAAM,CAAC,CAAC,CAAC,EAAC,MAAM,CAAC,CAAC,CAAC,EAAC,MAAM,CAAC,CAAC;AAChD,CAAC;AACD,8EAA8E;AAC9E,MAAM,UAAU,kBAAkB,CAAC,MAAwB,EAAC,SAA2B,EAAC,OAA+B,EAAC,UAA0B,EAAE;IAClJ,IAAI,KAAK,GAAC,CAAC,EAAC,QAAQ,GAAC,CAAC,CAAC;IACvB,KAAI,MAAM,CAAC,KAAK,EAAC,CAAC,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,EAAC,CAAC;QAAA,MAAM,MAAM,GAAC,OAAO,CAAC,KAAK,CAAC,IAAE,CAAC,CAAC;QAAA,MAAM,CAAC,GAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAC,MAAM,CAAC,CAAC,CAAC,EAAC,CAAC,CAAC,CAAC,CAAC,GAAC,MAAM,CAAC,CAAC,CAAC,EAAC,CAAC,CAAC,CAAC,CAAC,GAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QACxI,MAAM,MAAM,GAAC,CAAC,GAAC,CAAC,CAAC,CAAC,CAAC,CAAA,CAAC,CAAA,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAC,CAAC,GAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAC,CAAC,CAAC,IAAE,CAAC,CAAC,CAAC,CAAA,CAAC,CAAA,CAAC,CAAC,CAAC;QAC5D,KAAK,IAAE,CAAC,GAAC,IAAI,CAAC,EAAE,GAAC,CAAC,CAAC,GAAC,MAAM,CAAC,GAAC,MAAM,CAAC;QACnC,IAAG,CAAC,IAAE,CAAC,CAAC,CAAC,CAAC,IAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAC,SAAS,CAAC,CAAC,CAAC,GAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAC,SAAS,CAAC,CAAC,CAAC,GAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAC,CAAC,IAAE,MAAM;YAAC,QAAQ,IAAE,MAAM,CAAC;IACrI,CAAC;IACD,OAAO,KAAK,GAAC,CAAC,CAAA,CAAC,CAAA,QAAQ,GAAC,KAAK,CAAA,CAAC,CAAA,CAAC,CAAC;AAClC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,0BAA0B,CAAC,MAAsB;IAChE,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAA,EAAE,CAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAA,EAAE,CAAA,iBAAiB,CAAC,CAAC,CAAC,IAAE,wBAAwB,CAAC,CAAC,CAAC,KAAG,OAAO,CAAC,CAAC,CAAC;AAC/G,CAAC","sourcesContent":["import {computeGeometryBounds} from './geometryBvhBounds.js';\nimport type Geometry from '../scene/Geometry.js';\nimport {matrixStorage} from '../math/storage.js';\nimport {read,write} from '../math/access.js';\nimport type Mesh from '../scene/MeshState.js';\nimport {meshInstanceCount,meshInstanceTransform} from './meshInstances.js';\nimport {mat4,vec3} from '../math.js';\nimport type OpenPBRMaterial from '../scene/MaterialState.js';\nimport {resolveMaterialAlphaMode} from '../scene/MaterialState.js';\n\nexport const CAUSTIC_ROUGHNESS_MAX = 0.1;\n/** Material-only classification, shared by caster collection and GPU estimators. */\nexport function isCausticSpecular(m: Pick<OpenPBRMaterial, 'baseWeight' | 'baseMetalness' | 'transmissionWeight' | 'subsurfaceWeight' | 'fuzzWeight' | 'coatWeight' | 'specularRoughness'>) {\n return m.baseWeight * (1 - m.baseMetalness) * (1 - m.transmissionWeight) <= 1e-6 &&\n m.subsurfaceWeight <= 0 && m.fuzzWeight <= 0 && m.coatWeight <= 0 && m.specularRoughness <= CAUSTIC_ROUGHNESS_MAX;\n}\n\nexport type CasterSphere = [number,number,number,number];\nconst casterBounds=new WeakMap<Geometry,{version:number;positions:Float32Array;bounds:[Float64Array,Float64Array]}>();\nfunction localCasterBounds(geometry:Geometry){\n const cached=casterBounds.get(geometry),positions=geometry.position.array;\n if(cached&&cached.version===geometry.version&&cached.positions===positions)return cached.bounds;\n const value=computeGeometryBounds(geometry),bounds:[Float64Array,Float64Array]=[matrixStorage(value[0]),matrixStorage(value[1])];\n casterBounds.set(geometry,{version:geometry.version,positions,bounds});return bounds;\n}\n/** One conservative world-space sphere per smooth mesh instance. */\nexport function causticCasterSpheres(meshes: readonly Mesh[]): CasterSphere[] {\n const spheres:CasterSphere[]=[];\n const matrix=mat4.create(),point=vec3.create();\n for(const mesh of meshes) {\n if(!mesh.materials.some(isCausticSpecular))continue;\n // Geometry.boundingBox is optional caller metadata and starts at zero.\n // Caster collection must also work for a raw public Geometry descriptor.\n const bounds=localCasterBounds(mesh.geometry),minCorner=bounds[0],maxCorner=bounds[1];\n if(!Number.isFinite(minCorner[0])||!Number.isFinite(maxCorner[0]))continue;\n let expansion=0;\n for(const material of mesh.materials)if(isCausticSpecular(material))expansion=Math.max(expansion,\n Math.abs(material.displacementBias)+(material.displacementMap?Math.abs(material.displacementScale):0));\n for(let instance=0;instance<meshInstanceCount(mesh);instance++) {\n const min=[Infinity,Infinity,Infinity],max=[-Infinity,-Infinity,-Infinity];\n meshInstanceTransform(mesh,instance,matrix);\n for(let corner=0;corner<8;corner++) {\n for(let axis=0;axis<3;axis++)write(point,axis,((corner&(1<<axis))?maxCorner[axis]+expansion:minCorner[axis]-expansion));\n vec3.transformMat4(point,point,matrix);\n for(let axis=0;axis<3;axis++){min[axis]=Math.min(min[axis],read(point,axis));max[axis]=Math.max(max[axis],read(point,axis));}\n }\n spheres.push([(min[0]+max[0])*.5,(min[1]+max[1])*.5,(min[2]+max[2])*.5,Math.hypot(max[0]-min[0],max[1]-min[1],max[2]-min[2])*.501]);\n }\n }\n return spheres;\n}\n/** Conservative sphere enclosing the caster mixture. */\nexport function causticCasterSphere(meshes:readonly Mesh[]):CasterSphere {\n const spheres=causticCasterSpheres(meshes);if(!spheres.length)return [0,0,0,0];\n const min=[Infinity,Infinity,Infinity],max=[-Infinity,-Infinity,-Infinity];\n for(const s of spheres){const components:number[]=[s[0],s[1],s[2]];for(let i=0;i<3;i++){min[i]=Math.min(min[i],components[i]-s[3]);max[i]=Math.max(max[i],components[i]+s[3]);}}\n const center=min.map((v,i)=>(v+max[i])*.5);\n let radius=0;for(const s of spheres)radius=Math.max(radius,Math.hypot(s[0]-center[0],s[1]-center[1],s[2]-center[2])+s[3]);\n return [center[0],center[1],center[2],radius];\n}\n/** CPU reference for the solid-angle mixture, including overlapping cones. */\nexport function casterDirectionPdf(origin:readonly number[],direction:readonly number[],spheres:readonly CasterSphere[],weights:readonly number[]=[]) {\n let total=0,overlaps=0;\n for(const [index,s] of spheres.entries()){const weight=weights[index]??1;const d=Math.hypot(s[0]-origin[0],s[1]-origin[1],s[2]-origin[2]);\n const cosine=d>s[3]?Math.sqrt(Math.max(0,1-(s[3]/d)**2)):-1;\n total+=2*Math.PI*(1-cosine)*weight;\n if(d<=s[3]||((s[0]-origin[0])*direction[0]+(s[1]-origin[1])*direction[1]+(s[2]-origin[2])*direction[2])/d>=cosine)overlaps+=weight;\n }\n return total>0?overlaps/total:0;\n}\n\n/** Stochastic smooth coverage currently disagrees with PT energy.\n * Keep those scenes on PT until transport and endpoint weights are verified.\n */\nexport function hasStochasticCausticCaster(meshes:readonly Mesh[]){\n return meshes.some(mesh=>mesh.materials.some(m=>isCausticSpecular(m)&&resolveMaterialAlphaMode(m)==='blend'));\n}\n"]}
|
|
@@ -9,7 +9,7 @@ export default new FragmentShader({
|
|
|
9
9
|
mapping: Shader.uniform('vec4'), idComponent: Shader.uniform('int')
|
|
10
10
|
},
|
|
11
11
|
main: /* glsl */ `
|
|
12
|
-
uint
|
|
12
|
+
uint vB(uint v) {
|
|
13
13
|
v = (v ^ (v >> 16u)) * 0x7feb352du;
|
|
14
14
|
v = (v ^ (v >> 15u)) * 0x846ca68bu;
|
|
15
15
|
return v ^ (v >> 16u);
|
|
@@ -36,16 +36,16 @@ color = srgb(clamp(r.xyz / max(r.w, 1.0), 0.0, 1.0));
|
|
|
36
36
|
} else if (kind == 5) {
|
|
37
37
|
uvec4 ids = texelFetch(identity, p, 0);
|
|
38
38
|
alpha = ids.x == 0xffffffffu ? 0.0 : 1.0;
|
|
39
|
-
uint h =
|
|
39
|
+
uint h = vB(ids[idComponent]);
|
|
40
40
|
color = .2 + .8 * vec3(float(h & 255u), float((h >> 8u) & 255u),
|
|
41
41
|
float((h >> 16u) & 255u)) / 255.0;
|
|
42
42
|
} else {
|
|
43
43
|
vec4 m = texelFetch(motion, p, 0);
|
|
44
44
|
alpha = m.w == 3.0 ? 1.0 : 0.0;
|
|
45
|
-
float
|
|
46
|
-
if (
|
|
45
|
+
float gz = length(m.xy), hue = 0.0;
|
|
46
|
+
if (gz > 0.0) hue = fract(atan(m.y, m.x) / 6.28318530718 + 1.0);
|
|
47
47
|
vec3 v = abs(fract(vec3(hue) + vec3(0.0, 2.0 / 3.0, 1.0 / 3.0)) * 6.0 - 3.0);
|
|
48
|
-
color = clamp(v - 1.0, 0.0, 1.0) * clamp(
|
|
48
|
+
color = clamp(v - 1.0, 0.0, 1.0) * clamp(gz / mapping.w, 0.0, 1.0);
|
|
49
49
|
}
|
|
50
50
|
if (alpha <= 0.0) color = vec3(0.0);
|
|
51
51
|
out_color = vec4(color, clamp(alpha, 0.0, 1.0));
|
|
@@ -1,82 +1,82 @@
|
|
|
1
1
|
import proposals from './aovReflectanceSamples.glsl.js';
|
|
2
2
|
// GLSL mirror of the shared 256-proposal, fused OpenPBR reflection quadrature.
|
|
3
3
|
export default proposals + /* glsl */ `
|
|
4
|
-
void aovReflectance(
|
|
4
|
+
void aovReflectance(OpenPbrPreparedBsdf prepared, bool qH, bool kE, out vec3 diffuse, out vec3 specular) {
|
|
5
5
|
diffuse=vec3(0.0); specular=vec3(0.0);
|
|
6
6
|
vec3 view = prepared.viewLocal;
|
|
7
7
|
if (view.z <= 1e-6) { return; }
|
|
8
8
|
OpenPbrResolvedMaterial material = prepared.material;
|
|
9
9
|
vec2 alpha = vec2(material.alphaX, material.alphaY);
|
|
10
|
-
float
|
|
11
|
-
float
|
|
12
|
-
float
|
|
10
|
+
float lN = aD(view, alpha);
|
|
11
|
+
float iR = prepared.weights[OPENPBR_LOBE_DIFFUSE];
|
|
12
|
+
float fN = prepared.weights[OPENPBR_LOBE_METAL];
|
|
13
13
|
float specularWeight = prepared.weights[OPENPBR_LOBE_SPECULAR];
|
|
14
|
-
float
|
|
15
|
-
if (
|
|
16
|
-
|
|
14
|
+
float dS = 1.0;
|
|
15
|
+
if (kE && prepared.dielectricMsProbability > 0.0) {
|
|
16
|
+
dS = max(aY(prepared.refractionEtaTOverEtaI, prepared.specularAlpha), 1e-12);
|
|
17
17
|
}
|
|
18
|
-
vec3
|
|
19
|
-
float
|
|
20
|
-
float
|
|
18
|
+
vec3 ce = normalize(vec3(alpha, 1.0) * view);
|
|
19
|
+
float qG = min(ce.z, 1.0);
|
|
20
|
+
float jN = 1.0 + qG;
|
|
21
21
|
uint count = 256u;
|
|
22
22
|
for (uint i = 0u; i < uint(NO_UNROLL(256)); i++) {
|
|
23
|
-
uint
|
|
24
|
-
vec2 u = vec2((float(
|
|
25
|
-
fract(float(reverseBits(
|
|
26
|
-
vec4
|
|
23
|
+
uint wn = i / 2u;
|
|
24
|
+
vec2 u = vec2((float(wn) + 0.5) / float(count / 2u),
|
|
25
|
+
fract(float(reverseBits(wn)) * 2.3283064365386963e-10 + 0.37));
|
|
26
|
+
vec4 proposal = gV[wn];
|
|
27
27
|
|
|
28
|
-
bool
|
|
29
|
-
vec3 light = vec3(
|
|
30
|
-
if (
|
|
28
|
+
bool hv = prepared.specularAlpha < 0.001;
|
|
29
|
+
vec3 light = vec3(proposal.xy, sqrt(max(0.0, 1.0 - dot(proposal.xy, proposal.xy))));
|
|
30
|
+
if (hv) { light = aM(u); }
|
|
31
31
|
if ((i & 1u) != 0u) {
|
|
32
|
-
float
|
|
33
|
-
float
|
|
34
|
-
vec3
|
|
35
|
-
if (
|
|
36
|
-
light = reflect(-view,
|
|
32
|
+
float kf = (1.0 - u.y) * jN;
|
|
33
|
+
float dr = sqrt(max(0.0, (kf + (1.0 - qG)) * (u.y * jN)));
|
|
34
|
+
vec3 aa = normalize(vec3(alpha, 1.0) * vec3(ce.xy + dr * proposal.zw, kf));
|
|
35
|
+
if (hv) { aa = aA(view, alpha, u); }
|
|
36
|
+
light = reflect(-view, aa);
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
if (light.z <= 0.0) { continue; }
|
|
40
|
-
vec3
|
|
41
|
-
float
|
|
42
|
-
float pdf = 0.5 * (light.z * INVPI +
|
|
40
|
+
vec3 aa = normalize(view + light);
|
|
41
|
+
float specularPdf = lN * sampling_ggx_ndf(aa, alpha) / (4.0 * view.z);
|
|
42
|
+
float pdf = 0.5 * (light.z * INVPI + specularPdf);
|
|
43
43
|
|
|
44
44
|
|
|
45
|
-
vec3
|
|
46
|
-
if (
|
|
47
|
-
float scale = abs(
|
|
48
|
-
if (
|
|
49
|
-
float compensation = prepared.diffuseSpecularEnergyCompensation *
|
|
50
|
-
prepared.specularEtaTOverEtaI, prepared.specularAlpha, abs(
|
|
51
|
-
float
|
|
52
|
-
diffuse +=
|
|
53
|
-
view,
|
|
45
|
+
vec3 au = openpbr_to_local(prepared.basis, openpbr_to_world(prepared.basis, light));
|
|
46
|
+
if (au.z <= 0.0) { continue; }
|
|
47
|
+
float scale = abs(au.z) / (pdf * float(count));
|
|
48
|
+
if (qH && iR > 0.0) {
|
|
49
|
+
float compensation = prepared.diffuseSpecularEnergyCompensation * ar(
|
|
50
|
+
prepared.specularEtaTOverEtaI, prepared.specularAlpha, abs(au.z));
|
|
51
|
+
float unusedPdf = 0.0;
|
|
52
|
+
diffuse += iR * bw(material, prepared.diffuseColor,
|
|
53
|
+
view, au, compensation, unusedPdf) * scale;
|
|
54
54
|
}
|
|
55
|
-
if (
|
|
56
|
-
vec3
|
|
57
|
-
float
|
|
58
|
-
vec3
|
|
55
|
+
if (kE) {
|
|
56
|
+
vec3 evaluatedHalf = normalize(view + au);
|
|
57
|
+
float viewHalf = abs(dot(view, evaluatedHalf));
|
|
58
|
+
vec3 fresnel = vec3(0.0);
|
|
59
59
|
if (specularWeight > 0.0) {
|
|
60
|
-
vec3 dielectric = vec3(
|
|
61
|
-
if (material.thinWalled) { dielectric =
|
|
62
|
-
|
|
60
|
+
vec3 dielectric = vec3(ae(viewHalf, material.relativeIor));
|
|
61
|
+
if (material.thinWalled) { dielectric = aq(dielectric, material.transmissionWeight); }
|
|
62
|
+
fresnel += specularWeight * material.specularColor * dielectric;
|
|
63
63
|
}
|
|
64
|
-
if (
|
|
65
|
-
|
|
64
|
+
if (fN > 0.0) {
|
|
65
|
+
fresnel += fN * material.specularWeight * openpbr_metal_fresnel(viewHalf,
|
|
66
66
|
material.baseWeight * material.baseColor, material.specularColor);
|
|
67
67
|
}
|
|
68
|
-
float
|
|
69
|
-
*
|
|
70
|
-
vec3 reflection =
|
|
71
|
-
if (
|
|
72
|
-
float
|
|
73
|
-
reflection +=
|
|
68
|
+
float rE = sampling_ggx_ndf(evaluatedHalf, alpha) * lN
|
|
69
|
+
* aD(au, alpha) / (4.0 * max(au.z * view.z, 1e-8));
|
|
70
|
+
vec3 reflection = fresnel * rE;
|
|
71
|
+
if (fN > 0.0 && prepared.metalMsFactor > 0.0) {
|
|
72
|
+
float cv = min(prepared.metalMsFactor * aR(prepared.specularAlpha, au.z), 1.0 / max(au.z, 1e-8));
|
|
73
|
+
reflection += fN * prepared.metalMsScale * cv * INVPI;
|
|
74
74
|
}
|
|
75
75
|
if (prepared.dielectricMsProbability > 0.0) {
|
|
76
|
-
float
|
|
77
|
-
prepared.refractionEtaTOverEtaI, prepared.specularAlpha, abs(
|
|
78
|
-
float
|
|
79
|
-
reflection += prepared.dielectricMsReflectionScale *
|
|
76
|
+
float oP = prepared.dielectricMsViewLoss * aV(
|
|
77
|
+
prepared.refractionEtaTOverEtaI, prepared.specularAlpha, abs(au.z)) / dS;
|
|
78
|
+
float cv = min(oP * prepared.dielectricMsReflectionRatio, 1.0 / abs(au.z));
|
|
79
|
+
reflection += prepared.dielectricMsReflectionScale * cv * INVPI;
|
|
80
80
|
}
|
|
81
81
|
specular += reflection * scale;
|
|
82
82
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Generated by scripts/generate-aov-reflectance-samples.mjs; do not edit.
|
|
2
2
|
// xy: concentric cosine disk; zw: spherical-cap azimuth cosine/sine.
|
|
3
3
|
export default /* glsl */ `
|
|
4
|
-
const vec4
|
|
4
|
+
const vec4 gV[128] = vec4[128](
|
|
5
5
|
vec4(-0.971247852, -0.202764958, 0.999698818, 0.0245412290),
|
|
6
6
|
vec4(-0.808660269, 0.547487736, 0.997290432, 0.0735645667),
|
|
7
7
|
vec4(-0.942509234, 0.187289074, 0.992479563, 0.122410677),
|
|
@@ -11,19 +11,19 @@ import random from './chunks/random.glsl.js';
|
|
|
11
11
|
import cameraRay from './chunks/cameraRay.glsl.js';
|
|
12
12
|
import rand from './chunks/rand.glsl.js';
|
|
13
13
|
const surface = /* glsl */ `
|
|
14
|
-
uint
|
|
15
|
-
vec3
|
|
16
|
-
mat4
|
|
17
|
-
Ray
|
|
14
|
+
uint jK(int index) { ivec2 size = textureSize(aovScene,0); uvec4 v = texelFetch(aovScene, ivec2((index/4)%size.x, (index/4)/size.x),0); return v[index%4]; }
|
|
15
|
+
vec3 iu(int offset){return vec3(uintBitsToFloat(jK(offset)),uintBitsToFloat(jK(offset+1)),uintBitsToFloat(jK(offset+2)));}
|
|
16
|
+
mat4 oi(int offset) { mat4 m; for (int i=0;i<4;i++) for(int j=0;j<4;j++) m[i][j]=uintBitsToFloat(jK(offset+i*4+j)); return m; }
|
|
17
|
+
Ray xj(vec2 uv) {
|
|
18
18
|
vec4 origin = viewProjectionInv*vec4(uv*2.0-1.0,-1.0,1.0);
|
|
19
19
|
vec4 target = viewProjectionInv*vec4(uv*2.0-1.0,1.0,1.0);
|
|
20
|
-
Ray ray;
|
|
20
|
+
Ray ray; initRay(ray, origin.xyz/origin.w, normalize(target.xyz*origin.w-origin.xyz*target.w)); return ray;
|
|
21
21
|
}
|
|
22
|
-
bool
|
|
23
|
-
Ray ray=
|
|
22
|
+
bool mC(Ray xA, out SurfaceInteraction si, out OpenPbrResolvedMaterial material) {
|
|
23
|
+
Ray ray=xA; si.triangleIndex=-1;
|
|
24
24
|
for(int layer=0;layer<32;layer++) {
|
|
25
25
|
intersectScene(ray,si,false); if(!si.hit) return false;
|
|
26
|
-
|
|
26
|
+
getMaterial(material,si.materialIndex,si.uv,si.uv1,si.instanceIndex,si.vertexColor);
|
|
27
27
|
if(material.materialType!=SHADOW_CATCHER && material.alpha>=0.5) return true;
|
|
28
28
|
ray.o=si.position+ray.d*(EPS*0.02);
|
|
29
29
|
}
|
|
@@ -57,56 +57,56 @@ ${surface}
|
|
|
57
57
|
void main() {
|
|
58
58
|
${center ? /* glsl */ `
|
|
59
59
|
out_id=uvec4(0xffffffffu); out_motion=vec4(0.0);
|
|
60
|
-
Ray ray=
|
|
60
|
+
Ray ray=xj((floor(gl_FragCoord.xy)+0.5)/viewportSize);
|
|
61
61
|
SurfaceInteraction si; OpenPbrResolvedMaterial material;
|
|
62
|
-
if(!
|
|
62
|
+
if(!mC(ray,si,material)) return;
|
|
63
63
|
int offset=52+si.instanceIndex*24;
|
|
64
|
-
out_id=uvec4(
|
|
65
|
-
out_motion.z=dot(si.position-
|
|
66
|
-
if(
|
|
67
|
-
vec4
|
|
68
|
-
vec4
|
|
69
|
-
if(
|
|
70
|
-
vec3
|
|
71
|
-
if(any(lessThan(
|
|
72
|
-
uvec4 identity=texelFetch(previousId,ivec2(
|
|
73
|
-
if(any(notEqual(identity.xy,out_id.xy))||abs(
|
|
74
|
-
out_motion=vec4((
|
|
64
|
+
out_id=uvec4(jK(offset),jK(offset+1),jK(int(jK(16))+si.materialIndex),jK(int(jK(17))+si.triangleIndex));
|
|
65
|
+
out_motion.z=dot(si.position-iu(36),iu(40));
|
|
66
|
+
if(jK(offset+2)==0u)return;
|
|
67
|
+
vec4 qs=oi(offset+4)*vec4(si.position,1.0);
|
|
68
|
+
vec4 pg=oi(0)*qs;
|
|
69
|
+
if(pg.w<=0.0)return;
|
|
70
|
+
vec3 ua=pg.xyz/pg.w;vec2 hU=(ua.xy*0.5+0.5)*viewportSize;
|
|
71
|
+
if(any(lessThan(hU,vec2(0.0)))||any(greaterThanEqual(hU,viewportSize))||abs(ua.z)>1.0)return;
|
|
72
|
+
uvec4 identity=texelFetch(previousId,ivec2(hU),0);float qr=texelFetch(previousMotion,ivec2(hU),0).z;
|
|
73
|
+
if(any(notEqual(identity.xy,out_id.xy))||abs(qr-dot(qs.xyz-iu(44),iu(48)))>max(1e-4,abs(qr)*1e-3))return;
|
|
74
|
+
out_motion=vec4((hU-gl_FragCoord.xy)*vec2(1.0,-1.0),out_motion.z,3.0);
|
|
75
75
|
` : /* glsl */ `
|
|
76
76
|
ivec2 coord=ivec2(gl_FragCoord.xy);
|
|
77
77
|
out_geometry=aovSample==0 ? vec4(0.0) : texelFetch(previousGeometry,coord,0);
|
|
78
78
|
out_position=aovSample==0 ? vec4(0.0) : texelFetch(previousPosition,coord,0);
|
|
79
79
|
out_diffuse=aovSample==0 ? vec4(0.0) : texelFetch(previousDiffuse,coord,0);
|
|
80
80
|
out_specular=aovSample==0 ? vec4(0.0) : texelFetch(previousSpecular,coord,0);
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
Ray ray=
|
|
81
|
+
rA(); aI=uvec2(floor(gl_FragCoord.xy));
|
|
82
|
+
fi(floor(gl_FragCoord.xy),int(aC ^ cB(uint(sequenceSeed))));
|
|
83
|
+
Ray ray=xj((floor(gl_FragCoord.xy)+sample2D(CAMERA_PIXEL))/viewportSize);
|
|
84
84
|
if(cameraApertureRadius>0.0) {
|
|
85
85
|
vec3 eye=viewInv[3].xyz, forward=-normalize(viewInv[2].xyz);
|
|
86
|
-
vec3
|
|
87
|
-
vec2
|
|
88
|
-
vec3 origin=(viewInv*vec4(
|
|
89
|
-
|
|
86
|
+
vec3 ju=eye+ray.d*(cameraFocusDistance/dot(ray.d,forward));
|
|
87
|
+
vec2 uV=cameraApertureRadius*kq(sample2D(CAMERA_LENS));
|
|
88
|
+
vec3 origin=(viewInv*vec4(uV,0.0,1.0)).xyz;
|
|
89
|
+
initRay(ray,origin,normalize(ju-origin));
|
|
90
90
|
}
|
|
91
91
|
SurfaceInteraction si; OpenPbrResolvedMaterial material;
|
|
92
|
-
if(!
|
|
92
|
+
if(!mC(ray,si,material)) return;
|
|
93
93
|
float depth=max(dot(si.position-viewInv[3].xyz,-normalize(viewInv[2].xyz)),0.0);
|
|
94
94
|
bool unsupported=material.materialType!=STANDARD || material.alpha<1.0 || material.coatWeight>0.0 || material.fuzzWeight>0.0 || material.specularAnisotropy>0.0 || material.subsurfaceWeight>0.0 || dot(material.mediumScattering,material.mediumScattering)>0.0 || material.bevel>0.0 || material.thinFilmWeight>0.0 || material.transmissionDispersionScale>0.0;
|
|
95
95
|
out_geometry+=vec4(depth,material.specularRoughness,material.baseMetalness,unsupported?1.0:0.0);
|
|
96
96
|
#ifdef AOV_REFLECTANCE
|
|
97
97
|
if((aovMask&24)!=0 && !unsupported){
|
|
98
|
-
vec3 normal=si.normal,face=si.faceNormal;float cosine=-dot(normal,ray.d),
|
|
98
|
+
vec3 normal=si.normal,face=si.faceNormal;float cosine=-dot(normal,ray.d),fa=-dot(face,ray.d);
|
|
99
99
|
if(material.thinWalled&&(material.transmissionWeight>0.0||material.subsurfaceWeight>0.0)){
|
|
100
|
-
if(cosine<0.0){normal=-normal;cosine=-cosine;}if(
|
|
100
|
+
if(cosine<0.0){normal=-normal;cosine=-cosine;}if(fa<0.0){face=-face;fa=-fa;}
|
|
101
101
|
}
|
|
102
|
-
if(
|
|
102
|
+
if(fa>=0.0&&cosine<0.0){normal=face;cosine=fa;}
|
|
103
103
|
if(cosine<0.0)normal=-normal;
|
|
104
104
|
material.inside=cosine<=0.0&&!material.thinWalled;material.relativeIor=cosine>0.0?1.0/material.specularIor:material.specularIor;
|
|
105
105
|
vec3 tangent=vec3(0.0);
|
|
106
106
|
#ifdef USE_TANGENT
|
|
107
107
|
tangent=si.tangent;
|
|
108
108
|
#endif
|
|
109
|
-
|
|
109
|
+
OpenPbrPreparedBsdf prepared=bV(tangent,material,-ray.d,normal);
|
|
110
110
|
vec3 diffuse,specular;aovReflectance(prepared,(aovMask&8)!=0,(aovMask&16)!=0,diffuse,specular);
|
|
111
111
|
out_diffuse+=vec4(diffuse,1.0);out_specular+=vec4(specular,1.0);
|
|
112
112
|
}
|
|
@@ -3,16 +3,16 @@
|
|
|
3
3
|
// Copyright (c) 2019 HOVER, MIT license; see LICENSES/RayTracingRenderer-MIT.txt.
|
|
4
4
|
// Shared primary-ray construction keeps beauty and catcher coverage aligned.
|
|
5
5
|
export default /* glsl */ `
|
|
6
|
-
Ray
|
|
6
|
+
Ray eT(vec2 coord) {
|
|
7
7
|
vec4 origin = viewProjectionInv * vec4(coord * 2.0 - 1.0, -1.0, 1.0);
|
|
8
8
|
vec4 target = viewProjectionInv * vec4(coord * 2.0 - 1.0, 1.0, 1.0);
|
|
9
9
|
Ray cam;
|
|
10
|
-
|
|
10
|
+
initRay(cam, origin.xyz / origin.w, normalize(target.xyz * origin.w - origin.xyz * target.w));
|
|
11
11
|
|
|
12
12
|
return cam;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
vec2
|
|
15
|
+
vec2 kq(vec2 p) {
|
|
16
16
|
p = 2.0 * p - 1.0;
|
|
17
17
|
bool greater = abs(p.x) > abs(p.y);
|
|
18
18
|
float r = greater ? p.x : p.y;
|
|
@@ -20,16 +20,16 @@ float theta = greater ? 0.25 * PI * p.y / p.x : PI * (0.5 - 0.25 * p.x / p.y);
|
|
|
20
20
|
return r * vec2(cos(theta), sin(theta));
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
Ray
|
|
24
|
-
Ray cam =
|
|
23
|
+
Ray ow() {
|
|
24
|
+
Ray cam = eT(v_Texcoord + te());
|
|
25
25
|
if (cameraApertureRadius > 0.0) {
|
|
26
26
|
|
|
27
27
|
vec3 eye = viewInv[3].xyz;
|
|
28
28
|
vec3 forward = -normalize(viewInv[2].xyz);
|
|
29
|
-
vec3
|
|
30
|
-
vec2
|
|
31
|
-
vec3 origin = vec3(viewInv * vec4(
|
|
32
|
-
|
|
29
|
+
vec3 ju = eye + cam.d * (cameraFocusDistance / dot(cam.d, forward));
|
|
30
|
+
vec2 sH = cameraApertureRadius * kq(sample2D(CAMERA_LENS));
|
|
31
|
+
vec3 origin = vec3(viewInv * vec4(sH, 0.0, 1.0));
|
|
32
|
+
initRay(cam, origin, normalize(ju - origin));
|
|
33
33
|
}
|
|
34
34
|
return cam;
|
|
35
35
|
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
declare const _default: "\nvec4 emissiveTexel(int i) { return fetchData(emissiveLightData,i,emissiveLightColumns); }\nvoid sampleEmissiveSceneLight(vec3 x, vec3 rnd, inout LightSampleRec ls) {\n ls.pdf=0.0;ls.isDelta=false;ls.sourceType=0;ls.sourceIndex=-1;\n if(emissiveChoiceCount<=0) return;\n float scaled=rnd.z*float(emissiveChoiceCount);int column=min(int(scaled),emissiveChoiceCount-1);\n vec4 first=emissiveTexel(emissiveChoiceOffset+column);\n int chosen=fract(scaled)<first.x?column:floatBitsToInt(first.y);\n vec4 choice=emissiveTexel(emissiveChoiceOffset+chosen);int kind=floatBitsToInt(choice.z),index=floatBitsToInt(choice.w);\n float pmf=emissiveTexel(emissivePmfOffset+chosen).x;\n if(kind==1) {\n#ifdef USE_ENVMAP\n sampleEnvLight(rnd.xy,ls);ls.pdf*=pmf;\n#endif\n } else if(kind==2) {\n#ifdef NUM_LIGHTS\n Light light=fetchLight(index);\n \n ls.sourceType=2;ls.sourceIndex=index;\n sampleAnalyticLight(light,x,rnd.xy,ls);ls.pdf*=pmf;\n#endif\n } else if(kind==3) {\n vec4 a=emissiveTexel(index*6),b=emissiveTexel(index*6+1),c=emissiveTexel(index*6+2);\n vec4 d=emissiveTexel(index*6+3),e=emissiveTexel(index*6+4),f=emissiveTexel(index*6+5);\n float u=sqrt(rnd.x);vec3 bary=vec3(1.0-u,u*(1.0-rnd.y),u*rnd.y);\n vec3 p=a.xyz*bary.x+b.xyz*bary.y+c.xyz*bary.z;\n ls.normal=normalize(cross(b.xyz-a.xyz,c.xyz-a.xyz));ls.direction=normalize(p-x);ls.dist=distance(x,p);\n float cosine=dot(ls.normal,-ls.direction);if(cosine<=0.0) return;\n OpenPbrResolvedMaterial m;\n getMaterial(m,int(c.w),bary.x*d.xy+bary.y*d.zw+bary.z*e.xy,bary.x*e.zw+bary.y*f.xy+bary.z*f.zw,0,vec3(1.0));\n ls.emission=m.emission;ls.pdf=pmf*ls.dist*ls.dist/max(b.w*cosine,1e-8);ls.sourceType=1;ls.sourceIndex=index;\n }\n}\n";
|
|
2
|
+
export default _default;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export default /* glsl */ `
|
|
2
|
+
vec4 ei(int i) { return fetchData(emissiveLightData,i,emissiveLightColumns); }
|
|
3
|
+
void jb(vec3 x, vec3 rnd, inout LightSampleRec ls) {
|
|
4
|
+
ls.pdf=0.0;ls.isDelta=false;ls.sourceType=0;ls.sourceIndex=-1;
|
|
5
|
+
if(emissiveChoiceCount<=0) return;
|
|
6
|
+
float scaled=rnd.z*float(emissiveChoiceCount);int column=min(int(scaled),emissiveChoiceCount-1);
|
|
7
|
+
vec4 first=ei(emissiveChoiceOffset+column);
|
|
8
|
+
int chosen=fract(scaled)<first.x?column:floatBitsToInt(first.y);
|
|
9
|
+
vec4 choice=ei(emissiveChoiceOffset+chosen);int kind=floatBitsToInt(choice.z),index=floatBitsToInt(choice.w);
|
|
10
|
+
float pmf=ei(emissivePmfOffset+chosen).x;
|
|
11
|
+
if(kind==1) {
|
|
12
|
+
#ifdef USE_ENVMAP
|
|
13
|
+
ig(rnd.xy,ls);ls.pdf*=pmf;
|
|
14
|
+
#endif
|
|
15
|
+
} else if(kind==2) {
|
|
16
|
+
#ifdef NUM_LIGHTS
|
|
17
|
+
Light light=fetchLight(index);
|
|
18
|
+
|
|
19
|
+
ls.sourceType=2;ls.sourceIndex=index;
|
|
20
|
+
sampleAnalyticLight(light,x,rnd.xy,ls);ls.pdf*=pmf;
|
|
21
|
+
#endif
|
|
22
|
+
} else if(kind==3) {
|
|
23
|
+
vec4 a=ei(index*6),b=ei(index*6+1),c=ei(index*6+2);
|
|
24
|
+
vec4 d=ei(index*6+3),e=ei(index*6+4),f=ei(index*6+5);
|
|
25
|
+
float u=sqrt(rnd.x);vec3 bary=vec3(1.0-u,u*(1.0-rnd.y),u*rnd.y);
|
|
26
|
+
vec3 p=a.xyz*bary.x+b.xyz*bary.y+c.xyz*bary.z;
|
|
27
|
+
ls.normal=normalize(cross(b.xyz-a.xyz,c.xyz-a.xyz));ls.direction=normalize(p-x);ls.dist=distance(x,p);
|
|
28
|
+
float cosine=dot(ls.normal,-ls.direction);if(cosine<=0.0) return;
|
|
29
|
+
OpenPbrResolvedMaterial m;
|
|
30
|
+
getMaterial(m,int(c.w),bary.x*d.xy+bary.y*d.zw+bary.z*e.xy,bary.x*e.zw+bary.y*f.xy+bary.z*f.zw,0,vec3(1.0));
|
|
31
|
+
ls.emission=m.emission;ls.pdf=pmf*ls.dist*ls.dist/max(b.w*cosine,1e-8);ls.sourceType=1;ls.sourceIndex=index;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
`;
|
|
35
|
+
//# sourceMappingURL=emissiveLight.glsl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emissiveLight.glsl.js","sourceRoot":"","sources":["../../../../src/renderer/glsl/chunks/emissiveLight.glsl.ts"],"names":[],"mappings":"AAAA,eAAe,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiCzB,CAAC","sourcesContent":["export default /* glsl */ `\nvec4 emissiveTexel(int i) { return fetchData(emissiveLightData,i,emissiveLightColumns); }\nvoid sampleEmissiveSceneLight(vec3 x, vec3 rnd, inout LightSampleRec ls) {\n ls.pdf=0.0;ls.isDelta=false;ls.sourceType=0;ls.sourceIndex=-1;\n if(emissiveChoiceCount<=0) return;\n float scaled=rnd.z*float(emissiveChoiceCount);int column=min(int(scaled),emissiveChoiceCount-1);\n vec4 first=emissiveTexel(emissiveChoiceOffset+column);\n int chosen=fract(scaled)<first.x?column:floatBitsToInt(first.y);\n vec4 choice=emissiveTexel(emissiveChoiceOffset+chosen);int kind=floatBitsToInt(choice.z),index=floatBitsToInt(choice.w);\n float pmf=emissiveTexel(emissivePmfOffset+chosen).x;\n if(kind==1) {\n#ifdef USE_ENVMAP\n sampleEnvLight(rnd.xy,ls);ls.pdf*=pmf;\n#endif\n } else if(kind==2) {\n#ifdef NUM_LIGHTS\n Light light=fetchLight(index);\n \n ls.sourceType=2;ls.sourceIndex=index;\n sampleAnalyticLight(light,x,rnd.xy,ls);ls.pdf*=pmf;\n#endif\n } else if(kind==3) {\n vec4 a=emissiveTexel(index*6),b=emissiveTexel(index*6+1),c=emissiveTexel(index*6+2);\n vec4 d=emissiveTexel(index*6+3),e=emissiveTexel(index*6+4),f=emissiveTexel(index*6+5);\n float u=sqrt(rnd.x);vec3 bary=vec3(1.0-u,u*(1.0-rnd.y),u*rnd.y);\n vec3 p=a.xyz*bary.x+b.xyz*bary.y+c.xyz*bary.z;\n ls.normal=normalize(cross(b.xyz-a.xyz,c.xyz-a.xyz));ls.direction=normalize(p-x);ls.dist=distance(x,p);\n float cosine=dot(ls.normal,-ls.direction);if(cosine<=0.0) return;\n OpenPbrResolvedMaterial m;\n getMaterial(m,int(c.w),bary.x*d.xy+bary.y*d.zw+bary.z*e.xy,bary.x*e.zw+bary.y*f.xy+bary.z*f.zw,0,vec3(1.0));\n ls.emission=m.emission;ls.pdf=pmf*ls.dist*ls.dist/max(b.w*cosine,1e-8);ls.sourceType=1;ls.sourceIndex=index;\n }\n}\n`;\n"]}
|