rayzee 11.0.0 → 11.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/README.md +1 -1
  2. package/dist/{ArchiveImporter-BRQvLggb.js → ArchiveImporter-CFcggGqi.js} +1525 -680
  3. package/dist/BidirectionalIntegrator-DIPN8lJW.js +946 -0
  4. package/dist/{NeuralRetouch-BCXylThH.js → NeuralRetouch-Doo3a4vY.js} +1 -1
  5. package/dist/{NeuralSuperRes-sZAeS142.js → NeuralSuperRes-B-rNIU_R.js} +1 -1
  6. package/dist/{PathTracer-CQPW06Mm.js → PathTracer-D_LmDeLh.js} +79 -74
  7. package/dist/{PhysicalSky-BvqCw_dy.js → PhysicalSky-DYffGJ3O.js} +1 -1
  8. package/dist/{RayzeeRenderer-COpwotpU.js → RayzeeRenderer-DWx7D714.js} +3 -3
  9. package/dist/addons/archives.es.js +1 -1
  10. package/dist/addons/bidirectional.es.js +1 -1
  11. package/dist/addons/physical-sky.es.js +1 -1
  12. package/dist/{archiveFormats-BZw7TiDp.js → archiveFormats-tnAoUL1j.js} +28 -9
  13. package/dist/rayzee-core.es.js +4 -4
  14. package/dist/rayzee.es.js +12 -12
  15. package/dist/rayzee.umd.js +43 -43
  16. package/dist/{sceneCachePolicy-BSSsKY98.js → sceneCachePolicy-Bk8sI5PZ.js} +1 -1
  17. package/package.json +1 -1
  18. package/src/PathTracerApp.js +1 -0
  19. package/src/Processor/ArchiveCache.js +19 -6
  20. package/src/Processor/ArchiveImporter.js +9 -3
  21. package/src/Processor/ArchiveReader.js +22 -4
  22. package/src/Processor/PBRT/PBRTMaterials.js +132 -8
  23. package/src/Processor/PBRT/PBRTParser.js +20 -3
  24. package/src/Processor/PBRT/PBRTScattering.js +93 -0
  25. package/src/Processor/PBRT/PBRTSceneBuilder.js +513 -49
  26. package/src/Processor/PBRT/PBRTTextureBake.js +32 -7
  27. package/src/Processor/SceneMetadata.js +30 -5
  28. package/src/RayzeeRenderer.js +3 -2
  29. package/src/Stages/PathTracer.js +3 -5
  30. package/src/TSL/Bidirectional.js +6 -2
  31. package/src/TSL/ConnectKernel.js +31 -11
  32. package/src/TSL/LightSplatKernel.js +22 -7
  33. package/src/TSL/MergeKernel.js +13 -7
  34. package/src/TSL/ShadeKernel.js +51 -30
  35. package/src/integrators/BidirectionalIntegrator.js +6 -1
  36. package/dist/BidirectionalIntegrator-9lZQxFVH.js +0 -934
@@ -133,8 +133,7 @@ export function buildShadeKernel( params ) {
133
133
  bidirectional: bdpt = null,
134
134
  // The hit-distance output, when a stage asked for it (PathTracer.requestOutput).
135
135
  hitDistanceEncode = null,
136
- // The material layers some material uses (MaterialDataManager.materialLayers); the rest compile out. Bidirectional
137
- // always leaves diffuse transmission out: its connections and light tracing do not cross surfaces yet.
136
+ // The material layers some material uses (MaterialDataManager.materialLayers); the rest compile out.
138
137
  materialLayers: layers = ALL_MATERIAL_LAYERS,
139
138
  // Fewer shadow rays a hit, emitters included: null (one per light kind) or a lightPick variant; path tracing only.
140
139
  shadowRays = null,
@@ -189,6 +188,11 @@ export function buildShadeKernel( params ) {
189
188
  // Emissive NEE's solid-angle density for a triangle's point, from whichever sampler it runs.
190
189
  const emissiveNEEPdf = ( triangle, dist, toLight, from, instanceLeaf ) => {
191
190
 
191
+ // As values: an expression is generated at its first read, inside the light tree's walk, which a one-node tree
192
+ // leaves before reaching it — every later read saw zero.
193
+ dist = float( dist ).toVar();
194
+ toLight = vec3( toLight ).toVar();
195
+ from = vec3( from ).toVar();
192
196
  const pdf = float( 0.0 ).toVar();
193
197
  If( lightBVHNodeCount.greaterThan( int( 0 ) ), () => {
194
198
 
@@ -880,7 +884,7 @@ export function buildShadeKernel( params ) {
880
884
  const material = RayTracingMaterial.wrap(
881
885
  getMaterial( int( hitMatIdx ), materialBuffer )
882
886
  ).toVar();
883
- if ( ! diffuseTransmission || bdpt ) {
887
+ if ( ! diffuseTransmission ) {
884
888
 
885
889
  material.diffuseTransmission.assign( 0.0 );
886
890
  material.diffuseTransmissionMapIndex.assign( int( - 1 ) );
@@ -1503,11 +1507,22 @@ export function buildShadeKernel( params ) {
1503
1507
  } );
1504
1508
  // Light from behind a surface that passes light through diffusely: its rays leave from the other side.
1505
1509
  // Compiled in only with the lobe (see `diffuseTransmission`).
1506
- const transmitting = diffuseTransmission && ! bdpt;
1510
+ const transmitting = diffuseTransmission;
1507
1511
  const transmitsDiffusely = transmitting ? material.diffuseTransmission.greaterThan( 0.0 ) : tslBool( false );
1508
1512
  const throughSurface = L => ( transmitting ? transmitsDiffusely.and( dot( N, L ).lessThan( 0.0 ) ).and( dot( L, NgeoFF ).lessThan( 0.0 ) ) : tslBool( false ) );
1509
1513
  const backOrigin = transmitting ? offsetRayOrigin( hitPoint, facetN.negate() ) : null;
1510
1514
  const originFor = ( L, front ) => ( transmitting ? select( throughSurface( L ), backOrigin, front ) : front );
1515
+ // Bidirectional NEE: whether light from L reaches the surface, its cosine, and the normal of the frame with L on
1516
+ // top, in which the density of drawing V back from L is read.
1517
+ const reaches = L => {
1518
+
1519
+ const inFront = dot( N, L ).greaterThan( 0.0 ).and( dot( L, NgeoFF ).greaterThan( 0.0 ) );
1520
+ return transmitting ? inFront.or( throughSurface( L ) ) : inFront;
1521
+
1522
+ };
1523
+
1524
+ const cosineTo = L => ( transmitting ? abs( dot( N, L ) ) : max( float( 0.0 ), dot( N, L ) ) );
1525
+ const facing = L => ( transmitting ? select( throughSurface( L ), N.negate(), N ) : N );
1511
1526
 
1512
1527
  // Two-sided shading: opaque path only (transmissive/SSS already continued). Decide the flip on the
1513
1528
  // GEOMETRIC normal — an inward-normal / double-sided mesh (GLB/PBRT) faces away as a whole — so a
@@ -1754,24 +1769,24 @@ export function buildShadeKernel( params ) {
1754
1769
 
1755
1770
  take( sampleLightBVHTriangleIndexed(
1756
1771
  hitPoint, N, rngState, _pixelCoord, resolution, frame, dimBase,
1757
- lightBuffer, lightBuffer, emissiveVec4Offset, triangleBuffer, bvhBuffer, tslBool( false ),
1772
+ lightBuffer, lightBuffer, emissiveVec4Offset, triangleBuffer, bvhBuffer, transmitsDiffusely,
1758
1773
  ) );
1759
1774
 
1760
1775
  } ).Else( () => {
1761
1776
 
1762
1777
  take( sampleEmissiveTriangleIndexed(
1763
1778
  hitPoint, N, rngState, _pixelCoord, resolution, frame, dimBase,
1764
- lightBuffer, emissiveVec4Offset, emissiveTriangleCount, emissiveTotalPower, triangleBuffer, bvhBuffer, tslBool( false ),
1779
+ lightBuffer, emissiveVec4Offset, emissiveTriangleCount, emissiveTotalPower, triangleBuffer, bvhBuffer, transmitsDiffusely,
1765
1780
  ) );
1766
1781
 
1767
1782
  } );
1768
1783
 
1769
- const NoL = max( float( 0.0 ), dot( N, lightDir ) ).toVar();
1784
+ const NoL = cosineTo( lightDir ).toVar();
1770
1785
  const side = triangleSide( triangleRow( triangleBuffer, lightTriangle, 4 ).z ).toVar();
1771
- If( valid.and( lightPdf.greaterThan( 0.0 ) ).and( NoL.greaterThan( 0.0 ) ).and( dot( lightDir, NgeoFF ).greaterThan( 0.0 ) )
1786
+ If( valid.and( lightPdf.greaterThan( 0.0 ) ).and( reaches( lightDir ) )
1772
1787
  .and( sideAccepts( side, dot( lightDir, windingN ) ) ), () => {
1773
1788
 
1774
- const rayOrigin = lightShadowOrigin( lightDir ).toVar();
1789
+ const rayOrigin = originFor( lightDir, lightShadowOrigin( lightDir ) ).toVar();
1775
1790
  const toSample = position.sub( rayOrigin ).toVar();
1776
1791
  const shadowDist = length( toSample ).toVar();
1777
1792
  const visibility = traceShadowRayRefractiveOpaque(
@@ -1783,7 +1798,7 @@ export function buildShadeKernel( params ) {
1783
1798
 
1784
1799
  const brdfVal = evaluateMaterialResponse( V, lightDir, N, material );
1785
1800
  const forward = calculateMaterialPDF( V, lightDir, N, material );
1786
- const reverse = calculateMaterialPDF( lightDir, V, N, material );
1801
+ const reverse = calculateMaterialPDF( lightDir, V, facing( lightDir ), material );
1787
1802
  // Emission density over NEE's, both seen from here; the light's cosine cancels.
1788
1803
  const emissionOverDirect = select( bdpt.lightPaths.greaterThan( uint( 0 ) ),
1789
1804
  emitterAreaPdf( emission, emissiveTotalPower, float( 1.0 ).sub( bdpt.sunPick ) )
@@ -1815,11 +1830,11 @@ export function buildShadeKernel( params ) {
1815
1830
 
1816
1831
  const lightDir = sampleSunDisc( sunDirection, sunParams, getRandomSample2D( _pixelCoord, int( 0 ), dimBase.add( int( 9 ) ), rngState, resolution, frame ) ).toVar();
1817
1832
  const radiance = sunRadianceToward( lightDir, sunDirection, sunRadiance, sunParams ).mul( environmentIntensity ).toVar();
1818
- const NoL = max( float( 0.0 ), dot( N, lightDir ) ).toVar();
1819
- If( radiance.x.add( radiance.y ).add( radiance.z ).greaterThan( 0.0 ).and( NoL.greaterThan( 0.0 ) ).and( dot( lightDir, NgeoFF ).greaterThan( 0.0 ) ), () => {
1833
+ const NoL = cosineTo( lightDir ).toVar();
1834
+ If( radiance.x.add( radiance.y ).add( radiance.z ).greaterThan( 0.0 ).and( reaches( lightDir ) ), () => {
1820
1835
 
1821
1836
  const visibility = traceShadowRayRefractiveOpaque(
1822
- lightShadowOrigin( lightDir ), lightDir, float( 1e20 ),
1837
+ originFor( lightDir, lightShadowOrigin( lightDir ) ), lightDir, float( 1e20 ),
1823
1838
  traverseBVHShadow, bvhBuffer, triangleBuffer, materialBuffer,
1824
1839
  ).toVar();
1825
1840
 
@@ -1827,7 +1842,7 @@ export function buildShadeKernel( params ) {
1827
1842
 
1828
1843
  const brdfVal = evaluateMaterialResponse( V, lightDir, N, material );
1829
1844
  const forward = calculateMaterialPDF( V, lightDir, N, material );
1830
- const reverse = calculateMaterialPDF( lightDir, V, N, material );
1845
+ const reverse = calculateMaterialPDF( lightDir, V, facing( lightDir ), material );
1831
1846
  const emissionOverDirect = select( bdpt.lightPaths.greaterThan( uint( 0 ) ),
1832
1847
  sunEmissionPdf( bdpt, sunParams, guidedDiscPdf( bdpt, bdpt.guideTexture, lightDir, hitPoint ) ).mul( sunParams.y ).mul( abs( dot( lightDir, exactFacetN ) ) ), float( 0.0 ) );
1833
1848
  const weight = misWeight( mis( forward.mul( sunParams.y ) ), misPartial( emissionOverDirect, subpath, reverse ) );
@@ -1865,19 +1880,18 @@ export function buildShadeKernel( params ) {
1865
1880
  const radiance = sampleEnvironment( {
1866
1881
  tex: envTexture, samp: sampler( envTexture ), direction: lightDir, environmentMatrix: envMatrix, environmentIntensity, enableEnvironmentLight: float( 1.0 ),
1867
1882
  } ).xyz.toVar();
1868
- const NoL = max( float( 0.0 ), dot( N, lightDir ) ).toVar();
1869
- If( lightPdf.greaterThan( 0.0 ).and( radiance.x.add( radiance.y ).add( radiance.z ).greaterThan( 0.0 ) ).and( NoL.greaterThan( 0.0 ) )
1870
- .and( dot( lightDir, NgeoFF ).greaterThan( 0.0 ) ), () => {
1883
+ const NoL = cosineTo( lightDir ).toVar();
1884
+ If( lightPdf.greaterThan( 0.0 ).and( radiance.x.add( radiance.y ).add( radiance.z ).greaterThan( 0.0 ) ).and( reaches( lightDir ) ), () => {
1871
1885
 
1872
1886
  const visibility = traceShadowRayRefractiveOpaque(
1873
- lightShadowOrigin( lightDir ), lightDir, float( 1e20 ), traverseBVHShadow, bvhBuffer, triangleBuffer, materialBuffer,
1887
+ originFor( lightDir, lightShadowOrigin( lightDir ) ), lightDir, float( 1e20 ), traverseBVHShadow, bvhBuffer, triangleBuffer, materialBuffer,
1874
1888
  ).toVar();
1875
1889
 
1876
1890
  If( visibility.greaterThan( 0.0 ), () => {
1877
1891
 
1878
1892
  const brdfVal = evaluateMaterialResponse( V, lightDir, N, material );
1879
1893
  const forward = calculateMaterialPDF( V, lightDir, N, material );
1880
- const reverse = calculateMaterialPDF( lightDir, V, N, material );
1894
+ const reverse = calculateMaterialPDF( lightDir, V, facing( lightDir ), material );
1881
1895
  const lead = select( bdpt.lightPaths.greaterThan( uint( 0 ) ),
1882
1896
  bdpt.envPick.mul( guidedDiscPdf( bdpt, bdpt.guideTexture, lightDir, hitPoint ) ).mul( abs( dot( lightDir, exactFacetN ) ) ), float( 0.0 ) );
1883
1897
  const weight = misWeight( mis( forward.div( lightPdf ) ), misPartial( lead, subpath, reverse ) );
@@ -1964,11 +1978,11 @@ export function buildShadeKernel( params ) {
1964
1978
 
1965
1979
  } );
1966
1980
 
1967
- const NoL = max( float( 0.0 ), dot( N, lightDir ) ).toVar();
1968
- If( valid.and( lightPdf.greaterThan( 0.0 ) ).and( NoL.greaterThan( 0.0 ) ).and( dot( lightDir, NgeoFF ).greaterThan( 0.0 ) ), () => {
1981
+ const NoL = cosineTo( lightDir ).toVar();
1982
+ If( valid.and( lightPdf.greaterThan( 0.0 ) ).and( reaches( lightDir ) ), () => {
1969
1983
 
1970
1984
  const atInfinity = pick.kind.equal( int( LIGHT_TYPE_DIRECTIONAL ) );
1971
- const shadowOrigin = lightShadowOrigin( lightDir ).toVar();
1985
+ const shadowOrigin = originFor( lightDir, lightShadowOrigin( lightDir ) ).toVar();
1972
1986
  const toSample = hitPoint.add( lightDir.mul( dist ) ).sub( shadowOrigin ).toVar();
1973
1987
  const shadowDist = length( toSample ).toVar();
1974
1988
  const visibility = traceShadowRayRefractiveOpaque(
@@ -1980,7 +1994,7 @@ export function buildShadeKernel( params ) {
1980
1994
 
1981
1995
  const brdfVal = evaluateMaterialResponse( V, lightDir, N, material );
1982
1996
  const forward = calculateMaterialPDF( V, lightDir, N, material );
1983
- const reverse = calculateMaterialPDF( lightDir, V, N, material );
1997
+ const reverse = calculateMaterialPDF( lightDir, V, facing( lightDir ), material );
1984
1998
  const lead = select( bdpt.lightPaths.greaterThan( uint( 0 ) ), emissionOverDirect.mul( abs( dot( lightDir, exactFacetN ) ) ), float( 0.0 ) );
1985
1999
  const wLight = select( pick.kind.equal( int( LIGHT_TYPE_AREA ) ), mis( forward.div( lightPdf ) ), float( 0.0 ) );
1986
2000
 
@@ -2165,14 +2179,18 @@ export function buildShadeKernel( params ) {
2165
2179
 
2166
2180
  If( isLight, () => {
2167
2181
 
2182
+ const side = triangleSide( triangleRow( triangleBuffer, int( hitTriIdx ), 4 ).z ).toVar();
2183
+ const cosWinding = dot( direction, windingNormal( triangleBuffer, bvhBuffer, int( hitTriIdx ), hitInstance ) ).toVar();
2184
+ const nearCulled = select( sideAccepts( side, cosWinding ), uint( 0 ), uint( 1 ) );
2185
+ const cullFlags = transmitting ? nearCulled.bitOr( select( sideAccepts( side, cosWinding.negate() ), uint( 0 ), uint( 2 ) ) ) : nearCulled;
2168
2186
  // The path's vertex count rides in its first slot.
2169
2187
  const first = rayID.mul( bdpt.slotsPerPath ).toVar();
2170
2188
  writeVertexRecord( hitBufferRW, cachedVertex( first.add( uint( cameraDepth ) ) ), {
2171
2189
  position: hitPoint, tag: uint( 0 ), throughput: throughput.mul( readLightOrigin( hitBufferRW, rayID ).scale ),
2172
2190
  V, N, facetN: exactFacetN, materialIndex: hitMatIdx, uv: samplingUV, dVCM: subpath.dVCM, dVC: subpath.dVC,
2173
- // 1: a camera on this side would cull the face, so light tracing must not show it.
2174
- extra: select( sideAccepts( triangleSide( triangleRow( triangleBuffer, int( hitTriIdx ), 4 ).z ),
2175
- dot( direction, windingNormal( triangleBuffer, bvhBuffer, int( hitTriIdx ), hitInstance ) ) ), uint( 0 ), uint( 1 ) ),
2191
+ // Bit 0: a camera on this side would cull the face, so light tracing must not show it; bit 1: one on the
2192
+ // far side would, which only light passing through the surface (diffuse transmission) can reach.
2193
+ extra: cullFlags,
2176
2194
  } );
2177
2195
  writeLightPathLength( hitBufferRW, cachedVertex( first ), bdpt.lightTag, uint( cameraDepth ).add( uint( 1 ) ) );
2178
2196
 
@@ -2225,8 +2243,10 @@ export function buildShadeKernel( params ) {
2225
2243
 
2226
2244
  } ).Else( () => {
2227
2245
 
2228
- throughput.mulAssign( evaluateMaterialResponse( bounceDir, V, N, material )
2229
- .mul( max( dot( N, bounceDir ), 0.0 ) ).div( max( brdfPdf, MIN_PDF ) ).mul( correction ) );
2246
+ // A transmission draw leaves from the far side: read the BSDF in the frame with bounceDir on top.
2247
+ const cosOut = transmitting ? select( brdfIsDiffuseTransmission, dot( N, bounceDir ).negate(), max( dot( N, bounceDir ), 0.0 ) ) : max( dot( N, bounceDir ), 0.0 );
2248
+ throughput.mulAssign( evaluateMaterialResponse( bounceDir, V, transmitting ? select( brdfIsDiffuseTransmission, N.negate(), N ) : N, material )
2249
+ .mul( cosOut ).div( max( brdfPdf, MIN_PDF ) ).mul( correction ) );
2230
2250
 
2231
2251
  } );
2232
2252
 
@@ -2285,7 +2305,8 @@ export function buildShadeKernel( params ) {
2285
2305
 
2286
2306
  } ).Else( () => {
2287
2307
 
2288
- misOnScatter( subpath, cosOut, calculateMaterialPDF( V, bounceDir, N, material ), calculateMaterialPDF( bounceDir, V, N, material ) );
2308
+ misOnScatter( subpath, cosOut, calculateMaterialPDF( V, bounceDir, N, material ),
2309
+ calculateMaterialPDF( bounceDir, V, transmitting ? select( brdfIsDiffuseTransmission, N.negate(), N ) : N, material ) );
2289
2310
 
2290
2311
  } );
2291
2312
 
@@ -2296,7 +2317,7 @@ export function buildShadeKernel( params ) {
2296
2317
 
2297
2318
  if ( bdpt ) If( isLight.not().and( numAreaLights.greaterThan( int( 0 ) ) ), () => {
2298
2319
 
2299
- const connectible = specularScatter.not().and( dot( N, bounceDir ).greaterThan( 0.0 ) ).and( dot( bounceDir, NgeoFF ).greaterThan( 0.0 ) );
2320
+ const connectible = specularScatter.not().and( reaches( bounceDir ) );
2300
2321
  bidirectionalAreaHit( newOrigin, bounceDir, ( light ) => select( connectible, select( lampTotal.greaterThan( 0.0 ),
2301
2322
  estimateLightImportance( light, hitPoint, N, material ).div( max( lampTotal, 1e-30 ) ),
2302
2323
  float( 1.0 ).div( max( float( lampCount( lamps ) ), 1.0 ) ) ), float( 0.0 ) ) );
@@ -196,8 +196,10 @@ export class BidirectionalIntegrator {
196
196
 
197
197
  const {
198
198
  km, qm, pb, counters, bounceCountsBuf, wfCurrentBounce, copyReadB, copyWriteA, maxRays, w, own,
199
- freshLight, freshTri, freshBvh, freshMat, freshEnvTex, freshEnvCDF,
199
+ freshLight, freshTri, freshBvh, freshMat, freshEnvTex, freshEnvCDF, materialLayers,
200
200
  } = ctx;
201
+ // Whether some material passes light through diffusely: its strategies then cross surfaces.
202
+ const transmits = materialLayers?.diffuseTransmission ?? true;
201
203
 
202
204
  const bd = this.uniforms;
203
205
  const n = qm.MAX_BOUNCE_SNAPSHOTS;
@@ -291,6 +293,7 @@ export class BidirectionalIntegrator {
291
293
  globalIlluminationIntensity: this.pt.globalIlluminationIntensity,
292
294
  fireflyThreshold: this.pt.fireflyThreshold,
293
295
  mergeVm: bd.merging ? ( p ) => mergeVmAt( bd, p ) : null,
296
+ diffuseTransmission: transmits,
294
297
  } )() ).compute( [ Math.ceil( maxRays / CONNECT_WG_SIZE ), 1, 1 ], [ CONNECT_WG_SIZE, 1, 1 ] ) );
295
298
 
296
299
  if ( bd.merging ) {
@@ -314,6 +317,7 @@ export class BidirectionalIntegrator {
314
317
  globalIlluminationIntensity: this.pt.globalIlluminationIntensity,
315
318
  fireflyThreshold: this.pt.fireflyThreshold,
316
319
  accumFrame: this.pt.frame,
320
+ diffuseTransmission: transmits,
317
321
  } )() ).compute( [ Math.ceil( maxRays / MERGE_WG_SIZE ), 1, 1 ], [ MERGE_WG_SIZE, 1, 1 ] ) );
318
322
 
319
323
  }
@@ -342,6 +346,7 @@ export class BidirectionalIntegrator {
342
346
  accumFrame: this.pt.frame,
343
347
  frame: this.pt.seedFrame,
344
348
  mergeVm: bd.merging ? ( p ) => mergeVmAt( bd, p ) : null,
349
+ diffuseTransmission: transmits,
345
350
  } )() ).compute( [ Math.ceil( this._lightCacheSlots / LIGHT_SPLAT_WG_SIZE ), 1, 1 ], [ LIGHT_SPLAT_WG_SIZE, 1, 1 ] ) );
346
351
 
347
352
  km.register( 'splatResolve', buildSplatResolveKernel( {