@plasius/gpu-lighting 0.2.5 → 0.2.7
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/CHANGELOG.md +35 -3
- package/README.md +98 -0
- package/dist/index.cjs +837 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +817 -0
- package/dist/index.js.map +1 -1
- package/dist/techniques/techniques/wavefront/accumulate-terminal-radiance.job.wgsl +61 -0
- package/dist/techniques/techniques/wavefront/prelude.wgsl +237 -0
- package/dist/techniques/techniques/wavefront/scatter-continuations.job.wgsl +136 -0
- package/package.json +2 -1
- package/src/index.js +889 -0
- package/src/techniques/wavefront/accumulate-terminal-radiance.job.wgsl +61 -0
- package/src/techniques/wavefront/prelude.wgsl +237 -0
- package/src/techniques/wavefront/scatter-continuations.job.wgsl +136 -0
package/dist/index.cjs
CHANGED
|
@@ -33,9 +33,18 @@ __export(index_exports, {
|
|
|
33
33
|
createLightingBandPlan: () => createLightingBandPlan,
|
|
34
34
|
createLightingProfileModeLadder: () => createLightingProfileModeLadder,
|
|
35
35
|
createWavefrontEnvironmentLightingOptions: () => createWavefrontEnvironmentLightingOptions,
|
|
36
|
+
createWavefrontLightingPlan: () => createWavefrontLightingPlan,
|
|
37
|
+
createWavefrontRayPayload: () => createWavefrontRayPayload,
|
|
38
|
+
createWavefrontReferenceFixture: () => createWavefrontReferenceFixture,
|
|
39
|
+
createWavefrontVisibilityProbeRay: () => createWavefrontVisibilityProbeRay,
|
|
36
40
|
defaultAdaptiveLightingProfilePolicy: () => defaultAdaptiveLightingProfilePolicy,
|
|
37
41
|
defaultLightingProfile: () => defaultLightingProfile,
|
|
38
42
|
defaultLightingTechnique: () => defaultLightingTechnique,
|
|
43
|
+
evaluateWavefrontContinuationEvent: () => evaluateWavefrontContinuationEvent,
|
|
44
|
+
evaluateWavefrontMaterialReference: () => evaluateWavefrontMaterialReference,
|
|
45
|
+
evaluateWavefrontMediumState: () => evaluateWavefrontMediumState,
|
|
46
|
+
evaluateWavefrontTerminalRadiance: () => evaluateWavefrontTerminalRadiance,
|
|
47
|
+
evaluateWavefrontVisibilityProbe: () => evaluateWavefrontVisibilityProbe,
|
|
39
48
|
getLightingProfile: () => getLightingProfile,
|
|
40
49
|
getLightingProfileWorkerManifest: () => getLightingProfileWorkerManifest,
|
|
41
50
|
getLightingTechnique: () => getLightingTechnique,
|
|
@@ -54,8 +63,19 @@ __export(index_exports, {
|
|
|
54
63
|
lightingProfileModeOrder: () => lightingProfileModeOrder,
|
|
55
64
|
lightingProfileNames: () => lightingProfileNames,
|
|
56
65
|
lightingProfiles: () => lightingProfiles,
|
|
66
|
+
lightingRequiredRendererWavefrontPassOrder: () => lightingRequiredRendererWavefrontPassOrder,
|
|
57
67
|
lightingTechniqueNames: () => lightingTechniqueNames,
|
|
58
68
|
lightingTechniques: () => lightingTechniques,
|
|
69
|
+
lightingWavefrontBufferContracts: () => lightingWavefrontBufferContracts,
|
|
70
|
+
lightingWavefrontContinuationHitTypes: () => lightingWavefrontContinuationHitTypes,
|
|
71
|
+
lightingWavefrontHitTypes: () => lightingWavefrontHitTypes,
|
|
72
|
+
lightingWavefrontPassOrder: () => lightingWavefrontPassOrder,
|
|
73
|
+
lightingWavefrontQueuePairStrategy: () => lightingWavefrontQueuePairStrategy,
|
|
74
|
+
lightingWavefrontRayKinds: () => lightingWavefrontRayKinds,
|
|
75
|
+
lightingWavefrontSchemaVersion: () => lightingWavefrontSchemaVersion,
|
|
76
|
+
lightingWavefrontTerminalHitTypes: () => lightingWavefrontTerminalHitTypes,
|
|
77
|
+
lightingWavefrontTerminationPolicy: () => lightingWavefrontTerminationPolicy,
|
|
78
|
+
lightingWavefrontVisibilityProbeModes: () => lightingWavefrontVisibilityProbeModes,
|
|
59
79
|
lightingWorkerManifests: () => lightingWorkerManifests,
|
|
60
80
|
lightingWorkerQueueClass: () => lightingWorkerQueueClass,
|
|
61
81
|
loadLightingJobs: () => loadLightingJobs,
|
|
@@ -100,6 +120,14 @@ var techniqueSpecs = {
|
|
|
100
120
|
denoise: "denoise.job.wgsl"
|
|
101
121
|
}
|
|
102
122
|
},
|
|
123
|
+
wavefront: {
|
|
124
|
+
description: "Renderer-aligned wavefront lighting jobs for terminal radiance and continuation scattering.",
|
|
125
|
+
prelude: "prelude.wgsl",
|
|
126
|
+
jobs: {
|
|
127
|
+
accumulateTerminalRadiance: "accumulate-terminal-radiance.job.wgsl",
|
|
128
|
+
scatterContinuations: "scatter-continuations.job.wgsl"
|
|
129
|
+
}
|
|
130
|
+
},
|
|
103
131
|
volumetrics: {
|
|
104
132
|
description: "Froxel volumetric lighting for fog, shafts, and participating media shadows.",
|
|
105
133
|
prelude: "prelude.wgsl",
|
|
@@ -1108,6 +1136,684 @@ function createWavefrontEnvironmentLightingOptions(options = {}) {
|
|
|
1108
1136
|
lightingEnvironment: config
|
|
1109
1137
|
});
|
|
1110
1138
|
}
|
|
1139
|
+
var lightingWavefrontSchemaVersion = 1;
|
|
1140
|
+
var lightingWavefrontQueuePairStrategy = "ping-pong-active-next";
|
|
1141
|
+
var lightingWavefrontHitTypes = Object.freeze([
|
|
1142
|
+
"surface",
|
|
1143
|
+
"emissive",
|
|
1144
|
+
"environment",
|
|
1145
|
+
"transparent",
|
|
1146
|
+
"miss"
|
|
1147
|
+
]);
|
|
1148
|
+
var lightingWavefrontRayKinds = Object.freeze([
|
|
1149
|
+
"path",
|
|
1150
|
+
"visibility-probe"
|
|
1151
|
+
]);
|
|
1152
|
+
var lightingWavefrontVisibilityProbeModes = Object.freeze([
|
|
1153
|
+
"disabled",
|
|
1154
|
+
"mis-balanced",
|
|
1155
|
+
"exclusive-emissive"
|
|
1156
|
+
]);
|
|
1157
|
+
var lightingWavefrontTerminalHitTypes = Object.freeze([
|
|
1158
|
+
"emissive",
|
|
1159
|
+
"environment",
|
|
1160
|
+
"miss"
|
|
1161
|
+
]);
|
|
1162
|
+
var lightingWavefrontContinuationHitTypes = Object.freeze([
|
|
1163
|
+
"surface",
|
|
1164
|
+
"transparent"
|
|
1165
|
+
]);
|
|
1166
|
+
var lightingWavefrontPassOrder = Object.freeze([
|
|
1167
|
+
"accumulateTerminalRadiance",
|
|
1168
|
+
"scatterContinuations"
|
|
1169
|
+
]);
|
|
1170
|
+
var lightingRequiredRendererWavefrontPassOrder = Object.freeze([
|
|
1171
|
+
"generatePrimaryRays",
|
|
1172
|
+
"intersectActiveQueue",
|
|
1173
|
+
"resolveSurfaceRecords",
|
|
1174
|
+
"accumulateTerminalRadiance",
|
|
1175
|
+
"scatterContinuations",
|
|
1176
|
+
"compactAndSwapQueues"
|
|
1177
|
+
]);
|
|
1178
|
+
function createLightingWavefrontField(name, type, description) {
|
|
1179
|
+
return Object.freeze({
|
|
1180
|
+
name,
|
|
1181
|
+
type,
|
|
1182
|
+
description
|
|
1183
|
+
});
|
|
1184
|
+
}
|
|
1185
|
+
function createLightingWavefrontRecordContract(recordName, fields) {
|
|
1186
|
+
return Object.freeze({
|
|
1187
|
+
schemaVersion: lightingWavefrontSchemaVersion,
|
|
1188
|
+
recordName,
|
|
1189
|
+
fields: Object.freeze(fields)
|
|
1190
|
+
});
|
|
1191
|
+
}
|
|
1192
|
+
var lightingWavefrontBufferContracts = Object.freeze({
|
|
1193
|
+
ray: createLightingWavefrontRecordContract(
|
|
1194
|
+
"RayRecord",
|
|
1195
|
+
[
|
|
1196
|
+
createLightingWavefrontField("rayId", "u32", "Stable ray identifier."),
|
|
1197
|
+
createLightingWavefrontField("parentRayId", "u32", "Parent ray identifier."),
|
|
1198
|
+
createLightingWavefrontField("sourcePixelId", "u32", "Source pixel/sample owner."),
|
|
1199
|
+
createLightingWavefrontField("sampleId", "u32", "Per-pixel sample slot."),
|
|
1200
|
+
createLightingWavefrontField("bounce", "u32", "Current bounce depth."),
|
|
1201
|
+
createLightingWavefrontField("mediumRefId", "u32", "Current medium reference."),
|
|
1202
|
+
createLightingWavefrontField(
|
|
1203
|
+
"mediumStackDepth",
|
|
1204
|
+
"u32",
|
|
1205
|
+
"Depth of the bounded nested medium stack."
|
|
1206
|
+
),
|
|
1207
|
+
createLightingWavefrontField(
|
|
1208
|
+
"flags",
|
|
1209
|
+
"u32",
|
|
1210
|
+
"Renderer-owned ray flags. Low bits may encode ray kind metadata."
|
|
1211
|
+
),
|
|
1212
|
+
createLightingWavefrontField(
|
|
1213
|
+
"mediumStack0",
|
|
1214
|
+
"vec4<u32>",
|
|
1215
|
+
"Lower half of the bounded nested medium stack."
|
|
1216
|
+
),
|
|
1217
|
+
createLightingWavefrontField(
|
|
1218
|
+
"mediumStack1",
|
|
1219
|
+
"vec4<u32>",
|
|
1220
|
+
"Upper half of the bounded nested medium stack."
|
|
1221
|
+
),
|
|
1222
|
+
createLightingWavefrontField(
|
|
1223
|
+
"spectralState",
|
|
1224
|
+
"vec4<f32>",
|
|
1225
|
+
"Spectral transport payload for wavelength-driven reference validation."
|
|
1226
|
+
),
|
|
1227
|
+
createLightingWavefrontField("origin", "vec3<f32>", "Ray origin."),
|
|
1228
|
+
createLightingWavefrontField("direction", "vec3<f32>", "Normalized ray direction."),
|
|
1229
|
+
createLightingWavefrontField("throughput", "vec3<f32>", "Accumulated path throughput.")
|
|
1230
|
+
]
|
|
1231
|
+
),
|
|
1232
|
+
hit: createLightingWavefrontRecordContract(
|
|
1233
|
+
"HitRecord",
|
|
1234
|
+
[
|
|
1235
|
+
createLightingWavefrontField("rayId", "u32", "Stable ray identifier."),
|
|
1236
|
+
createLightingWavefrontField("sourcePixelId", "u32", "Source pixel/sample owner."),
|
|
1237
|
+
createLightingWavefrontField("hitType", "u32", "Surface, emissive, environment, transparent, or miss."),
|
|
1238
|
+
createLightingWavefrontField("distance", "f32", "Nearest-hit distance."),
|
|
1239
|
+
createLightingWavefrontField("entityId", "u32", "Owning entity identifier."),
|
|
1240
|
+
createLightingWavefrontField("instanceId", "u32", "Owning instance identifier."),
|
|
1241
|
+
createLightingWavefrontField("primitiveId", "u32", "Primitive identifier."),
|
|
1242
|
+
createLightingWavefrontField("materialId", "u32", "Resolved material identifier."),
|
|
1243
|
+
createLightingWavefrontField("barycentrics", "vec3<f32>", "Triangle barycentrics."),
|
|
1244
|
+
createLightingWavefrontField("uv", "vec2<f32>", "Resolved UV coordinates."),
|
|
1245
|
+
createLightingWavefrontField("geometricNormal", "vec3<f32>", "Geometric surface normal."),
|
|
1246
|
+
createLightingWavefrontField("shadingNormal", "vec3<f32>", "Interpolated shading normal."),
|
|
1247
|
+
createLightingWavefrontField("frontFace", "u32", "Front-face classification.")
|
|
1248
|
+
]
|
|
1249
|
+
),
|
|
1250
|
+
surface: createLightingWavefrontRecordContract(
|
|
1251
|
+
"SurfaceRecord",
|
|
1252
|
+
[
|
|
1253
|
+
createLightingWavefrontField("rayId", "u32", "Stable ray identifier."),
|
|
1254
|
+
createLightingWavefrontField("entityId", "u32", "Owning entity identifier."),
|
|
1255
|
+
createLightingWavefrontField("materialRefId", "u32", "Renderer material reference id."),
|
|
1256
|
+
createLightingWavefrontField("mediumRefId", "u32", "Renderer medium reference id."),
|
|
1257
|
+
createLightingWavefrontField("geometricNormal", "vec3<f32>", "Geometric surface normal."),
|
|
1258
|
+
createLightingWavefrontField("shadingNormal", "vec3<f32>", "Interpolated shading normal."),
|
|
1259
|
+
createLightingWavefrontField("uv", "vec2<f32>", "Resolved UV coordinates."),
|
|
1260
|
+
createLightingWavefrontField("tangentFrame", "mat3x3<f32>", "Resolved tangent frame.")
|
|
1261
|
+
]
|
|
1262
|
+
),
|
|
1263
|
+
materialReference: createLightingWavefrontRecordContract(
|
|
1264
|
+
"MaterialReferenceRecord",
|
|
1265
|
+
[
|
|
1266
|
+
createLightingWavefrontField("materialRefId", "u32", "Lighting-visible material reference id."),
|
|
1267
|
+
createLightingWavefrontField("materialId", "u32", "Source material identifier."),
|
|
1268
|
+
createLightingWavefrontField("shadingModel", "u32", "Renderer shading-model discriminator."),
|
|
1269
|
+
createLightingWavefrontField("textureSetId", "u32", "Resolved texture-set identifier."),
|
|
1270
|
+
createLightingWavefrontField("flags", "u32", "Renderer material flags.")
|
|
1271
|
+
]
|
|
1272
|
+
),
|
|
1273
|
+
mediumReference: createLightingWavefrontRecordContract(
|
|
1274
|
+
"MediumReferenceRecord",
|
|
1275
|
+
[
|
|
1276
|
+
createLightingWavefrontField("mediumRefId", "u32", "Lighting-visible medium reference id."),
|
|
1277
|
+
createLightingWavefrontField("mediumId", "u32", "Source medium identifier."),
|
|
1278
|
+
createLightingWavefrontField("phaseModel", "u32", "Phase-function discriminator."),
|
|
1279
|
+
createLightingWavefrontField("absorption", "vec3<f32>", "Medium absorption coefficients."),
|
|
1280
|
+
createLightingWavefrontField("scattering", "vec3<f32>", "Medium scattering coefficients.")
|
|
1281
|
+
]
|
|
1282
|
+
),
|
|
1283
|
+
accumulation: createLightingWavefrontRecordContract(
|
|
1284
|
+
"AccumulationRecord",
|
|
1285
|
+
[
|
|
1286
|
+
createLightingWavefrontField("sourcePixelId", "u32", "Source pixel/sample owner."),
|
|
1287
|
+
createLightingWavefrontField("sampleCount", "u32", "Accumulated sample count."),
|
|
1288
|
+
createLightingWavefrontField("radiance", "vec3<f32>", "Accumulated radiance."),
|
|
1289
|
+
createLightingWavefrontField("throughput", "vec3<f32>", "Last surviving throughput."),
|
|
1290
|
+
createLightingWavefrontField("resetEpoch", "u32", "Renderer accumulation reset epoch.")
|
|
1291
|
+
]
|
|
1292
|
+
)
|
|
1293
|
+
});
|
|
1294
|
+
var lightingWavefrontTerminationPolicy = Object.freeze({
|
|
1295
|
+
terminalHitTypes: lightingWavefrontTerminalHitTypes,
|
|
1296
|
+
continuationHitTypes: lightingWavefrontContinuationHitTypes,
|
|
1297
|
+
emissive: Object.freeze({
|
|
1298
|
+
action: "accumulate-and-stop",
|
|
1299
|
+
contributesRadiance: true
|
|
1300
|
+
}),
|
|
1301
|
+
environment: Object.freeze({
|
|
1302
|
+
action: "accumulate-and-stop",
|
|
1303
|
+
contributesRadiance: true
|
|
1304
|
+
}),
|
|
1305
|
+
miss: Object.freeze({
|
|
1306
|
+
action: "accumulate-environment-or-dark-stop",
|
|
1307
|
+
contributesRadiance: true
|
|
1308
|
+
})
|
|
1309
|
+
});
|
|
1310
|
+
var defaultWavefrontDarkRadiance = Object.freeze([1e-4, 1e-4, 1e-4]);
|
|
1311
|
+
var wavefrontEventKinds = Object.freeze([
|
|
1312
|
+
"diffuse",
|
|
1313
|
+
"reflection",
|
|
1314
|
+
"refraction",
|
|
1315
|
+
"transparency",
|
|
1316
|
+
"terminate"
|
|
1317
|
+
]);
|
|
1318
|
+
var wavefrontRayKindFlagMask = 3;
|
|
1319
|
+
var wavefrontRayKindFlagValues = Object.freeze({
|
|
1320
|
+
path: 0,
|
|
1321
|
+
"visibility-probe": 1
|
|
1322
|
+
});
|
|
1323
|
+
function normalizeWavefrontRayKind(value) {
|
|
1324
|
+
return lightingWavefrontRayKinds.includes(value) ? value : "path";
|
|
1325
|
+
}
|
|
1326
|
+
function normalizeWavefrontVisibilityProbeMode(value) {
|
|
1327
|
+
return lightingWavefrontVisibilityProbeModes.includes(value) ? value : "disabled";
|
|
1328
|
+
}
|
|
1329
|
+
function normalizeWavefrontHitType(value) {
|
|
1330
|
+
return lightingWavefrontHitTypes.includes(value) ? value : "surface";
|
|
1331
|
+
}
|
|
1332
|
+
function normalizeWavefrontEventKind(value) {
|
|
1333
|
+
return wavefrontEventKinds.includes(value) ? value : null;
|
|
1334
|
+
}
|
|
1335
|
+
function normalizeVec3(value, fallback = [0, 0, 0]) {
|
|
1336
|
+
if (!Array.isArray(value) || value.length < 3) {
|
|
1337
|
+
return [...fallback];
|
|
1338
|
+
}
|
|
1339
|
+
return [
|
|
1340
|
+
Number.isFinite(value[0]) ? value[0] : fallback[0],
|
|
1341
|
+
Number.isFinite(value[1]) ? value[1] : fallback[1],
|
|
1342
|
+
Number.isFinite(value[2]) ? value[2] : fallback[2]
|
|
1343
|
+
];
|
|
1344
|
+
}
|
|
1345
|
+
function clampUnit(value, fallback = 0) {
|
|
1346
|
+
return Math.max(0, Math.min(1, readFinite(value, fallback)));
|
|
1347
|
+
}
|
|
1348
|
+
function saturateVec3(value) {
|
|
1349
|
+
return value.map((component) => Math.max(0, component));
|
|
1350
|
+
}
|
|
1351
|
+
function scaleVec3(value, scalar) {
|
|
1352
|
+
return value.map((component) => component * scalar);
|
|
1353
|
+
}
|
|
1354
|
+
function addVec3(left, right) {
|
|
1355
|
+
return left.map((component, index) => component + right[index]);
|
|
1356
|
+
}
|
|
1357
|
+
function multiplyVec3(left, right) {
|
|
1358
|
+
return left.map((component, index) => component * right[index]);
|
|
1359
|
+
}
|
|
1360
|
+
function dotVec3(left, right) {
|
|
1361
|
+
return left[0] * right[0] + left[1] * right[1] + left[2] * right[2];
|
|
1362
|
+
}
|
|
1363
|
+
function lengthVec3(value) {
|
|
1364
|
+
return Math.hypot(value[0], value[1], value[2]);
|
|
1365
|
+
}
|
|
1366
|
+
function normalizeDirection(value, fallback = [0, 1, 0]) {
|
|
1367
|
+
const vector = normalizeVec3(value, fallback);
|
|
1368
|
+
const length = lengthVec3(vector);
|
|
1369
|
+
if (!Number.isFinite(length) || length <= 1e-6) {
|
|
1370
|
+
return [...fallback];
|
|
1371
|
+
}
|
|
1372
|
+
return vector.map((component) => component / length);
|
|
1373
|
+
}
|
|
1374
|
+
function mixVec3(left, right, factor) {
|
|
1375
|
+
return left.map(
|
|
1376
|
+
(component, index) => component * (1 - factor) + right[index] * factor
|
|
1377
|
+
);
|
|
1378
|
+
}
|
|
1379
|
+
function reflectDirection(direction, normal) {
|
|
1380
|
+
const scale = 2 * dotVec3(direction, normal);
|
|
1381
|
+
return normalizeDirection(
|
|
1382
|
+
[
|
|
1383
|
+
direction[0] - scale * normal[0],
|
|
1384
|
+
direction[1] - scale * normal[1],
|
|
1385
|
+
direction[2] - scale * normal[2]
|
|
1386
|
+
],
|
|
1387
|
+
normal
|
|
1388
|
+
);
|
|
1389
|
+
}
|
|
1390
|
+
function refractDirection(direction, normal, etaRatio) {
|
|
1391
|
+
const cosTheta = Math.min(-dotVec3(direction, normal), 1);
|
|
1392
|
+
const rOutPerp = scaleVec3(addVec3(direction, scaleVec3(normal, cosTheta)), etaRatio);
|
|
1393
|
+
const rOutPerpLengthSquared = dotVec3(rOutPerp, rOutPerp);
|
|
1394
|
+
const parallelFactor = 1 - rOutPerpLengthSquared;
|
|
1395
|
+
if (parallelFactor <= 0) {
|
|
1396
|
+
return null;
|
|
1397
|
+
}
|
|
1398
|
+
const rOutParallel = scaleVec3(normal, -Math.sqrt(parallelFactor));
|
|
1399
|
+
return normalizeDirection(addVec3(rOutPerp, rOutParallel), direction);
|
|
1400
|
+
}
|
|
1401
|
+
function normalizeMediumRefId(value) {
|
|
1402
|
+
const mediumRefId = Math.max(0, Math.trunc(readFinite(value, 0)));
|
|
1403
|
+
return Number.isFinite(mediumRefId) ? mediumRefId : 0;
|
|
1404
|
+
}
|
|
1405
|
+
function normalizeMediumStack(value) {
|
|
1406
|
+
if (!Array.isArray(value)) {
|
|
1407
|
+
return [];
|
|
1408
|
+
}
|
|
1409
|
+
return value.map((entry) => normalizeMediumRefId(entry)).filter((entry, index, stack) => entry > 0 && stack.indexOf(entry) === index).slice(0, 4);
|
|
1410
|
+
}
|
|
1411
|
+
function createWavefrontMediumStatePayload(currentMediumRefId, stack) {
|
|
1412
|
+
const normalizedStack = normalizeMediumStack(stack);
|
|
1413
|
+
const stackSlots = [0, 0, 0, 0];
|
|
1414
|
+
normalizedStack.forEach((entry, index) => {
|
|
1415
|
+
stackSlots[index] = entry;
|
|
1416
|
+
});
|
|
1417
|
+
return Object.freeze({
|
|
1418
|
+
currentMediumRefId,
|
|
1419
|
+
stackDepth: normalizedStack.length,
|
|
1420
|
+
stack: Object.freeze(normalizedStack),
|
|
1421
|
+
stackSlots: Object.freeze(stackSlots)
|
|
1422
|
+
});
|
|
1423
|
+
}
|
|
1424
|
+
function evaluateWavefrontMediumState(options = {}) {
|
|
1425
|
+
const currentMediumRefId = normalizeMediumRefId(
|
|
1426
|
+
options.currentMediumRefId ?? options.mediumRefId
|
|
1427
|
+
);
|
|
1428
|
+
const surfaceMediumRefId = normalizeMediumRefId(options.surfaceMediumRefId);
|
|
1429
|
+
const stack = normalizeMediumStack(options.mediumStack);
|
|
1430
|
+
const frontFace = options.frontFace !== false;
|
|
1431
|
+
const eventKind = normalizeWavefrontEventKind(options.eventKind) ?? "transparency";
|
|
1432
|
+
if (surfaceMediumRefId === 0 || eventKind !== "refraction" && eventKind !== "transparency") {
|
|
1433
|
+
return Object.freeze({
|
|
1434
|
+
...createWavefrontMediumStatePayload(currentMediumRefId, stack),
|
|
1435
|
+
enteredMediumRefId: 0,
|
|
1436
|
+
exitedMediumRefId: 0
|
|
1437
|
+
});
|
|
1438
|
+
}
|
|
1439
|
+
let nextStack = [...stack];
|
|
1440
|
+
let nextMediumRefId = currentMediumRefId;
|
|
1441
|
+
let enteredMediumRefId = 0;
|
|
1442
|
+
let exitedMediumRefId = 0;
|
|
1443
|
+
const stackTop = nextStack.at(-1) ?? 0;
|
|
1444
|
+
if (frontFace) {
|
|
1445
|
+
if (stackTop !== surfaceMediumRefId) {
|
|
1446
|
+
nextStack.push(surfaceMediumRefId);
|
|
1447
|
+
nextStack = nextStack.slice(-4);
|
|
1448
|
+
}
|
|
1449
|
+
nextMediumRefId = surfaceMediumRefId;
|
|
1450
|
+
enteredMediumRefId = surfaceMediumRefId;
|
|
1451
|
+
} else if (stackTop === surfaceMediumRefId) {
|
|
1452
|
+
nextStack.pop();
|
|
1453
|
+
nextMediumRefId = nextStack.at(-1) ?? 0;
|
|
1454
|
+
exitedMediumRefId = surfaceMediumRefId;
|
|
1455
|
+
}
|
|
1456
|
+
return Object.freeze({
|
|
1457
|
+
...createWavefrontMediumStatePayload(nextMediumRefId, nextStack),
|
|
1458
|
+
enteredMediumRefId,
|
|
1459
|
+
exitedMediumRefId
|
|
1460
|
+
});
|
|
1461
|
+
}
|
|
1462
|
+
function encodeWavefrontRayFlags(flags, rayKind) {
|
|
1463
|
+
const normalizedFlags = Math.max(0, Math.trunc(readFinite(flags, 0)));
|
|
1464
|
+
const rayKindValue = wavefrontRayKindFlagValues[rayKind];
|
|
1465
|
+
return normalizedFlags & ~wavefrontRayKindFlagMask | rayKindValue;
|
|
1466
|
+
}
|
|
1467
|
+
function createWavefrontRayPayload(options = {}) {
|
|
1468
|
+
const rayKind = normalizeWavefrontRayKind(options.rayKind);
|
|
1469
|
+
const mediumState = evaluateWavefrontMediumState({
|
|
1470
|
+
currentMediumRefId: options.mediumRefId,
|
|
1471
|
+
mediumStack: options.mediumStack
|
|
1472
|
+
});
|
|
1473
|
+
const spectralState = Object.freeze(
|
|
1474
|
+
normalizeVec3(options.spectralState, [550, 1, 0]).concat(
|
|
1475
|
+
readFinite(options.spectralWeight, 0)
|
|
1476
|
+
)
|
|
1477
|
+
);
|
|
1478
|
+
const mediumStack0 = Object.freeze([
|
|
1479
|
+
mediumState.stackSlots[0],
|
|
1480
|
+
mediumState.stackSlots[1],
|
|
1481
|
+
mediumState.stackSlots[2],
|
|
1482
|
+
mediumState.stackSlots[3]
|
|
1483
|
+
]);
|
|
1484
|
+
const mediumStack1 = Object.freeze([0, 0, 0, 0]);
|
|
1485
|
+
return Object.freeze({
|
|
1486
|
+
rayId: Math.max(0, Math.trunc(readFinite(options.rayId, 0))),
|
|
1487
|
+
parentRayId: Math.max(0, Math.trunc(readFinite(options.parentRayId, 0))),
|
|
1488
|
+
sourcePixelId: Math.max(0, Math.trunc(readFinite(options.sourcePixelId, 0))),
|
|
1489
|
+
sampleId: Math.max(0, Math.trunc(readFinite(options.sampleId, 0))),
|
|
1490
|
+
bounce: Math.max(0, Math.trunc(readFinite(options.bounce, 0))),
|
|
1491
|
+
origin: Object.freeze(normalizeVec3(options.origin, [0, 0, 0])),
|
|
1492
|
+
direction: Object.freeze(normalizeDirection(options.direction, [0, 0, -1])),
|
|
1493
|
+
throughput: Object.freeze(
|
|
1494
|
+
saturateVec3(normalizeVec3(options.throughput, [1, 1, 1]))
|
|
1495
|
+
),
|
|
1496
|
+
mediumRefId: mediumState.currentMediumRefId,
|
|
1497
|
+
mediumStackDepth: mediumState.stackDepth,
|
|
1498
|
+
mediumStack: mediumState.stack,
|
|
1499
|
+
mediumStackSlots: mediumState.stackSlots,
|
|
1500
|
+
mediumStack0,
|
|
1501
|
+
mediumStack1,
|
|
1502
|
+
spectralState,
|
|
1503
|
+
rayKind,
|
|
1504
|
+
flags: encodeWavefrontRayFlags(options.flags, rayKind)
|
|
1505
|
+
});
|
|
1506
|
+
}
|
|
1507
|
+
function createWavefrontVisibilityProbeRay(options = {}) {
|
|
1508
|
+
return createWavefrontRayPayload({
|
|
1509
|
+
...options,
|
|
1510
|
+
rayKind: "visibility-probe"
|
|
1511
|
+
});
|
|
1512
|
+
}
|
|
1513
|
+
function createWavefrontLightingPlan(options = {}) {
|
|
1514
|
+
const maxDepth = Math.max(1, Math.trunc(readFinite(options.maxDepth, 4)));
|
|
1515
|
+
const queueCapacity = Math.max(
|
|
1516
|
+
1,
|
|
1517
|
+
Math.trunc(readFinite(options.queueCapacity, 4096))
|
|
1518
|
+
);
|
|
1519
|
+
const explicitLightSampling = Boolean(options.explicitLightSampling);
|
|
1520
|
+
const visibilityProbeMode = normalizeWavefrontVisibilityProbeMode(
|
|
1521
|
+
options.visibilityProbeMode ?? (explicitLightSampling ? "mis-balanced" : "disabled")
|
|
1522
|
+
);
|
|
1523
|
+
const accumulationResetEpoch = Math.max(
|
|
1524
|
+
0,
|
|
1525
|
+
Math.trunc(readFinite(options.accumulationResetEpoch, 0))
|
|
1526
|
+
);
|
|
1527
|
+
return Object.freeze({
|
|
1528
|
+
schemaVersion: lightingWavefrontSchemaVersion,
|
|
1529
|
+
maxDepth,
|
|
1530
|
+
queueCapacity,
|
|
1531
|
+
explicitLightSampling,
|
|
1532
|
+
visibilityProbeMode,
|
|
1533
|
+
rayKinds: lightingWavefrontRayKinds,
|
|
1534
|
+
accumulationResetEpoch,
|
|
1535
|
+
queueLayout: Object.freeze({
|
|
1536
|
+
strategy: lightingWavefrontQueuePairStrategy,
|
|
1537
|
+
compactAfterScatter: true,
|
|
1538
|
+
queues: Object.freeze([
|
|
1539
|
+
Object.freeze({ name: "active", role: "current-bounce" }),
|
|
1540
|
+
Object.freeze({ name: "next", role: "next-bounce" })
|
|
1541
|
+
])
|
|
1542
|
+
}),
|
|
1543
|
+
bufferContracts: lightingWavefrontBufferContracts,
|
|
1544
|
+
terminationPolicy: lightingWavefrontTerminationPolicy,
|
|
1545
|
+
requiredRendererPassOrder: lightingRequiredRendererWavefrontPassOrder,
|
|
1546
|
+
lightingPasses: Object.freeze([
|
|
1547
|
+
Object.freeze({
|
|
1548
|
+
key: "accumulateTerminalRadiance",
|
|
1549
|
+
stage: "accumulateTerminalRadiance",
|
|
1550
|
+
reads: Object.freeze([
|
|
1551
|
+
"ray",
|
|
1552
|
+
"hit",
|
|
1553
|
+
"surface",
|
|
1554
|
+
"materialReference",
|
|
1555
|
+
"mediumReference"
|
|
1556
|
+
]),
|
|
1557
|
+
writes: Object.freeze(["accumulation"]),
|
|
1558
|
+
terminalHitTypes: lightingWavefrontTerminalHitTypes
|
|
1559
|
+
}),
|
|
1560
|
+
Object.freeze({
|
|
1561
|
+
key: "scatterContinuations",
|
|
1562
|
+
stage: "scatterContinuations",
|
|
1563
|
+
reads: Object.freeze([
|
|
1564
|
+
"ray",
|
|
1565
|
+
"hit",
|
|
1566
|
+
"surface",
|
|
1567
|
+
"materialReference",
|
|
1568
|
+
"mediumReference"
|
|
1569
|
+
]),
|
|
1570
|
+
writes: Object.freeze(["ray"]),
|
|
1571
|
+
continuationHitTypes: lightingWavefrontContinuationHitTypes,
|
|
1572
|
+
explicitLightSampling,
|
|
1573
|
+
visibilityProbeMode
|
|
1574
|
+
})
|
|
1575
|
+
])
|
|
1576
|
+
});
|
|
1577
|
+
}
|
|
1578
|
+
function evaluateWavefrontTerminalRadiance(options = {}) {
|
|
1579
|
+
const hitType = normalizeWavefrontHitType(options.hitType);
|
|
1580
|
+
const throughput = saturateVec3(normalizeVec3(options.throughput, [1, 1, 1]));
|
|
1581
|
+
const emission = saturateVec3(normalizeVec3(options.emission, [0, 0, 0]));
|
|
1582
|
+
const environmentRadiance = saturateVec3(
|
|
1583
|
+
normalizeVec3(options.environmentRadiance, [0, 0, 0])
|
|
1584
|
+
);
|
|
1585
|
+
const missRadiance = saturateVec3(
|
|
1586
|
+
normalizeVec3(options.missRadiance, defaultWavefrontDarkRadiance)
|
|
1587
|
+
);
|
|
1588
|
+
const environmentLuminance = colorLuminance(environmentRadiance);
|
|
1589
|
+
let source = "none";
|
|
1590
|
+
let rawRadiance = [0, 0, 0];
|
|
1591
|
+
if (hitType === "emissive") {
|
|
1592
|
+
source = "emissive";
|
|
1593
|
+
rawRadiance = emission;
|
|
1594
|
+
} else if (hitType === "environment") {
|
|
1595
|
+
source = "environment";
|
|
1596
|
+
rawRadiance = environmentRadiance;
|
|
1597
|
+
} else if (hitType === "miss") {
|
|
1598
|
+
source = environmentLuminance > 1e-6 ? "environment" : "dark";
|
|
1599
|
+
rawRadiance = environmentLuminance > 1e-6 ? environmentRadiance : missRadiance;
|
|
1600
|
+
}
|
|
1601
|
+
const radiance = multiplyVec3(throughput, rawRadiance);
|
|
1602
|
+
const terminated = lightingWavefrontTerminalHitTypes.includes(hitType);
|
|
1603
|
+
return Object.freeze({
|
|
1604
|
+
hitType,
|
|
1605
|
+
source,
|
|
1606
|
+
terminated,
|
|
1607
|
+
radiance: Object.freeze(radiance),
|
|
1608
|
+
nearDarkSample: source === "dark" && colorLuminance(radiance) <= colorLuminance(defaultWavefrontDarkRadiance)
|
|
1609
|
+
});
|
|
1610
|
+
}
|
|
1611
|
+
function evaluateWavefrontContinuationEvent(options = {}) {
|
|
1612
|
+
const hitType = normalizeWavefrontHitType(options.hitType);
|
|
1613
|
+
const bounceIndex = Math.max(0, Math.trunc(readFinite(options.bounceIndex, 0)));
|
|
1614
|
+
const maxDepth = Math.max(1, Math.trunc(readFinite(options.maxDepth, 4)));
|
|
1615
|
+
const throughput = saturateVec3(normalizeVec3(options.throughput, [1, 1, 1]));
|
|
1616
|
+
const albedo = saturateVec3(normalizeVec3(options.albedo, [0.8, 0.8, 0.8]));
|
|
1617
|
+
const transmission = saturateVec3(
|
|
1618
|
+
normalizeVec3(options.transmission, [0, 0, 0])
|
|
1619
|
+
);
|
|
1620
|
+
const shadingNormal = normalizeDirection(options.shadingNormal, [0, 1, 0]);
|
|
1621
|
+
const viewDirection = normalizeDirection(options.viewDirection, [0, 0, 1]);
|
|
1622
|
+
const incomingDirection = normalizeDirection(
|
|
1623
|
+
scaleVec3(viewDirection, -1),
|
|
1624
|
+
[0, 0, -1]
|
|
1625
|
+
);
|
|
1626
|
+
const frontFace = options.frontFace !== false;
|
|
1627
|
+
const orientedNormal = frontFace ? shadingNormal : scaleVec3(shadingNormal, -1);
|
|
1628
|
+
const metalness = clampUnit(options.metalness, 0);
|
|
1629
|
+
const roughness = clampUnit(options.roughness, 0.5);
|
|
1630
|
+
const opacity = clampUnit(options.opacity, 1);
|
|
1631
|
+
const refractiveIndex = Math.max(1, readFinite(options.refractiveIndex ?? options.ior, 1.45));
|
|
1632
|
+
const transmissionStrength = Math.max(...transmission);
|
|
1633
|
+
const requestedEventKind = normalizeWavefrontEventKind(options.eventKind) ?? (hitType === "transparent" || opacity < 0.999 ? "transparency" : transmissionStrength > 1e-3 ? "refraction" : metalness >= 0.5 || roughness <= 0.2 ? "reflection" : "diffuse");
|
|
1634
|
+
let eventKind = requestedEventKind;
|
|
1635
|
+
let totalInternalReflection = false;
|
|
1636
|
+
let nextDirection = incomingDirection;
|
|
1637
|
+
let attenuation;
|
|
1638
|
+
if (!lightingWavefrontContinuationHitTypes.includes(hitType) || bounceIndex >= maxDepth - 1) {
|
|
1639
|
+
eventKind = "terminate";
|
|
1640
|
+
attenuation = [0, 0, 0];
|
|
1641
|
+
} else if (eventKind === "reflection") {
|
|
1642
|
+
nextDirection = reflectDirection(incomingDirection, orientedNormal);
|
|
1643
|
+
attenuation = mixVec3([0.04, 0.04, 0.04], albedo, metalness);
|
|
1644
|
+
} else if (eventKind === "refraction") {
|
|
1645
|
+
const etaRatio = frontFace ? 1 / refractiveIndex : refractiveIndex;
|
|
1646
|
+
const refractedDirection = refractDirection(
|
|
1647
|
+
incomingDirection,
|
|
1648
|
+
orientedNormal,
|
|
1649
|
+
etaRatio
|
|
1650
|
+
);
|
|
1651
|
+
if (refractedDirection) {
|
|
1652
|
+
nextDirection = refractedDirection;
|
|
1653
|
+
attenuation = transmissionStrength > 1e-3 ? transmission : [1, 1, 1];
|
|
1654
|
+
} else {
|
|
1655
|
+
totalInternalReflection = true;
|
|
1656
|
+
eventKind = "reflection";
|
|
1657
|
+
nextDirection = reflectDirection(incomingDirection, orientedNormal);
|
|
1658
|
+
attenuation = mixVec3([0.04, 0.04, 0.04], albedo, metalness);
|
|
1659
|
+
}
|
|
1660
|
+
} else if (eventKind === "transparency") {
|
|
1661
|
+
nextDirection = incomingDirection;
|
|
1662
|
+
const transparencyWeight = Math.max(1 - opacity, transmissionStrength, 0.05);
|
|
1663
|
+
attenuation = transmissionStrength > 1e-3 ? transmission : [transparencyWeight, transparencyWeight, transparencyWeight];
|
|
1664
|
+
} else {
|
|
1665
|
+
nextDirection = normalizeDirection(
|
|
1666
|
+
addVec3(orientedNormal, albedo.map((component) => component - 0.5)),
|
|
1667
|
+
orientedNormal
|
|
1668
|
+
);
|
|
1669
|
+
attenuation = scaleVec3(albedo, Math.max(0.05, 1 - metalness));
|
|
1670
|
+
}
|
|
1671
|
+
const nextThroughput = multiplyVec3(throughput, saturateVec3(attenuation));
|
|
1672
|
+
const continueTracing = eventKind !== "terminate" && colorLuminance(nextThroughput) > 1e-4;
|
|
1673
|
+
const mediumState = evaluateWavefrontMediumState({
|
|
1674
|
+
currentMediumRefId: options.currentMediumRefId ?? options.mediumRefId,
|
|
1675
|
+
surfaceMediumRefId: options.surfaceMediumRefId,
|
|
1676
|
+
mediumStack: options.mediumStack,
|
|
1677
|
+
frontFace,
|
|
1678
|
+
eventKind
|
|
1679
|
+
});
|
|
1680
|
+
return Object.freeze({
|
|
1681
|
+
hitType,
|
|
1682
|
+
requestedEventKind,
|
|
1683
|
+
eventKind,
|
|
1684
|
+
continueTracing,
|
|
1685
|
+
totalInternalReflection,
|
|
1686
|
+
nextDirection: Object.freeze(nextDirection),
|
|
1687
|
+
attenuation: Object.freeze(saturateVec3(attenuation)),
|
|
1688
|
+
nextThroughput: Object.freeze(nextThroughput),
|
|
1689
|
+
mediumState,
|
|
1690
|
+
explicitLightSamplingEnabled: Boolean(options.explicitLightSampling)
|
|
1691
|
+
});
|
|
1692
|
+
}
|
|
1693
|
+
function evaluateWavefrontVisibilityProbe(options = {}) {
|
|
1694
|
+
const probeMode = normalizeWavefrontVisibilityProbeMode(
|
|
1695
|
+
options.probeMode ?? (options.explicitLightSampling ? "mis-balanced" : "disabled")
|
|
1696
|
+
);
|
|
1697
|
+
const probeRay = createWavefrontVisibilityProbeRay({
|
|
1698
|
+
...options.probeRay,
|
|
1699
|
+
throughput: options.throughput ?? options.probeRay?.throughput,
|
|
1700
|
+
direction: options.direction ?? options.probeRay?.direction,
|
|
1701
|
+
mediumRefId: options.currentMediumRefId ?? options.probeRay?.mediumRefId,
|
|
1702
|
+
mediumStack: options.mediumStack ?? options.probeRay?.mediumStack
|
|
1703
|
+
});
|
|
1704
|
+
const transparentSegments = Array.isArray(options.transparentSegments) ? options.transparentSegments : [];
|
|
1705
|
+
const transmittance = transparentSegments.reduce(
|
|
1706
|
+
(current, segment) => multiplyVec3(current, saturateVec3(normalizeVec3(segment, [1, 1, 1]))),
|
|
1707
|
+
[1, 1, 1]
|
|
1708
|
+
);
|
|
1709
|
+
const emissiveRadiance = saturateVec3(
|
|
1710
|
+
normalizeVec3(options.emissiveRadiance, [0, 0, 0])
|
|
1711
|
+
);
|
|
1712
|
+
const environmentRadiance = saturateVec3(
|
|
1713
|
+
normalizeVec3(options.environmentRadiance, [0, 0, 0])
|
|
1714
|
+
);
|
|
1715
|
+
const activeEmissiveRadiance = saturateVec3(
|
|
1716
|
+
normalizeVec3(options.activeEmissiveRadiance, [0, 0, 0])
|
|
1717
|
+
);
|
|
1718
|
+
const prefersEnvironment = Boolean(options.prefersEnvironment);
|
|
1719
|
+
const sourceRadiance = prefersEnvironment || colorLuminance(emissiveRadiance) <= 1e-6 ? environmentRadiance : emissiveRadiance;
|
|
1720
|
+
const rawContribution = multiplyVec3(
|
|
1721
|
+
probeRay.throughput,
|
|
1722
|
+
multiplyVec3(sourceRadiance, transmittance)
|
|
1723
|
+
);
|
|
1724
|
+
const activeEmissiveVisible = colorLuminance(activeEmissiveRadiance) > 1e-6;
|
|
1725
|
+
const misWeight = probeMode === "mis-balanced" && activeEmissiveVisible ? 0.5 : 1;
|
|
1726
|
+
const contribution = probeMode === "exclusive-emissive" && activeEmissiveVisible ? [0, 0, 0] : scaleVec3(rawContribution, misWeight);
|
|
1727
|
+
return Object.freeze({
|
|
1728
|
+
probeMode,
|
|
1729
|
+
probeRay,
|
|
1730
|
+
transmittance: Object.freeze(transmittance),
|
|
1731
|
+
misWeight,
|
|
1732
|
+
doubleCountPrevented: activeEmissiveVisible && probeMode !== "disabled",
|
|
1733
|
+
contribution: Object.freeze(contribution)
|
|
1734
|
+
});
|
|
1735
|
+
}
|
|
1736
|
+
function evaluateWavefrontMaterialReference(options = {}) {
|
|
1737
|
+
const material = Object.freeze({
|
|
1738
|
+
albedo: Object.freeze(
|
|
1739
|
+
saturateVec3(normalizeVec3(options.albedo, [0.8, 0.8, 0.8]))
|
|
1740
|
+
),
|
|
1741
|
+
emission: Object.freeze(
|
|
1742
|
+
saturateVec3(normalizeVec3(options.emission, [0, 0, 0]))
|
|
1743
|
+
),
|
|
1744
|
+
roughness: clampUnit(options.roughness, 0.5),
|
|
1745
|
+
metalness: clampUnit(options.metalness, 0),
|
|
1746
|
+
opacity: clampUnit(options.opacity, 1),
|
|
1747
|
+
transmission: Object.freeze(
|
|
1748
|
+
saturateVec3(normalizeVec3(options.transmission, [0, 0, 0]))
|
|
1749
|
+
),
|
|
1750
|
+
refractiveIndex: Math.max(
|
|
1751
|
+
1,
|
|
1752
|
+
readFinite(options.refractiveIndex ?? options.ior, 1.45)
|
|
1753
|
+
)
|
|
1754
|
+
});
|
|
1755
|
+
const continuation = evaluateWavefrontContinuationEvent({
|
|
1756
|
+
...options,
|
|
1757
|
+
albedo: material.albedo,
|
|
1758
|
+
roughness: material.roughness,
|
|
1759
|
+
metalness: material.metalness,
|
|
1760
|
+
opacity: material.opacity,
|
|
1761
|
+
transmission: material.transmission,
|
|
1762
|
+
refractiveIndex: material.refractiveIndex
|
|
1763
|
+
});
|
|
1764
|
+
const terminal = evaluateWavefrontTerminalRadiance({
|
|
1765
|
+
...options,
|
|
1766
|
+
emission: material.emission
|
|
1767
|
+
});
|
|
1768
|
+
return Object.freeze({
|
|
1769
|
+
material,
|
|
1770
|
+
terminal,
|
|
1771
|
+
continuation,
|
|
1772
|
+
throughputUpdate: continuation.nextThroughput
|
|
1773
|
+
});
|
|
1774
|
+
}
|
|
1775
|
+
function createWavefrontReferenceFixture(options = {}) {
|
|
1776
|
+
const tolerance = Math.max(1e-4, readFinite(options.tolerance, 5e-4));
|
|
1777
|
+
const ray = createWavefrontRayPayload({
|
|
1778
|
+
rayId: options.rayId,
|
|
1779
|
+
parentRayId: options.parentRayId,
|
|
1780
|
+
sourcePixelId: options.sourcePixelId,
|
|
1781
|
+
sampleId: options.sampleId,
|
|
1782
|
+
bounce: options.bounceIndex ?? options.bounce,
|
|
1783
|
+
origin: options.origin,
|
|
1784
|
+
direction: options.direction ?? scaleVec3(options.viewDirection ?? [0, 0, 1], -1),
|
|
1785
|
+
throughput: options.throughput,
|
|
1786
|
+
mediumRefId: options.currentMediumRefId ?? options.mediumRefId,
|
|
1787
|
+
mediumStack: options.mediumStack
|
|
1788
|
+
});
|
|
1789
|
+
const reference = evaluateWavefrontMaterialReference(options);
|
|
1790
|
+
const visibilityProbe = options.visibilityProbe === void 0 ? null : evaluateWavefrontVisibilityProbe({
|
|
1791
|
+
...options.visibilityProbe,
|
|
1792
|
+
throughput: options.visibilityProbe.throughput ?? ray.throughput
|
|
1793
|
+
});
|
|
1794
|
+
const accumulationRadiance = addVec3(
|
|
1795
|
+
reference.terminal.radiance,
|
|
1796
|
+
visibilityProbe?.contribution ?? [0, 0, 0]
|
|
1797
|
+
);
|
|
1798
|
+
return Object.freeze({
|
|
1799
|
+
tolerance,
|
|
1800
|
+
ray,
|
|
1801
|
+
material: reference.material,
|
|
1802
|
+
continuation: reference.continuation,
|
|
1803
|
+
terminal: reference.terminal,
|
|
1804
|
+
visibilityProbe,
|
|
1805
|
+
accumulation: Object.freeze({
|
|
1806
|
+
sourcePixelId: ray.sourcePixelId,
|
|
1807
|
+
sampleCount: reference.terminal.terminated ? 1 : 0,
|
|
1808
|
+
radiance: Object.freeze(accumulationRadiance),
|
|
1809
|
+
throughput: reference.continuation.nextThroughput,
|
|
1810
|
+
resetEpoch: Math.max(
|
|
1811
|
+
0,
|
|
1812
|
+
Math.trunc(readFinite(options.accumulationResetEpoch, 0))
|
|
1813
|
+
)
|
|
1814
|
+
})
|
|
1815
|
+
});
|
|
1816
|
+
}
|
|
1111
1817
|
var lightingImportanceLevels = Object.freeze([
|
|
1112
1818
|
"low",
|
|
1113
1819
|
"medium",
|
|
@@ -1673,6 +2379,91 @@ var lightingWorkerSpecPresets = {
|
|
|
1673
2379
|
}
|
|
1674
2380
|
}
|
|
1675
2381
|
},
|
|
2382
|
+
wavefront: {
|
|
2383
|
+
suggestedAllocationIds: [
|
|
2384
|
+
"lighting.wavefront.active-queue",
|
|
2385
|
+
"lighting.wavefront.next-queue",
|
|
2386
|
+
"lighting.wavefront.accumulation"
|
|
2387
|
+
],
|
|
2388
|
+
jobs: {
|
|
2389
|
+
accumulateTerminalRadiance: {
|
|
2390
|
+
domain: "lighting",
|
|
2391
|
+
importance: "critical",
|
|
2392
|
+
levels: buildWorkerBudgetLevels(
|
|
2393
|
+
"lighting.wavefront.accumulateTerminalRadiance",
|
|
2394
|
+
lightingWorkerQueueClass,
|
|
2395
|
+
{
|
|
2396
|
+
low: {
|
|
2397
|
+
estimatedCostMs: 0.7,
|
|
2398
|
+
maxDispatchesPerFrame: 1,
|
|
2399
|
+
maxJobsPerDispatch: 32,
|
|
2400
|
+
cadenceDivisor: 2,
|
|
2401
|
+
workgroupScale: 0.5,
|
|
2402
|
+
maxQueueDepth: 96
|
|
2403
|
+
},
|
|
2404
|
+
medium: {
|
|
2405
|
+
estimatedCostMs: 1.2,
|
|
2406
|
+
maxDispatchesPerFrame: 1,
|
|
2407
|
+
maxJobsPerDispatch: 64,
|
|
2408
|
+
cadenceDivisor: 1,
|
|
2409
|
+
workgroupScale: 0.75,
|
|
2410
|
+
maxQueueDepth: 192
|
|
2411
|
+
},
|
|
2412
|
+
high: {
|
|
2413
|
+
estimatedCostMs: 1.8,
|
|
2414
|
+
maxDispatchesPerFrame: 2,
|
|
2415
|
+
maxJobsPerDispatch: 128,
|
|
2416
|
+
cadenceDivisor: 1,
|
|
2417
|
+
workgroupScale: 1,
|
|
2418
|
+
maxQueueDepth: 256
|
|
2419
|
+
}
|
|
2420
|
+
}
|
|
2421
|
+
),
|
|
2422
|
+
suggestedAllocationIds: [
|
|
2423
|
+
"lighting.wavefront.accumulation",
|
|
2424
|
+
"lighting.wavefront.active-queue"
|
|
2425
|
+
]
|
|
2426
|
+
},
|
|
2427
|
+
scatterContinuations: {
|
|
2428
|
+
domain: "lighting",
|
|
2429
|
+
importance: "critical",
|
|
2430
|
+
levels: buildWorkerBudgetLevels(
|
|
2431
|
+
"lighting.wavefront.scatterContinuations",
|
|
2432
|
+
lightingWorkerQueueClass,
|
|
2433
|
+
{
|
|
2434
|
+
low: {
|
|
2435
|
+
estimatedCostMs: 0.8,
|
|
2436
|
+
maxDispatchesPerFrame: 1,
|
|
2437
|
+
maxJobsPerDispatch: 32,
|
|
2438
|
+
cadenceDivisor: 2,
|
|
2439
|
+
workgroupScale: 0.5,
|
|
2440
|
+
maxQueueDepth: 96
|
|
2441
|
+
},
|
|
2442
|
+
medium: {
|
|
2443
|
+
estimatedCostMs: 1.4,
|
|
2444
|
+
maxDispatchesPerFrame: 1,
|
|
2445
|
+
maxJobsPerDispatch: 64,
|
|
2446
|
+
cadenceDivisor: 1,
|
|
2447
|
+
workgroupScale: 0.75,
|
|
2448
|
+
maxQueueDepth: 192
|
|
2449
|
+
},
|
|
2450
|
+
high: {
|
|
2451
|
+
estimatedCostMs: 2.1,
|
|
2452
|
+
maxDispatchesPerFrame: 2,
|
|
2453
|
+
maxJobsPerDispatch: 128,
|
|
2454
|
+
cadenceDivisor: 1,
|
|
2455
|
+
workgroupScale: 1,
|
|
2456
|
+
maxQueueDepth: 256
|
|
2457
|
+
}
|
|
2458
|
+
}
|
|
2459
|
+
),
|
|
2460
|
+
suggestedAllocationIds: [
|
|
2461
|
+
"lighting.wavefront.active-queue",
|
|
2462
|
+
"lighting.wavefront.next-queue"
|
|
2463
|
+
]
|
|
2464
|
+
}
|
|
2465
|
+
}
|
|
2466
|
+
},
|
|
1676
2467
|
volumetrics: {
|
|
1677
2468
|
suggestedAllocationIds: [
|
|
1678
2469
|
"lighting.volumetrics.froxel-grid",
|
|
@@ -1882,6 +2673,13 @@ var lightingWorkerDagSpecs = {
|
|
|
1882
2673
|
accumulate: { priority: 3, dependencies: ["pathTrace"] },
|
|
1883
2674
|
denoise: { priority: 2, dependencies: ["accumulate"] }
|
|
1884
2675
|
},
|
|
2676
|
+
wavefront: {
|
|
2677
|
+
accumulateTerminalRadiance: { priority: 3, dependencies: [] },
|
|
2678
|
+
scatterContinuations: {
|
|
2679
|
+
priority: 2,
|
|
2680
|
+
dependencies: ["accumulateTerminalRadiance"]
|
|
2681
|
+
}
|
|
2682
|
+
},
|
|
1885
2683
|
volumetrics: {
|
|
1886
2684
|
volumetricShadow: { priority: 3, dependencies: [] },
|
|
1887
2685
|
froxelIntegrate: { priority: 2, dependencies: ["volumetricShadow"] }
|
|
@@ -1915,6 +2713,16 @@ function resolveLightingQualityDimensions(techniqueName, jobKey) {
|
|
|
1915
2713
|
"pathtracer.pathTrace": { rayTracing: 1, lightingSamples: 1 },
|
|
1916
2714
|
"pathtracer.accumulate": { temporalReuse: 1, updateCadence: 0.4 },
|
|
1917
2715
|
"pathtracer.denoise": { temporalReuse: 1, shading: 0.4 },
|
|
2716
|
+
"wavefront.accumulateTerminalRadiance": {
|
|
2717
|
+
rayTracing: 1,
|
|
2718
|
+
lightingSamples: 1,
|
|
2719
|
+
temporalReuse: 0.4
|
|
2720
|
+
},
|
|
2721
|
+
"wavefront.scatterContinuations": {
|
|
2722
|
+
rayTracing: 1,
|
|
2723
|
+
shading: 0.7,
|
|
2724
|
+
updateCadence: 0.5
|
|
2725
|
+
},
|
|
1918
2726
|
"volumetrics.froxelIntegrate": {
|
|
1919
2727
|
lightingSamples: 0.6,
|
|
1920
2728
|
shading: 0.4,
|
|
@@ -1959,6 +2767,15 @@ function resolveLightingImportanceSignals(techniqueName, jobKey) {
|
|
|
1959
2767
|
},
|
|
1960
2768
|
"pathtracer.accumulate": { visible: true },
|
|
1961
2769
|
"pathtracer.denoise": { visible: true },
|
|
2770
|
+
"wavefront.accumulateTerminalRadiance": {
|
|
2771
|
+
visible: true,
|
|
2772
|
+
shadowSignificance: "high",
|
|
2773
|
+
reflectionSignificance: "high"
|
|
2774
|
+
},
|
|
2775
|
+
"wavefront.scatterContinuations": {
|
|
2776
|
+
visible: true,
|
|
2777
|
+
reflectionSignificance: "high"
|
|
2778
|
+
},
|
|
1962
2779
|
"volumetrics.froxelIntegrate": { visible: true },
|
|
1963
2780
|
"volumetrics.volumetricShadow": { visible: true, shadowSignificance: "high" },
|
|
1964
2781
|
"hdri.irradianceConvolution": { visible: false },
|
|
@@ -2229,9 +3046,18 @@ async function loadLightingProfileWorkerPlan(profileName = defaultLightingProfil
|
|
|
2229
3046
|
createLightingBandPlan,
|
|
2230
3047
|
createLightingProfileModeLadder,
|
|
2231
3048
|
createWavefrontEnvironmentLightingOptions,
|
|
3049
|
+
createWavefrontLightingPlan,
|
|
3050
|
+
createWavefrontRayPayload,
|
|
3051
|
+
createWavefrontReferenceFixture,
|
|
3052
|
+
createWavefrontVisibilityProbeRay,
|
|
2232
3053
|
defaultAdaptiveLightingProfilePolicy,
|
|
2233
3054
|
defaultLightingProfile,
|
|
2234
3055
|
defaultLightingTechnique,
|
|
3056
|
+
evaluateWavefrontContinuationEvent,
|
|
3057
|
+
evaluateWavefrontMaterialReference,
|
|
3058
|
+
evaluateWavefrontMediumState,
|
|
3059
|
+
evaluateWavefrontTerminalRadiance,
|
|
3060
|
+
evaluateWavefrontVisibilityProbe,
|
|
2235
3061
|
getLightingProfile,
|
|
2236
3062
|
getLightingProfileWorkerManifest,
|
|
2237
3063
|
getLightingTechnique,
|
|
@@ -2250,8 +3076,19 @@ async function loadLightingProfileWorkerPlan(profileName = defaultLightingProfil
|
|
|
2250
3076
|
lightingProfileModeOrder,
|
|
2251
3077
|
lightingProfileNames,
|
|
2252
3078
|
lightingProfiles,
|
|
3079
|
+
lightingRequiredRendererWavefrontPassOrder,
|
|
2253
3080
|
lightingTechniqueNames,
|
|
2254
3081
|
lightingTechniques,
|
|
3082
|
+
lightingWavefrontBufferContracts,
|
|
3083
|
+
lightingWavefrontContinuationHitTypes,
|
|
3084
|
+
lightingWavefrontHitTypes,
|
|
3085
|
+
lightingWavefrontPassOrder,
|
|
3086
|
+
lightingWavefrontQueuePairStrategy,
|
|
3087
|
+
lightingWavefrontRayKinds,
|
|
3088
|
+
lightingWavefrontSchemaVersion,
|
|
3089
|
+
lightingWavefrontTerminalHitTypes,
|
|
3090
|
+
lightingWavefrontTerminationPolicy,
|
|
3091
|
+
lightingWavefrontVisibilityProbeModes,
|
|
2255
3092
|
lightingWorkerManifests,
|
|
2256
3093
|
lightingWorkerQueueClass,
|
|
2257
3094
|
loadLightingJobs,
|