rayzee 10.0.0 → 11.1.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 +252 -44
- package/dist/ActiveColor-YvuQq44O.js +13 -0
- package/dist/ArchiveImporter-Hn35o6Z5.js +5145 -0
- package/dist/AssetConfig-DSEntE65.js +30 -0
- package/dist/BidirectionalIntegrator-CBw8hkeu.js +946 -0
- package/dist/BufferLayout-D_IBo2ci.js +150 -0
- package/dist/ColorManagement-oeEk7oSu.js +1488 -0
- package/dist/EngineEvents-Ci8dVWCP.js +73 -0
- package/dist/EngineIssues-CIZnXHsF.js +72 -0
- package/dist/FileFormats-sPGJeCRc.js +102 -0
- package/dist/Logger-dDDGj9Av.js +97 -0
- package/dist/{NeuralRetouch-CYgkQY8Z.js → NeuralRetouch-BzNpiVHZ.js} +8 -6
- package/dist/{NeuralSuperRes-PkgDLQcD.js → NeuralSuperRes-Bk7bHg2B.js} +55 -120
- package/dist/PathTracer-72XufKAr.js +29976 -0
- package/dist/PhysicalSky-BgjdV88k.js +1219 -0
- package/dist/RayzeeRenderer-1QRO97eq.js +3551 -0
- package/dist/SolarLimb-CPaeZVwz.js +721 -0
- package/dist/ToneMapGPU-CjU3osDd.js +177 -0
- package/dist/ViewTransforms-CYN7bq2w.js +255 -0
- package/dist/WorkingMatrix-C6y233hT.js +27 -0
- package/dist/ZipReader-gDSWr0I5.js +98 -0
- package/dist/addons/archives.es.js +3 -0
- package/dist/addons/bidirectional.es.js +2 -0
- package/dist/addons/color.es.js +3 -0
- package/dist/addons/formats.es.js +2 -0
- package/dist/addons/physical-sky.es.js +2 -0
- package/dist/addons/storage.es.js +3 -0
- package/dist/archiveFormats-tnAoUL1j.js +94 -0
- package/dist/identity-DrQsGT2o.js +39 -0
- package/dist/openStorage-DwcBRUj7.js +820 -0
- package/dist/rayzee-core.es.js +12 -0
- package/dist/rayzee.es.js +2551 -44024
- package/dist/rayzee.umd.js +528 -487
- package/dist/sceneCachePolicy-C67jbci-.js +443 -0
- package/dist/shared-BGBcSxBQ.js +17 -0
- package/package.json +23 -2
- package/src/Color/ActiveColor.js +34 -0
- package/src/Color/BasicColor.js +147 -0
- package/src/Color/ColorManagement.js +7 -31
- package/src/Color/ViewTransforms.js +5 -1
- package/src/EngineDefaults.js +62 -1029
- package/src/EngineEvents.js +2 -0
- package/src/EngineIssues.js +2 -0
- package/src/Headless.js +6 -5
- package/src/Passes/AIUpscaler.js +58 -141
- package/src/Passes/OIDNDenoiser.js +92 -65
- package/src/Passes/OIDNTemporalHistory.js +1 -1
- package/src/PathTracerApp.js +620 -4026
- package/src/Pipeline/PipelineContext.js +0 -4
- package/src/Platform.js +36 -0
- package/src/Processor/ArchiveCache.js +20 -7
- package/src/Processor/ArchiveImporter.js +1265 -0
- package/src/Processor/ArchiveReader.js +22 -4
- package/src/Processor/AssetLoader.js +327 -1763
- package/src/Processor/AtmosphereModel.js +1 -2
- package/src/Processor/BVHBuilder.js +14 -126
- package/src/Processor/BVHLeafFold.js +4 -6
- package/src/Processor/BVHRefitter.js +67 -46
- package/src/Processor/BufferLayout.js +291 -0
- package/src/Processor/EmissiveTriangleBuilder.js +1 -1
- package/src/Processor/EnvironmentExactTable.js +187 -0
- package/src/Processor/EquirectHDRInfo.js +30 -223
- package/src/Processor/FileFormats.js +116 -0
- package/src/Processor/GLTFDecoders.js +85 -0
- package/src/Processor/GLTFDiffuseTransmission.js +63 -0
- package/src/Processor/GeometryExtractor.js +15 -5
- package/src/Processor/HostMemory.js +7 -1
- package/src/Processor/IESParser.js +47 -35
- package/src/Processor/InstanceTable.js +1 -1
- package/src/Processor/KernelManager.js +35 -2
- package/src/Processor/MaterialPacking.js +10 -8
- package/src/Processor/PBRT/PBRTMaterials.js +254 -42
- package/src/Processor/PBRT/PBRTParser.js +49 -19
- package/src/Processor/PBRT/PBRTScattering.js +93 -0
- package/src/Processor/PBRT/PBRTSceneBuilder.js +1050 -75
- package/src/Processor/PBRT/PBRTTextureBake.js +179 -0
- package/src/Processor/PBRT/PFM.js +59 -0
- package/src/Processor/PackedRayBuffer.js +116 -9
- package/src/Processor/ParallelBVHBuilder.js +3 -6
- package/src/Processor/PhysicalSky.js +5 -4
- package/src/Processor/PlatformImageLoader.js +50 -6
- package/src/Processor/QueueManager.js +39 -5
- package/src/Processor/ReinsertionOptimizer.js +2 -2
- package/src/Processor/SceneMetadata.js +30 -5
- package/src/Processor/SceneProcessor.js +53 -62
- package/src/Processor/ShaderBuilder.js +6 -16
- package/src/Processor/SimpleSky.js +1 -62
- package/src/Processor/SolarLimb.js +3 -0
- package/src/Processor/SplitBLAS.js +1 -1
- package/src/Processor/StorageTexturePool.js +22 -1
- package/src/Processor/TLASBuilder.js +1 -3
- package/src/Processor/TextureBuckets.js +237 -0
- package/src/Processor/TextureCreator.js +181 -8
- package/src/Processor/ToneMapGPU.js +64 -15
- package/src/Processor/Workers/BVHRefitWorker.js +5 -2
- package/src/Processor/Workers/BVHSubtreeWorker.js +1 -34
- package/src/Processor/Workers/BVHWorker.js +5 -18
- package/src/Processor/Workers/CDFWorker.js +6 -183
- package/src/Processor/Workers/TexturesWorker.js +103 -18
- package/src/Processor/archiveFormats.js +7 -0
- package/src/Processor/utils.js +2 -1
- package/src/RayzeeRenderer.js +3900 -0
- package/src/RenderSettings.js +68 -62
- package/src/Stages/ASVGF.js +13 -14
- package/src/Stages/AutoExposure.js +17 -17
- package/src/Stages/BilateralFilter.js +2 -1
- package/src/Stages/Compositor.js +8 -23
- package/src/Stages/DenoiserSettings.js +182 -0
- package/src/Stages/EdgeFilter.js +2 -1
- package/src/Stages/MotionVector.js +1 -1
- package/src/Stages/NRD.js +11 -5
- package/src/Stages/NormalDepth.js +12 -8
- package/src/Stages/PathTracer.js +336 -43
- package/src/Stages/PathTracerStage.js +69 -66
- package/src/Stages/Variance.js +1 -1
- package/src/Storage/BLASCache.js +1 -1
- package/src/Storage/CDFCache.js +18 -17
- package/src/Storage/DownloadCache.js +1 -1
- package/src/Storage/SceneGraphCodec.js +46 -3
- package/src/Storage/SpillStore.js +1 -1
- package/src/Storage/StorageManager.js +45 -9
- package/src/Storage/areas.js +4 -0
- package/src/TSL/BVHTraversal.js +50 -25
- package/src/TSL/Bidirectional.js +208 -0
- package/src/TSL/BidirectionalLamps.js +132 -0
- package/src/TSL/Clearcoat.js +15 -6
- package/src/TSL/Common.js +20 -15
- package/src/TSL/ConnectKernel.js +167 -0
- package/src/TSL/Debugger.js +1 -1
- package/src/TSL/Displacement.js +4 -3
- package/src/TSL/EmissiveSampling.js +65 -18
- package/src/TSL/Environment.js +77 -106
- package/src/TSL/EnvironmentCDF.js +85 -39
- package/src/TSL/ExtendKernel.js +8 -3
- package/src/TSL/FinalWriteKernel.js +4 -4
- package/src/TSL/GenerateKernel.js +18 -4
- package/src/TSL/HitFacet.js +35 -5
- package/src/TSL/LightBVHSampling.js +40 -9
- package/src/TSL/LightGenerateKernel.js +293 -0
- package/src/TSL/LightGuide.js +198 -0
- package/src/TSL/LightSplatKernel.js +180 -0
- package/src/TSL/LightVisibility.js +111 -0
- package/src/TSL/LightsCore.js +13 -38
- package/src/TSL/LightsDirect.js +28 -29
- package/src/TSL/LightsIndirect.js +3 -1
- package/src/TSL/LightsSampling.js +239 -51
- package/src/TSL/MaterialEvaluation.js +113 -31
- package/src/TSL/MaterialProperties.js +44 -17
- package/src/TSL/MaterialTransmission.js +52 -47
- package/src/TSL/MergeKernel.js +224 -0
- package/src/TSL/PathTracerCore.js +65 -29
- package/src/TSL/Random.js +5 -1
- package/src/TSL/SceneResources.js +51 -0
- package/src/TSL/ShadeKernel.js +985 -101
- package/src/TSL/Struct.js +10 -0
- package/src/TSL/Sun.js +1 -1
- package/src/TSL/TextureSampling.js +66 -61
- package/src/addons/archives.js +14 -0
- package/src/addons/bidirectional.js +13 -0
- package/src/addons/color.js +32 -0
- package/src/addons/formats.js +16 -0
- package/src/addons/physicalSky.js +14 -0
- package/src/addons/storage.js +19 -0
- package/src/core.js +31 -0
- package/src/index.js +13 -23
- package/src/integrators/BidirectionalIntegrator.js +838 -0
- package/src/managers/AnimationManager.js +88 -6
- package/src/managers/CameraManager.js +103 -46
- package/src/managers/DenoisingManager.js +14 -10
- package/src/managers/EnvironmentManager.js +125 -103
- package/src/managers/GoboManager.js +9 -0
- package/src/managers/MaterialDataManager.js +48 -37
- package/src/managers/UniformManager.js +32 -10
- package/dist/ToneMapGPU-B6XIe3DU.js +0 -544
- package/dist/rolldown-runtime-CAFD8bLK.js +0 -11
- package/src/Processor/TreeletOptimizer.js +0 -574
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where each kind of light gets through, learned from the shadow-ray pick's own rays (LightsSampling lightPick):
|
|
3
|
+
* tries and visible counts per cell of space and facing. Shade reads the learned half, which no kernel writes during
|
|
4
|
+
* a frame, so a render repeats; it adds to the fresh half, folded into the learned one after each frame.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { Fn, float, int, uint, If, Return, instanceIndex, abs, ceil, exp2, floor, length, log2, max, select, sqrt, atomicAdd, atomicLoad, atomicStore } from 'three/tsl';
|
|
8
|
+
|
|
9
|
+
import { VISIBILITY_BASE, VISIBILITY_CELLS, VISIBILITY_KINDS, VISIBILITY_COUNTER_WORDS } from '../Processor/QueueManager.js';
|
|
10
|
+
import { pcgHash } from './Random.js';
|
|
11
|
+
|
|
12
|
+
export const VISIBILITY_KIND = { LAMPS: 0, ENVIRONMENT: 1, SUN: 2, EMITTERS: 3 };
|
|
13
|
+
|
|
14
|
+
const LEARNED = VISIBILITY_BASE;
|
|
15
|
+
const FRESH = VISIBILITY_BASE + VISIBILITY_COUNTER_WORDS;
|
|
16
|
+
const SLOTS = VISIBILITY_CELLS * VISIBILITY_KINDS;
|
|
17
|
+
// A cell is this share of its distance from the camera, rounded up to a power of two.
|
|
18
|
+
const CELL_SHARE = 1 / 32;
|
|
19
|
+
// Below it a kind is still picked now and then, so a light that comes into view is found again.
|
|
20
|
+
const MIN_SHARE = 1 / 64;
|
|
21
|
+
const HALVE_AT = 1 << 16;
|
|
22
|
+
|
|
23
|
+
const hashIn = ( h, v ) => pcgHash( { state: h.bitXor( v ) } );
|
|
24
|
+
|
|
25
|
+
/** The cell of a point and the side its surface faces. */
|
|
26
|
+
export const visibilityCell = ( p, n, cameraPosition ) => {
|
|
27
|
+
|
|
28
|
+
const level = ceil( log2( max( length( p.sub( cameraPosition ) ).mul( CELL_SHARE ), 1e-6 ) ) ).toVar();
|
|
29
|
+
const c = floor( p.div( exp2( level ) ) ).toVar();
|
|
30
|
+
const a = abs( n );
|
|
31
|
+
const facing = select( a.x.greaterThan( max( a.y, a.z ) ), select( n.x.greaterThan( 0.0 ), uint( 0 ), uint( 1 ) ),
|
|
32
|
+
select( a.y.greaterThan( a.z ), select( n.y.greaterThan( 0.0 ), uint( 2 ), uint( 3 ) ), select( n.z.greaterThan( 0.0 ), uint( 4 ), uint( 5 ) ) ) );
|
|
33
|
+
|
|
34
|
+
let h = pcgHash( { state: uint( int( level ).add( 1024 ) ) } );
|
|
35
|
+
h = hashIn( h, uint( int( c.x ) ) );
|
|
36
|
+
h = hashIn( h, uint( int( c.y ) ) );
|
|
37
|
+
h = hashIn( h, uint( int( c.z ) ) );
|
|
38
|
+
h = hashIn( h, facing );
|
|
39
|
+
return h.bitAnd( uint( VISIBILITY_CELLS - 1 ) ).toVar();
|
|
40
|
+
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const slot = ( cell, kind ) => cell.mul( uint( VISIBILITY_KINDS ) ).add( uint( kind ) ).mul( uint( 2 ) );
|
|
44
|
+
|
|
45
|
+
/** √ of the share of rays that got through: the pick's best weight against a light that is on or off. */
|
|
46
|
+
export const visibilityShare = ( counters, cell, kind ) => {
|
|
47
|
+
|
|
48
|
+
const at = uint( LEARNED ).add( slot( cell, kind ) ).toVar();
|
|
49
|
+
const tries = float( atomicLoad( counters.element( at ) ) );
|
|
50
|
+
const seen = float( atomicLoad( counters.element( at.add( uint( 1 ) ) ) ) );
|
|
51
|
+
return sqrt( max( seen.add( 0.5 ).div( tries.add( 1.0 ) ), MIN_SHARE ) );
|
|
52
|
+
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export const recordVisibility = ( counters, cell, kind, visible ) => {
|
|
56
|
+
|
|
57
|
+
const at = uint( FRESH ).add( slot( cell, kind ) ).toVar();
|
|
58
|
+
atomicAdd( counters.element( at ), uint( 1 ) );
|
|
59
|
+
If( visible, () => {
|
|
60
|
+
|
|
61
|
+
atomicAdd( counters.element( at.add( uint( 1 ) ) ), uint( 1 ) );
|
|
62
|
+
|
|
63
|
+
} );
|
|
64
|
+
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
/** Adds the frame's counts to the learned ones, halving both past HALVE_AT so the table keeps up with a change. */
|
|
68
|
+
export function buildVisibilityFoldKernel( { counters } ) {
|
|
69
|
+
|
|
70
|
+
return Fn( () => {
|
|
71
|
+
|
|
72
|
+
If( instanceIndex.greaterThanEqual( uint( SLOTS ) ), () => {
|
|
73
|
+
|
|
74
|
+
Return();
|
|
75
|
+
|
|
76
|
+
} );
|
|
77
|
+
|
|
78
|
+
const learned = uint( LEARNED ).add( instanceIndex.mul( uint( 2 ) ) ).toVar();
|
|
79
|
+
const fresh = uint( FRESH ).add( instanceIndex.mul( uint( 2 ) ) ).toVar();
|
|
80
|
+
const tries = atomicLoad( counters.element( learned ) ).add( atomicLoad( counters.element( fresh ) ) ).toVar();
|
|
81
|
+
const seen = atomicLoad( counters.element( learned.add( uint( 1 ) ) ) ).add( atomicLoad( counters.element( fresh.add( uint( 1 ) ) ) ) ).toVar();
|
|
82
|
+
If( tries.greaterThan( uint( HALVE_AT ) ), () => {
|
|
83
|
+
|
|
84
|
+
tries.assign( tries.shiftRight( uint( 1 ) ) );
|
|
85
|
+
seen.assign( seen.shiftRight( uint( 1 ) ) );
|
|
86
|
+
|
|
87
|
+
} );
|
|
88
|
+
atomicStore( counters.element( learned ), tries );
|
|
89
|
+
atomicStore( counters.element( learned.add( uint( 1 ) ) ), seen );
|
|
90
|
+
atomicStore( counters.element( fresh ), uint( 0 ) );
|
|
91
|
+
atomicStore( counters.element( fresh.add( uint( 1 ) ) ), uint( 0 ) );
|
|
92
|
+
|
|
93
|
+
} )().compute( SLOTS, [ 256 ] );
|
|
94
|
+
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** Forgets everything learned: a reset may have moved what blocks what. */
|
|
98
|
+
export function buildVisibilityClearKernel( { counters } ) {
|
|
99
|
+
|
|
100
|
+
const words = 2 * VISIBILITY_COUNTER_WORDS;
|
|
101
|
+
return Fn( () => {
|
|
102
|
+
|
|
103
|
+
If( instanceIndex.lessThan( uint( words ) ), () => {
|
|
104
|
+
|
|
105
|
+
atomicStore( counters.element( uint( LEARNED ).add( instanceIndex ) ), uint( 0 ) );
|
|
106
|
+
|
|
107
|
+
} );
|
|
108
|
+
|
|
109
|
+
} )().compute( words, [ 256 ] );
|
|
110
|
+
|
|
111
|
+
}
|
package/src/TSL/LightsCore.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Lights Core - Ported from lights_core.fs
|
|
2
2
|
// Light data structures, access functions, and utility functions
|
|
3
3
|
|
|
4
|
+
import { sceneResources } from './SceneResources.js';
|
|
4
5
|
import {
|
|
5
6
|
Fn, wgslFn,
|
|
6
7
|
vec2,
|
|
@@ -268,28 +269,14 @@ export const getSpotAttenuation = /*@__PURE__*/ wgslFn( `
|
|
|
268
269
|
// SPOT LIGHT GOBO (PROJECTION MASK) SAMPLING
|
|
269
270
|
// ================================================================================
|
|
270
271
|
|
|
271
|
-
// Module-level state for spot light gobo masks.
|
|
272
|
-
// Set by ShaderBuilder before graph construction.
|
|
273
|
-
let _goboMapsTexNode = null;
|
|
274
|
-
|
|
275
|
-
/**
|
|
276
|
-
* Set the DataArrayTexture node used to sample spot light gobo masks.
|
|
277
|
-
* Must be called before the shader graph is constructed.
|
|
278
|
-
* @param {TextureNode} node - TSL texture node for the gobo DataArrayTexture
|
|
279
|
-
*/
|
|
280
|
-
export function setGoboMapsTexture( node ) {
|
|
281
|
-
|
|
282
|
-
_goboMapsTexNode = node;
|
|
283
|
-
|
|
284
|
-
}
|
|
285
|
-
|
|
286
272
|
// Sample a spot light's gobo mask. Returns 1.0 if no gobo assigned.
|
|
287
273
|
// Projects the surface direction onto a plane perpendicular to the light's
|
|
288
274
|
// forward axis at unit distance; cone edge maps to UV ±0.5 around centre.
|
|
289
275
|
//
|
|
290
276
|
// `lightDir` = unit direction from surface TO light (matches `LightSample.direction`).
|
|
291
|
-
export const sampleSpotGoboMask = /*@__PURE__*/ Fn( ( [ light, lightDir ] ) => {
|
|
277
|
+
export const sampleSpotGoboMask = /*@__PURE__*/ Fn( ( [ light, lightDir ], builder ) => {
|
|
292
278
|
|
|
279
|
+
const { goboMaps } = sceneResources( builder );
|
|
293
280
|
const mask = float( 1.0 ).toVar();
|
|
294
281
|
|
|
295
282
|
If( light.goboIndex.greaterThanEqual( int( 0 ) ), () => {
|
|
@@ -319,13 +306,13 @@ export const sampleSpotGoboMask = /*@__PURE__*/ Fn( ( [ light, lightDir ] ) => {
|
|
|
319
306
|
const u = clamp( px.mul( invTan ).add( 0.5 ), float( 0.0 ), float( 1.0 ) );
|
|
320
307
|
const v = clamp( py.mul( invTan ).add( 0.5 ), float( 0.0 ), float( 1.0 ) );
|
|
321
308
|
|
|
322
|
-
if (
|
|
309
|
+
if ( goboMaps ) {
|
|
323
310
|
|
|
324
311
|
// Sample min(.r, .a) so masks encoded in either RGB-luminance
|
|
325
312
|
// or alpha (Kenney's "Transparent" variants store the shape in alpha
|
|
326
313
|
// with RGB=white) both produce the expected result.
|
|
327
314
|
// Sign of goboIntensity encodes inversion: negative = inverted, |value| = strength.
|
|
328
|
-
const tex = texture(
|
|
315
|
+
const tex = texture( goboMaps, vec2( u, v ) ).depth( light.goboIndex );
|
|
329
316
|
const sample = min( tex.r, tex.a );
|
|
330
317
|
const inverted = light.goboIntensity.lessThan( 0.0 );
|
|
331
318
|
const effective = select( inverted, float( 1.0 ).sub( sample ), sample );
|
|
@@ -353,8 +340,9 @@ export const sampleSpotGoboMask = /*@__PURE__*/ Fn( ( [ light, lightDir ] ) => {
|
|
|
353
340
|
// can cover any scene size by adjusting the scale.
|
|
354
341
|
//
|
|
355
342
|
// `surfacePoint` = world-space position of the surface being shaded.
|
|
356
|
-
export const sampleDirectionalGoboMask = /*@__PURE__*/ Fn( ( [ light, surfacePoint ] ) => {
|
|
343
|
+
export const sampleDirectionalGoboMask = /*@__PURE__*/ Fn( ( [ light, surfacePoint ], builder ) => {
|
|
357
344
|
|
|
345
|
+
const { goboMaps } = sceneResources( builder );
|
|
358
346
|
const mask = float( 1.0 ).toVar();
|
|
359
347
|
|
|
360
348
|
If( light.goboIndex.greaterThanEqual( int( 0 ) ), () => {
|
|
@@ -379,9 +367,9 @@ export const sampleDirectionalGoboMask = /*@__PURE__*/ Fn( ( [ light, surfacePoi
|
|
|
379
367
|
const uTiled = u.sub( u.floor() );
|
|
380
368
|
const vTiled = v.sub( v.floor() );
|
|
381
369
|
|
|
382
|
-
if (
|
|
370
|
+
if ( goboMaps ) {
|
|
383
371
|
|
|
384
|
-
const tex = texture(
|
|
372
|
+
const tex = texture( goboMaps, vec2( uTiled, vTiled ) ).depth( light.goboIndex );
|
|
385
373
|
const sample = min( tex.r, tex.a );
|
|
386
374
|
const inverted = light.goboIntensity.lessThan( 0.0 );
|
|
387
375
|
const effective = select( inverted, float( 1.0 ).sub( sample ), sample );
|
|
@@ -400,20 +388,6 @@ export const sampleDirectionalGoboMask = /*@__PURE__*/ Fn( ( [ light, surfacePoi
|
|
|
400
388
|
// IES PROFILE (PHOTOMETRIC INTENSITY) SAMPLING
|
|
401
389
|
// ================================================================================
|
|
402
390
|
|
|
403
|
-
// Module-level texture node for IES profile DataArrayTexture.
|
|
404
|
-
// Set by ShaderBuilder before graph construction.
|
|
405
|
-
let _iesProfilesTexNode = null;
|
|
406
|
-
|
|
407
|
-
/**
|
|
408
|
-
* Bind the DataArrayTexture node carrying all loaded IES profiles.
|
|
409
|
-
* @param {TextureNode} node
|
|
410
|
-
*/
|
|
411
|
-
export function setIESProfilesTexture( node ) {
|
|
412
|
-
|
|
413
|
-
_iesProfilesTexNode = node;
|
|
414
|
-
|
|
415
|
-
}
|
|
416
|
-
|
|
417
391
|
// Sample a spot light's IES profile. Returns a normalized multiplier in [0,1]
|
|
418
392
|
// (or 1.0 if no profile assigned).
|
|
419
393
|
//
|
|
@@ -421,8 +395,9 @@ export function setIESProfilesTexture( node ) {
|
|
|
421
395
|
// where V=0 is along the light's "forward" axis (the spot's direction).
|
|
422
396
|
//
|
|
423
397
|
// `lightDir` = unit direction from surface TO light (matches LightSample.direction).
|
|
424
|
-
export const sampleIESProfile = /*@__PURE__*/ Fn( ( [ light, lightDir ] ) => {
|
|
398
|
+
export const sampleIESProfile = /*@__PURE__*/ Fn( ( [ light, lightDir ], builder ) => {
|
|
425
399
|
|
|
400
|
+
const { iesProfiles } = sceneResources( builder );
|
|
426
401
|
const result = float( 1.0 ).toVar();
|
|
427
402
|
|
|
428
403
|
If( light.iesIndex.greaterThanEqual( int( 0 ) ), () => {
|
|
@@ -451,9 +426,9 @@ export const sampleIESProfile = /*@__PURE__*/ Fn( ( [ light, lightDir ] ) => {
|
|
|
451
426
|
const phi = atan( py, px );
|
|
452
427
|
const u = phi.div( float( 2.0 * Math.PI ) ).add( 0.5 );
|
|
453
428
|
|
|
454
|
-
if (
|
|
429
|
+
if ( iesProfiles ) {
|
|
455
430
|
|
|
456
|
-
const sample = texture(
|
|
431
|
+
const sample = texture( iesProfiles, vec2( u, v ) ).depth( light.iesIndex ).r;
|
|
457
432
|
// Blend between flat (1.0) and full profile by iesIntensity.
|
|
458
433
|
const strength = clamp( light.iesIntensity, float( 0.0 ), float( 1.0 ) );
|
|
459
434
|
result.assign( mix( float( 1.0 ), sample, strength ) );
|
package/src/TSL/LightsDirect.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// Direct lighting calculations including shadow ray tracing
|
|
3
3
|
// and contribution calculations for all light types.
|
|
4
4
|
|
|
5
|
+
import { sceneResources } from './SceneResources.js';
|
|
5
6
|
import {
|
|
6
7
|
Fn,
|
|
7
8
|
float,
|
|
@@ -28,43 +29,27 @@ import {
|
|
|
28
29
|
import { Ray, ShadowMaterial, HitInfo } from './Struct.js';
|
|
29
30
|
import {
|
|
30
31
|
REC709_LUMINANCE_COEFFICIENTS, getShadowMaterial, instanceRows,
|
|
31
|
-
instanceFaceNormalToWorld, triangleRow,
|
|
32
|
+
instanceFaceNormalToWorld, triangleRow, shadowFlagsSettle, offsetRayOrigin,
|
|
32
33
|
} from './Common.js';
|
|
33
34
|
import { fresnelDielectric } from './Fresnel.js';
|
|
34
35
|
import { calculateBeerLawAbsorption } from './MaterialTransmission.js';
|
|
35
36
|
import { getTransformedUV, sampleBucket } from './TextureSampling.js';
|
|
36
37
|
|
|
37
|
-
// Module-level state for alpha-cutout shadow testing.
|
|
38
|
-
// Set by PathTracer before shade-graph construction.
|
|
39
|
-
let _shadowAlbedoMaps = null;
|
|
40
|
-
|
|
41
|
-
export { setAlphaShadowsUniform } from './Common.js';
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Set the sRGB bucket texture node array for alpha-aware shadow rays (albedo alpha).
|
|
45
|
-
* Must be called before the shade graph is constructed.
|
|
46
|
-
* @param {Array} buckets - K sRGB bucket texture nodes
|
|
47
|
-
*/
|
|
48
|
-
export function setShadowAlbedoMaps( buckets ) {
|
|
49
|
-
|
|
50
|
-
_shadowAlbedoMaps = buckets;
|
|
51
|
-
|
|
52
|
-
}
|
|
53
|
-
|
|
54
38
|
// ================================================================================
|
|
55
39
|
// SHADOW RAY TRACING
|
|
56
40
|
// ================================================================================
|
|
57
41
|
|
|
58
42
|
// Note: traverseBVH is passed as a parameter to avoid circular dependency
|
|
59
|
-
|
|
43
|
+
const makeTraceShadowRay = ( refractiveBlocks ) => Fn( ( [
|
|
60
44
|
origin, dir, maxDist,
|
|
61
45
|
// BVH traversal function and textures passed as parameters
|
|
62
46
|
traverseBVHShadowFn,
|
|
63
47
|
bvhBuffer,
|
|
64
48
|
triangleBuffer,
|
|
65
49
|
materialBuffer,
|
|
66
|
-
] ) => {
|
|
50
|
+
], builder ) => {
|
|
67
51
|
|
|
52
|
+
const { alphaShadows, shadowAlbedoMaps } = sceneResources( builder );
|
|
68
53
|
const transmittance = float( 1.0 ).toVar();
|
|
69
54
|
const rayOrigin = origin.toVar();
|
|
70
55
|
const remainingDist = float( maxDist ).toVar();
|
|
@@ -93,7 +78,7 @@ export const traceShadowRay = Fn( ( [
|
|
|
93
78
|
// alphaMode/transparent/transmission/opacity all indicate a fully opaque surface.
|
|
94
79
|
// Short-circuits the 7-slot getShadowMaterial fetch and the whole alpha decision tree.
|
|
95
80
|
const flags = triangleRow( triangleBuffer, shadowHit.triangleIndex, 4 ).z;
|
|
96
|
-
If( shadowFlagsSettle( flags ), () => {
|
|
81
|
+
If( shadowFlagsSettle( flags, alphaShadows ), () => {
|
|
97
82
|
|
|
98
83
|
transmittance.assign( 0.0 );
|
|
99
84
|
Break();
|
|
@@ -111,14 +96,13 @@ export const traceShadowRay = Fn( ( [
|
|
|
111
96
|
// ---------------------------------------------------------------
|
|
112
97
|
const alphaCutout = tslBool( false ).toVar();
|
|
113
98
|
|
|
114
|
-
const alphaShadows = getAlphaShadowsUniform();
|
|
115
99
|
if ( alphaShadows ) If( alphaShadows.equal( int( 1 ) ), () => {
|
|
116
100
|
|
|
117
101
|
// Sample texture alpha once (shared by MASK and BLEND paths).
|
|
118
102
|
// Deferred UV: barycentrics in shadowHit.uv, triangle index in shadowHit.triangleIndex.
|
|
119
103
|
const texAlpha = float( 1.0 ).toVar();
|
|
120
104
|
|
|
121
|
-
if (
|
|
105
|
+
if ( shadowAlbedoMaps ) {
|
|
122
106
|
|
|
123
107
|
If( shadowMaterial.albedoMapIndex.greaterThanEqual( int( 0 ) ), () => {
|
|
124
108
|
|
|
@@ -129,7 +113,7 @@ export const traceShadowRay = Fn( ( [
|
|
|
129
113
|
const uvData2 = uintBitsToFloat( triangleRow( triangleBuffer, shadowHit.triangleIndex, 4 ).xy );
|
|
130
114
|
const hitUV = uvData1.xy.mul( baryW ).add( uvData1.zw.mul( baryU ) ).add( uvData2.mul( baryV ) );
|
|
131
115
|
const albedoUV = getTransformedUV( { uv: hitUV, transform: shadowMaterial.albedoTransform } );
|
|
132
|
-
texAlpha.assign( sampleBucket(
|
|
116
|
+
texAlpha.assign( sampleBucket( shadowAlbedoMaps, shadowMaterial.albedoMapIndex, albedoUV ).a );
|
|
133
117
|
|
|
134
118
|
} );
|
|
135
119
|
|
|
@@ -176,7 +160,12 @@ export const traceShadowRay = Fn( ( [
|
|
|
176
160
|
rayOrigin.assign( shadowHit.hitPoint.add( dir.mul( alphaEps ) ) );
|
|
177
161
|
remainingDist.subAssign( shadowHit.dst.add( alphaEps ) );
|
|
178
162
|
|
|
179
|
-
} ).ElseIf( shadowMaterial.transmission.greaterThan( 0.0 ), () => {
|
|
163
|
+
} ).ElseIf( shadowMaterial.transmission.greaterThan( 0.0 ), refractiveBlocks ? () => {
|
|
164
|
+
|
|
165
|
+
transmittance.assign( 0.0 );
|
|
166
|
+
Break();
|
|
167
|
+
|
|
168
|
+
} : () => {
|
|
180
169
|
|
|
181
170
|
// Deferred geometric-normal compute — refetch triangle positions and
|
|
182
171
|
// derive the normal here so opaque/alpha-cutout shadow hits don't pay
|
|
@@ -262,6 +251,11 @@ export const traceShadowRay = Fn( ( [
|
|
|
262
251
|
|
|
263
252
|
} );
|
|
264
253
|
|
|
254
|
+
export const traceShadowRay = /*@__PURE__*/ makeTraceShadowRay( false );
|
|
255
|
+
|
|
256
|
+
// For the bidirectional strategies: their light paths carry what refracts, so glass must block.
|
|
257
|
+
export const traceShadowRayRefractiveOpaque = /*@__PURE__*/ makeTraceShadowRay( true );
|
|
258
|
+
|
|
265
259
|
// ================================================================================
|
|
266
260
|
// RAY OFFSET CALCULATION
|
|
267
261
|
// ================================================================================
|
|
@@ -273,9 +267,14 @@ export const calculateRayOffset = Fn( ( [ hitPoint, normal ] ) => offsetRayOrigi
|
|
|
273
267
|
// LIGHT IMPORTANCE ESTIMATION
|
|
274
268
|
// ================================================================================
|
|
275
269
|
|
|
270
|
+
// A light's cosine for importance: either side for a surface that passes light through diffusely.
|
|
271
|
+
const importanceCosine = ( normal, direction, material ) => select(
|
|
272
|
+
material.diffuseTransmission.greaterThan( 0.0 ), abs( dot( normal, direction ) ), max( float( 0.0 ), dot( normal, direction ) ),
|
|
273
|
+
);
|
|
274
|
+
|
|
276
275
|
export const calculateDirectionalLightImportance = Fn( ( [ light, normal, material, bounceIndex ] ) => {
|
|
277
276
|
|
|
278
|
-
const NoL =
|
|
277
|
+
const NoL = importanceCosine( normal, light.direction, material );
|
|
279
278
|
const result = float( 0.0 ).toVar();
|
|
280
279
|
|
|
281
280
|
If( NoL.greaterThan( 0.0 ), () => {
|
|
@@ -312,7 +311,7 @@ export const estimateLightImportance = Fn( ( [ light, hitPoint, normal, material
|
|
|
312
311
|
const distSq = dist.mul( dist );
|
|
313
312
|
|
|
314
313
|
const lightDir = toLight.div( dist );
|
|
315
|
-
const NoL =
|
|
314
|
+
const NoL = importanceCosine( normal, lightDir, material );
|
|
316
315
|
const result = float( 0.0 ).toVar();
|
|
317
316
|
|
|
318
317
|
If( NoL.greaterThan( 0.0 ), () => {
|
|
@@ -366,7 +365,7 @@ export const calculatePointLightImportance = Fn( ( [ light, hitPoint, normal, ma
|
|
|
366
365
|
|
|
367
366
|
const dist = sqrt( distSq );
|
|
368
367
|
const lightDir = toLight.div( dist );
|
|
369
|
-
const NoL =
|
|
368
|
+
const NoL = importanceCosine( normal, lightDir, material );
|
|
370
369
|
|
|
371
370
|
If( NoL.greaterThan( 0.0 ), () => {
|
|
372
371
|
|
|
@@ -417,7 +416,7 @@ export const calculateSpotLightImportance = Fn( ( [ light, hitPoint, normal, mat
|
|
|
417
416
|
If( distSq.greaterThanEqual( 0.001 ), () => {
|
|
418
417
|
|
|
419
418
|
const lightDir = toLight.div( sqrt( distSq ) );
|
|
420
|
-
const NoL =
|
|
419
|
+
const NoL = importanceCosine( normal, lightDir, material );
|
|
421
420
|
|
|
422
421
|
If( NoL.greaterThan( 0.0 ), () => {
|
|
423
422
|
|
|
@@ -32,6 +32,8 @@ export const calculateIndirectLighting = Fn( ( [
|
|
|
32
32
|
brdfSampleDirection, brdfSamplePdf, brdfSampleValue,
|
|
33
33
|
// DirectionSample carries these so refraction throughput does not need a second sampler run.
|
|
34
34
|
isTransmission, brdfSampleColorWeight,
|
|
35
|
+
// Drawn through the surface by the diffuse transmission lobe: its cosine is taken below N.
|
|
36
|
+
isDiffuseTransmission,
|
|
35
37
|
rngState,
|
|
36
38
|
pixelCoord, resolution, frame, dimBase,
|
|
37
39
|
] ) => {
|
|
@@ -61,7 +63,7 @@ export const calculateIndirectLighting = Fn( ( [
|
|
|
61
63
|
//
|
|
62
64
|
// brdfSamplePdf is now the true mixture density (calculateBSDFSamplingPDF), so the
|
|
63
65
|
// estimator is just f·NoL/pdf and the MIS pairs share one function by construction.
|
|
64
|
-
const NoL = max( dot( N, brdfSampleDirection ), 0.0 ).toVar();
|
|
66
|
+
const NoL = select( isDiffuseTransmission, dot( N, brdfSampleDirection ).negate(), max( dot( N, brdfSampleDirection ), 0.0 ) ).toVar();
|
|
65
67
|
const pdf = max( brdfSamplePdf, MIN_PDF ).toVar();
|
|
66
68
|
|
|
67
69
|
r_direction.assign( brdfSampleDirection );
|