three-realtime-rt 0.3.0 → 0.4.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 +559 -394
- package/package.json +52 -52
- package/src/CompositePass.js +261 -214
- package/src/CopyPass.js +75 -0
- package/src/DenoisePass.js +221 -202
- package/src/GBufferPass.js +290 -228
- package/src/RTLightingPass.js +1124 -680
- package/src/RealtimeRaytracer.js +1106 -730
- package/src/RestirPass.js +31 -4
- package/src/SceneCompiler.js +542 -424
- package/src/TAAPass.js +271 -230
- package/src/VolumetricPass.js +398 -329
- package/src/blueNoise.js +17 -17
- package/src/index.d.ts +107 -6
package/src/RestirPass.js
CHANGED
|
@@ -21,6 +21,7 @@ uniform sampler2D uGNormalMetal;
|
|
|
21
21
|
uniform sampler2D uMaterialsTex; // row 1: emissive tris, rows 2..65: blue noise
|
|
22
22
|
uniform vec4 uLightPosType[MAX_LIGHTS];
|
|
23
23
|
uniform vec4 uLightColorRadius[MAX_LIGHTS];
|
|
24
|
+
uniform vec4 uLightDirCone[MAX_LIGHTS]; // spot: direction.xyz + cos(outer)
|
|
24
25
|
uniform int uLightCount;
|
|
25
26
|
uniform int uEmissiveCount;
|
|
26
27
|
uniform float uFrame;
|
|
@@ -53,23 +54,45 @@ vec4 fetchBlueNoise() {
|
|
|
53
54
|
|
|
54
55
|
float luminance(vec3 c) { return dot(c, vec3(0.299, 0.587, 0.114)); }
|
|
55
56
|
|
|
57
|
+
// Primary-surface roughness, set per pixel in main(). Drives the cheap specular
|
|
58
|
+
// lobe below so reservoirs favour lights that land on a highlight.
|
|
59
|
+
float gRestirRough;
|
|
60
|
+
|
|
61
|
+
// Cheap Blinn-Phong specular lobe for the target pdf ONLY (never shaded with
|
|
62
|
+
// this). Deliberately approximate — no Fresnel or geometry term, one pow() per
|
|
63
|
+
// candidate — since it just biases which light each reservoir keeps. wi points
|
|
64
|
+
// from the surface toward the light. Returns a multiplier boost in [0, ~0.8].
|
|
65
|
+
float restirSpecBoost(vec3 N, vec3 wi, vec3 P) {
|
|
66
|
+
vec3 V = normalize(uCameraPos - P);
|
|
67
|
+
vec3 H = normalize(wi + V);
|
|
68
|
+
float shin = mix(4.0, 256.0, 1.0 - gRestirRough);
|
|
69
|
+
return 0.8 * pow(max(dot(N, H), 0.0), shin);
|
|
70
|
+
}
|
|
71
|
+
|
|
56
72
|
// Unshadowed contribution of candidate (id, uv) at surface (P, N).
|
|
57
73
|
vec3 candidateContribution(float id, vec2 uv, vec3 P, vec3 N) {
|
|
58
74
|
if (id < float(MAX_LIGHTS)) {
|
|
59
75
|
int i = int(id);
|
|
60
76
|
vec4 posType = uLightPosType[i];
|
|
61
77
|
vec4 colRad = uLightColorRadius[i];
|
|
62
|
-
if (posType.w < 0.5) {
|
|
78
|
+
if (posType.w < 0.5 || posType.w >= 1.5) {
|
|
63
79
|
vec3 d = posType.xyz - P; // light CENTER: soft-radius jitter re-drawn at shading
|
|
64
80
|
float dl = length(d);
|
|
65
81
|
if (dl < 1e-5) return vec3(0.0);
|
|
66
82
|
float NdotL = dot(N, d / dl);
|
|
67
83
|
if (NdotL <= 0.0) return vec3(0.0);
|
|
68
|
-
|
|
84
|
+
float cone = 1.0;
|
|
85
|
+
if (posType.w >= 1.5) {
|
|
86
|
+
// spot cone — MUST match RTLightingPass.spotFalloff for a consistent estimator
|
|
87
|
+
vec4 dc = uLightDirCone[i];
|
|
88
|
+
cone = smoothstep(dc.w, posType.w - 2.0, dot(dc.xyz, -d / dl));
|
|
89
|
+
if (cone <= 0.0) return vec3(0.0);
|
|
90
|
+
}
|
|
91
|
+
return colRad.rgb * (cone * NdotL / (dl * dl)) * (1.0 + restirSpecBoost(N, d / dl, P));
|
|
69
92
|
}
|
|
70
93
|
float NdotL = dot(N, -posType.xyz);
|
|
71
94
|
if (NdotL <= 0.0) return vec3(0.0);
|
|
72
|
-
return colRad.rgb * NdotL;
|
|
95
|
+
return colRad.rgb * NdotL * (1.0 + restirSpecBoost(N, -posType.xyz, P));
|
|
73
96
|
}
|
|
74
97
|
int t = (int(id) - MAX_LIGHTS) * 4;
|
|
75
98
|
vec4 t0 = texelFetch(uMaterialsTex, ivec2(t, 1), 0);
|
|
@@ -87,7 +110,7 @@ vec3 candidateContribution(float id, vec2 uv, vec3 P, vec3 N) {
|
|
|
87
110
|
if (cosS <= 0.0 || cosL < 1e-4) return vec3(0.0);
|
|
88
111
|
// Uniform pick within the emissive set happens at candidate level, so the
|
|
89
112
|
// per-triangle contribution uses area only (count folds into pick pdf).
|
|
90
|
-
return vec3(t1.w, t2.w, t3.w) * (cosS * cosL * t0.w / max(d2, 1e-6));
|
|
113
|
+
return vec3(t1.w, t2.w, t3.w) * (cosS * cosL * t0.w / max(d2, 1e-6)) * (1.0 + restirSpecBoost(N, wi, P));
|
|
91
114
|
}
|
|
92
115
|
|
|
93
116
|
// v3: reservoirs select TRIANGLES, not points. The selection target is the
|
|
@@ -129,6 +152,7 @@ void main() {
|
|
|
129
152
|
}
|
|
130
153
|
vec3 P = wp.xyz;
|
|
131
154
|
vec3 N = normalize(texture(uGNormalMetal, vUv).xyz);
|
|
155
|
+
gRestirRough = clamp(wp.w - 1.0, 0.0, 1.0);
|
|
132
156
|
|
|
133
157
|
ivec2 px = ivec2(gl_FragCoord.xy);
|
|
134
158
|
gSeed = uint(px.x) * 3079u + uint(px.y) * 9277u + uint(uFrame) * 26699u;
|
|
@@ -215,6 +239,7 @@ void main() {
|
|
|
215
239
|
}
|
|
216
240
|
vec3 P = wp.xyz;
|
|
217
241
|
vec3 N = normalize(texture(uGNormalMetal, vUv).xyz);
|
|
242
|
+
gRestirRough = clamp(wp.w - 1.0, 0.0, 1.0);
|
|
218
243
|
|
|
219
244
|
ivec2 px = ivec2(gl_FragCoord.xy);
|
|
220
245
|
gSeed = uint(px.x) * 5417u + uint(px.y) * 7907u + uint(uFrame) * 15731u;
|
|
@@ -283,6 +308,7 @@ export class RestirPass {
|
|
|
283
308
|
uMaterialsTex: { value: null },
|
|
284
309
|
uLightPosType: { value: [] },
|
|
285
310
|
uLightColorRadius: { value: [] },
|
|
311
|
+
uLightDirCone: { value: [] },
|
|
286
312
|
uLightCount: { value: 0 },
|
|
287
313
|
uEmissiveCount: { value: 0 },
|
|
288
314
|
uFrame: { value: 0 },
|
|
@@ -334,6 +360,7 @@ export class RestirPass {
|
|
|
334
360
|
u.uMaterialsTex.value = compiled.materialsTex;
|
|
335
361
|
u.uLightPosType.value = compiled.lightPosType;
|
|
336
362
|
u.uLightColorRadius.value = compiled.lightColorRadius;
|
|
363
|
+
u.uLightDirCone.value = compiled.lightDirCone;
|
|
337
364
|
u.uLightCount.value = compiled.lightCount;
|
|
338
365
|
u.uEmissiveCount.value = compiled.emissiveTriCount;
|
|
339
366
|
}
|