rayzee 7.20.3 → 7.21.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/dist/rayzee.es.js +2621 -2683
- package/dist/rayzee.umd.js +60 -58
- package/package.json +1 -1
- package/src/EngineDefaults.js +3 -2
- package/src/PathTracerApp.js +7 -0
- package/src/Pipeline/BindingAudit.js +178 -0
- package/src/Pipeline/RenderPipeline.js +5 -2
- package/src/Processor/CameraOptimizer.js +0 -5
- package/src/Processor/PackedRayBuffer.js +33 -8
- package/src/Stages/ASVGF.js +10 -10
- package/src/Stages/BilateralFilter.js +70 -11
- package/src/Stages/EdgeFilter.js +44 -6
- package/src/Stages/NormalDepth.js +10 -2
- package/src/Stages/PathTracer.js +7 -3
- package/src/Stages/PathTracerStage.js +15 -46
- package/src/TSL/Common.js +1 -47
- package/src/TSL/EmissiveSampling.js +40 -44
- package/src/TSL/LightsCore.js +3 -0
- package/src/TSL/LightsDirect.js +4 -4
- package/src/TSL/LightsSampling.js +138 -327
- package/src/TSL/PathTracerCore.js +2 -2
- package/src/TSL/Random.js +2 -2
- package/src/TSL/ShadeKernel.js +39 -17
- package/src/TSL/Struct.js +0 -10
- package/src/index.js +5 -0
- package/src/managers/EnvironmentManager.js +0 -5
- package/src/managers/UniformManager.js +4 -1
package/src/TSL/Random.js
CHANGED
|
@@ -132,7 +132,7 @@ export const RandomPointInCircle = ( rngState ) => {
|
|
|
132
132
|
// +6 subsurface HG scatter dir (ShadeKernel)
|
|
133
133
|
// +7 ground-catcher cosine BSDF (ShadeKernel)
|
|
134
134
|
// +8 indirect-strategy direction (LightsIndirect)
|
|
135
|
-
// 1D +0 {lights,BRDF} strategy
|
|
135
|
+
// 1D +0 (free — was the {lights,BRDF} stochastic strategy pick)
|
|
136
136
|
// +1 emissive-triangle pick (EmissiveSampling / LightBVHSampling)
|
|
137
137
|
// +2 BSDF lobe selection (ShadeKernel)
|
|
138
138
|
// +3 Russian roulette (PathTracerCore)
|
|
@@ -155,7 +155,7 @@ export const RandomPointInCircle = ( rngState ) => {
|
|
|
155
155
|
// Draws whose COUNT varies per pixel cannot sit in a per-bounce block without overflowing into
|
|
156
156
|
// the next bounce's dimensions, so they live above AUX_BASE:
|
|
157
157
|
// AUX_BASE + 0..63 env-backdrop blur taps (ShadeKernel)
|
|
158
|
-
// AUX_BASE + 64..
|
|
158
|
+
// AUX_BASE + 64.. light reservoir, one dimension per scene light (LightsSampling)
|
|
159
159
|
export const SAMPLER_DIMS_PER_BOUNCE = 32;
|
|
160
160
|
export const SAMPLER_DIM_AUX_BASE = 4096;
|
|
161
161
|
|
package/src/TSL/ShadeKernel.js
CHANGED
|
@@ -53,6 +53,7 @@ import {
|
|
|
53
53
|
readMediumStack, writeMediumStack, readMediumSigmaA, writeMediumSigmaA,
|
|
54
54
|
readPathBounces, readSssSteps, readSSSMedium, writeSSSMedium,
|
|
55
55
|
readTransparentCount,
|
|
56
|
+
readMisRayT,
|
|
56
57
|
readHitDistance, readHitBarycentrics, readHitNormal,
|
|
57
58
|
readHitMaterialIndex, readHitTriangleIndex,
|
|
58
59
|
writeRayOriginMeta, writeRayDirFlags, writeRayThroughputPdf, writeRayRadiance,
|
|
@@ -79,7 +80,7 @@ export function buildShadeKernel( params ) {
|
|
|
79
80
|
counters,
|
|
80
81
|
activeIndicesRO,
|
|
81
82
|
envTexture, environmentIntensity, envMatrix,
|
|
82
|
-
enableEnvironmentLight,
|
|
83
|
+
enableEnvironmentLight,
|
|
83
84
|
groundProjectionEnabled, groundProjectionRadius, groundProjectionHeight, groundProjectionLevel,
|
|
84
85
|
enableGroundCatcher, groundCatcherHeight,
|
|
85
86
|
envTotalSum, envCompensationDelta, envResolution,
|
|
@@ -94,6 +95,10 @@ export function buildShadeKernel( params ) {
|
|
|
94
95
|
globalIlluminationIntensity,
|
|
95
96
|
cameraProjectionMatrix, cameraViewMatrix,
|
|
96
97
|
fireflyThreshold, frame, resolution,
|
|
98
|
+
// Accumulation index, NOT the free-running seed counter `frame` rides. The firefly clamp
|
|
99
|
+
// relaxes as sqrt(frame+1) so its bias decays as a render converges; keying that off the
|
|
100
|
+
// seed axis let it grow for the whole session and disabled suppression outright.
|
|
101
|
+
accumFrame,
|
|
97
102
|
chunkRowBase, // chunked path pool: global pixel = chunkRowBase·W + localSlot (rayID). See spec.
|
|
98
103
|
emissiveTriangleCount, emissiveVec4Offset, emissiveTotalPower,
|
|
99
104
|
emissiveBoost, totalTriangleCount, enableEmissiveTriangleSampling,
|
|
@@ -405,7 +410,7 @@ export function buildShadeKernel( params ) {
|
|
|
405
410
|
|
|
406
411
|
// MIS weight for implicit env hit — prevents double-counting with NEE
|
|
407
412
|
const envMisWeight = float( 1.0 ).toVar();
|
|
408
|
-
If( isBackdropView.not()
|
|
413
|
+
If( isBackdropView.not(), () => {
|
|
409
414
|
|
|
410
415
|
const prevBouncePdf = readRayPdf( rayBufferRW, rayID );
|
|
411
416
|
If( prevBouncePdf.greaterThan( 0.0 ), () => {
|
|
@@ -440,7 +445,7 @@ export function buildShadeKernel( params ) {
|
|
|
440
445
|
currentRadiance.xyz.add(
|
|
441
446
|
regularizePathContribution(
|
|
442
447
|
throughput.mul( envColor ).mul( envScale ),
|
|
443
|
-
fireflyPathLen, fireflyThreshold, int(
|
|
448
|
+
fireflyPathLen, fireflyThreshold, int( accumFrame ),
|
|
444
449
|
),
|
|
445
450
|
),
|
|
446
451
|
currentRadiance.w
|
|
@@ -927,7 +932,10 @@ export function buildShadeKernel( params ) {
|
|
|
927
932
|
} );
|
|
928
933
|
|
|
929
934
|
} );
|
|
930
|
-
|
|
935
|
+
// Alpha skip keeps the direction, so the MIS origin is recoverable: accumulate the segment.
|
|
936
|
+
// Any redirection (refraction/reflection/SSS) breaks the line — reset.
|
|
937
|
+
const misRayT = select( interaction.isAlphaSkip, readMisRayT( rayBufferRW, rayID ).add( hitDist ), float( 0.0 ) );
|
|
938
|
+
writeRayOriginMeta( rayBufferRW, rayID, newOrigin, cameraDepth, sssSteps, transparentCount, misRayT );
|
|
931
939
|
writeRayDirFlags( rayBufferRW, rayID, interaction.direction, flags );
|
|
932
940
|
// Free bounce: preserve prevBouncePdf (megakernel keeps the last opaque-scatter pdf across
|
|
933
941
|
// transmission/alpha-skip/SSS-boundary). Writing 1.0 corrupts the next bounce's env/emissive MIS,
|
|
@@ -980,18 +988,24 @@ export function buildShadeKernel( params ) {
|
|
|
980
988
|
// MIS partner pdf MUST match the actual NEE sampler: re-walk the Light BVH descent
|
|
981
989
|
// when it is active, else use the flat-CDF pdf. Mismatching them breaks MIS
|
|
982
990
|
// partition-of-unity → a real bias (see calculateLightBVHPdf).
|
|
991
|
+
// Evaluate it at the scatter point that produced prevBouncePdf — alpha skips moved
|
|
992
|
+
// the ray origin, and the skip-point pdf under-counts dist² so full-Le BSDF hits
|
|
993
|
+
// pass nearly unweighted (fireflies on emitters inside alpha-blend shades).
|
|
994
|
+
const misT = readMisRayT( rayBufferRW, rayID ).toVar();
|
|
995
|
+
const misOrigin = origin.sub( direction.mul( misT ) ).toVar();
|
|
996
|
+
const misDist = hitDist.add( misT ).toVar();
|
|
983
997
|
const lightPdf = float( 0.0 ).toVar();
|
|
984
998
|
If( lightBVHNodeCount.greaterThan( int( 0 ) ), () => {
|
|
985
999
|
|
|
986
1000
|
lightPdf.assign( calculateLightBVHPdf(
|
|
987
|
-
int( hitTriIdx ),
|
|
1001
|
+
int( hitTriIdx ), misDist, direction, misOrigin,
|
|
988
1002
|
lightBuffer, emissiveVec4Offset, reverseMapVec4Offset, triangleBuffer,
|
|
989
1003
|
) );
|
|
990
1004
|
|
|
991
1005
|
} ).Else( () => {
|
|
992
1006
|
|
|
993
1007
|
lightPdf.assign( calculateEmissiveLightPdf(
|
|
994
|
-
int( hitTriIdx ),
|
|
1008
|
+
int( hitTriIdx ), misDist, direction, misOrigin,
|
|
995
1009
|
triangleBuffer, materialBuffer, emissiveTotalPower,
|
|
996
1010
|
) );
|
|
997
1011
|
|
|
@@ -1008,7 +1022,7 @@ export function buildShadeKernel( params ) {
|
|
|
1008
1022
|
currentRadiance.xyz.add(
|
|
1009
1023
|
regularizePathContribution(
|
|
1010
1024
|
emissive.mul( throughput ).mul( emissiveGiScale ).mul( emissiveMISWeight ),
|
|
1011
|
-
float( bounceIndex ), fireflyThreshold, int(
|
|
1025
|
+
float( bounceIndex ), fireflyThreshold, int( accumFrame ),
|
|
1012
1026
|
),
|
|
1013
1027
|
),
|
|
1014
1028
|
currentRadiance.w
|
|
@@ -1137,7 +1151,7 @@ export function buildShadeKernel( params ) {
|
|
|
1137
1151
|
currentRadiance.xyz.add(
|
|
1138
1152
|
regularizePathContribution(
|
|
1139
1153
|
throughput.mul( directLight ).mul( giScale ),
|
|
1140
|
-
float( bounceIndex ), fireflyThreshold, int(
|
|
1154
|
+
float( bounceIndex ), fireflyThreshold, int( accumFrame ),
|
|
1141
1155
|
),
|
|
1142
1156
|
),
|
|
1143
1157
|
currentRadiance.w
|
|
@@ -1173,12 +1187,9 @@ export function buildShadeKernel( params ) {
|
|
|
1173
1187
|
triangleBuffer,
|
|
1174
1188
|
) );
|
|
1175
1189
|
|
|
1176
|
-
//
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
.and( material.metalness.lessThan( 0.1 ) );
|
|
1180
|
-
|
|
1181
|
-
If( skip.not().and( emissiveSample.valid ).and( emissiveSample.pdf.greaterThan( 0.0 ) ), () => {
|
|
1190
|
+
// No rough-diffuse secondary-bounce skip here: dropping NEE while the emissive-hit
|
|
1191
|
+
// MIS still down-weights BSDF hits deletes emitter energy from deep GI.
|
|
1192
|
+
If( emissiveSample.valid.and( emissiveSample.pdf.greaterThan( 0.0 ) ), () => {
|
|
1182
1193
|
|
|
1183
1194
|
const NoL = max( float( 0.0 ), dot( N, emissiveSample.direction ) );
|
|
1184
1195
|
|
|
@@ -1210,7 +1221,7 @@ export function buildShadeKernel( params ) {
|
|
|
1210
1221
|
currentRadiance.xyz.add(
|
|
1211
1222
|
regularizePathContribution(
|
|
1212
1223
|
emissiveLight.mul( throughput ).mul( giScale ),
|
|
1213
|
-
float( bounceIndex ), fireflyThreshold, int(
|
|
1224
|
+
float( bounceIndex ), fireflyThreshold, int( accumFrame ),
|
|
1214
1225
|
),
|
|
1215
1226
|
),
|
|
1216
1227
|
currentRadiance.w,
|
|
@@ -1239,7 +1250,7 @@ export function buildShadeKernel( params ) {
|
|
|
1239
1250
|
currentRadiance.xyz.add(
|
|
1240
1251
|
regularizePathContribution(
|
|
1241
1252
|
emissiveLight.mul( throughput ).mul( giScale ),
|
|
1242
|
-
float( bounceIndex ), fireflyThreshold, int(
|
|
1253
|
+
float( bounceIndex ), fireflyThreshold, int( accumFrame ),
|
|
1243
1254
|
),
|
|
1244
1255
|
),
|
|
1245
1256
|
currentRadiance.w,
|
|
@@ -1265,6 +1276,17 @@ export function buildShadeKernel( params ) {
|
|
|
1265
1276
|
) ).toVar();
|
|
1266
1277
|
|
|
1267
1278
|
const bounceDir = indirectResult.direction.toVar();
|
|
1279
|
+
|
|
1280
|
+
// Shading-normal leak guard: a normal-mapped lobe can sample below the geometric surface;
|
|
1281
|
+
// tracing that ray tunnels through single-sided shells onto whatever sits behind them.
|
|
1282
|
+
const NgeoFF = select( dot( hitNormal, V ).lessThan( 0.0 ), hitNormal.negate(), hitNormal );
|
|
1283
|
+
If( brdfIsTransmission.not().and( dot( bounceDir, NgeoFF ).lessThanEqual( 0.0 ) ), () => {
|
|
1284
|
+
|
|
1285
|
+
commitDeferredAux( N );
|
|
1286
|
+
terminatePath();
|
|
1287
|
+
Return();
|
|
1288
|
+
|
|
1289
|
+
} );
|
|
1268
1290
|
// combinedPdf is stored as next bounce's prevBouncePdf for NEE↔implicit-env MIS
|
|
1269
1291
|
const bouncePdf = max( indirectResult.combinedPdf, 0.001 ).toVar();
|
|
1270
1292
|
throughput.mulAssign( indirectResult.throughput );
|
|
@@ -1276,7 +1298,7 @@ export function buildShadeKernel( params ) {
|
|
|
1276
1298
|
const rrSurvival = handleRussianRoulette(
|
|
1277
1299
|
bounceIndex, throughput, mc, bounceDir, rngState,
|
|
1278
1300
|
_pixelCoord, resolution, frame, dimBase,
|
|
1279
|
-
enableEnvironmentLight,
|
|
1301
|
+
enableEnvironmentLight,
|
|
1280
1302
|
).toVar();
|
|
1281
1303
|
If( rrSurvival.lessThanEqual( 0.0 ), () => {
|
|
1282
1304
|
|
package/src/TSL/Struct.js
CHANGED
|
@@ -242,16 +242,6 @@ export const MaterialCache = struct( {
|
|
|
242
242
|
} );
|
|
243
243
|
|
|
244
244
|
|
|
245
|
-
// IMPROVEMENT: Dynamic MIS strategy based on material properties
|
|
246
|
-
export const MISStrategy = struct( {
|
|
247
|
-
brdfWeight: 'float',
|
|
248
|
-
lightWeight: 'float',
|
|
249
|
-
envWeight: 'float',
|
|
250
|
-
useBRDFSampling: 'bool',
|
|
251
|
-
useLightSampling: 'bool',
|
|
252
|
-
useEnvSampling: 'bool',
|
|
253
|
-
} );
|
|
254
|
-
|
|
255
245
|
// General rendering state (used across all rendering paths)
|
|
256
246
|
export const RenderState = struct( {
|
|
257
247
|
traversals: 'int', // Remaining general bounces
|
package/src/index.js
CHANGED
|
@@ -54,6 +54,11 @@ export { VRAMTracker, bufferBytes, textureBytes } from './Processor/VRAMTracker.
|
|
|
54
54
|
export { RenderPipeline } from './Pipeline/RenderPipeline.js';
|
|
55
55
|
export { RenderStage, StageExecutionMode } from './Pipeline/RenderStage.js';
|
|
56
56
|
export { PipelineContext } from './Pipeline/PipelineContext.js';
|
|
57
|
+
export {
|
|
58
|
+
setBindingAudit,
|
|
59
|
+
getBindingAuditFindings,
|
|
60
|
+
clearBindingAuditFindings,
|
|
61
|
+
} from './Pipeline/BindingAudit.js';
|
|
57
62
|
|
|
58
63
|
// Animation (for advanced consumers)
|
|
59
64
|
export { AnimationManager } from './managers/AnimationManager.js';
|
|
@@ -274,7 +274,6 @@ export class EnvironmentManager {
|
|
|
274
274
|
this._updateCDFTexture();
|
|
275
275
|
this.uniforms.set( 'envTotalSum', 0.0 );
|
|
276
276
|
this.uniforms.set( 'envCompensationDelta', 0.0 );
|
|
277
|
-
this.uniforms.set( 'useEnvMapIS', 0 );
|
|
278
277
|
return;
|
|
279
278
|
|
|
280
279
|
}
|
|
@@ -289,7 +288,6 @@ export class EnvironmentManager {
|
|
|
289
288
|
this._updateCDFTexture();
|
|
290
289
|
this.uniforms.set( 'envTotalSum', 0.0 );
|
|
291
290
|
this.uniforms.set( 'envCompensationDelta', 0.0 );
|
|
292
|
-
this.uniforms.set( 'useEnvMapIS', 0 );
|
|
293
291
|
return;
|
|
294
292
|
|
|
295
293
|
}
|
|
@@ -309,7 +307,6 @@ export class EnvironmentManager {
|
|
|
309
307
|
this._updateCDFTexture();
|
|
310
308
|
this.uniforms.set( 'envTotalSum', this.equirectHdrInfo.totalSum );
|
|
311
309
|
this.uniforms.set( 'envCompensationDelta', this.equirectHdrInfo.compensationDelta );
|
|
312
|
-
this.uniforms.set( 'useEnvMapIS', 1 );
|
|
313
310
|
|
|
314
311
|
const { width, height } = this.equirectHdrInfo;
|
|
315
312
|
if ( width && height ) {
|
|
@@ -326,7 +323,6 @@ export class EnvironmentManager {
|
|
|
326
323
|
} catch ( error ) {
|
|
327
324
|
|
|
328
325
|
log.error( 'CDF build failed:', error );
|
|
329
|
-
this.uniforms.set( 'useEnvMapIS', 0 );
|
|
330
326
|
this.uniforms.set( 'envTotalSum', 0.0 );
|
|
331
327
|
this.uniforms.set( 'envCompensationDelta', 0.0 );
|
|
332
328
|
|
|
@@ -387,7 +383,6 @@ export class EnvironmentManager {
|
|
|
387
383
|
this._updateCDFTexture();
|
|
388
384
|
this.uniforms.set( 'envTotalSum', 0.0 );
|
|
389
385
|
this.uniforms.set( 'envCompensationDelta', 0.0 );
|
|
390
|
-
this.uniforms.set( 'useEnvMapIS', 0 );
|
|
391
386
|
|
|
392
387
|
}
|
|
393
388
|
|
|
@@ -160,6 +160,10 @@ export class UniformManager {
|
|
|
160
160
|
|
|
161
161
|
// Frame and sampling
|
|
162
162
|
u( 'frame', 0, 'uint' );
|
|
163
|
+
// Sampler seed axis, separate from the accumulation index: `frame` is zeroed by every
|
|
164
|
+
// reset, and a camera move resets each frame of a drag, so the RNG redrew the identical
|
|
165
|
+
// sequence and temporal denoising had nothing to average.
|
|
166
|
+
u( 'seedFrame', 0, 'uint' );
|
|
163
167
|
u( 'maxBounces', DEFAULT_STATE.bounces, 'int' );
|
|
164
168
|
u( 'maxSamples', DEFAULT_STATE.maxSamples, 'int' );
|
|
165
169
|
u( 'transmissiveBounces', DEFAULT_STATE.transmissiveBounces, 'int' );
|
|
@@ -198,7 +202,6 @@ export class UniformManager {
|
|
|
198
202
|
ub( 'transparentBackground', DEFAULT_STATE.transparentBackground );
|
|
199
203
|
ub( 'enableEnvironment', DEFAULT_STATE.enableEnvironment );
|
|
200
204
|
u( 'environmentMatrix', new Matrix4(), 'mat4' );
|
|
201
|
-
ub( 'useEnvMapIS', DEFAULT_STATE.useImportanceSampledEnvironment );
|
|
202
205
|
u( 'envTotalSum', 0.0, 'float' );
|
|
203
206
|
u( 'envCompensationDelta', 0.0, 'float' );
|
|
204
207
|
u( 'envResolution', new Vector2( 1, 1 ), 'vec2' );
|