Skip to content

Commit 5e3fa00

Browse files
committed
fix motion vector
1 parent 00e8a10 commit 5e3fa00

File tree

11 files changed

+195
-173
lines changed

11 files changed

+195
-173
lines changed
Lines changed: 87 additions & 76 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
height: 100%;
3030
}
3131
</style>
32-
<script type="module" crossorigin src="./assets/index-tF8bsfuq.js"></script>
32+
<script type="module" crossorigin src="./assets/index-C6cDfAF8.js"></script>
3333
</head>
3434
<body>
3535
<canvas></canvas>

src/device.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ class webGPUDevice {
44
device: GPUDevice;
55
context: GPUCanvasContext;
66
format: GPUTextureFormat;
7-
upscaleRatio: number = 2;
7+
upscaleRatio: number = 1;
88

99
async init(canvas: HTMLCanvasElement) {
1010
this.canvas = canvas;

src/raytracing.ts

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ class rayTracing {
88
device: webGPUDevice;
99
model: gltfmodel;
1010
camera: CameraManager;
11-
lightCount: number = 2;
12-
spatialReuseIteration: number = 4;
11+
lightCount: number = 1;
12+
spatialReuseIteration: number = 2;
1313
GI_FLAG: number = 1;
1414

1515
vBuffer: GPUTexture;
@@ -92,26 +92,26 @@ class rayTracing {
9292
let lights = Array<light>(cnt);
9393
const dimension = Math.sqrt(cnt);
9494
// lights[0] = new light(new Float32Array([0, 18, 3.5]), new Float32Array([1, 1, 1]), 2500, 0);
95-
lights[0] = new light(new Float32Array([0, 5, 0]), new Float32Array([0.4, 0.9, 1]), 40, 0);
96-
lights[1] = new light(new Float32Array([-4, 5, 0]), new Float32Array([1, 0.9, 0.4]), 30, 1);
95+
lights[0] = new light(new Float32Array([0, 5, 0]), new Float32Array([0.7, 0.9, 1]), 80, 0);
96+
// lights[1] = new light(new Float32Array([-4, 5, 0]), new Float32Array([1, 0.9, 0.4]), 60, 1);
9797
// generate light in grid
98-
for (let i = 2; i < cnt; i++) {
99-
// let x = (i % dimension) / dimension * 12 - 6;
100-
// let y = 5;
101-
// let z = Math.floor(i / dimension) / dimension * 12 - 6;
102-
// // generate color correlated to the position randomly
103-
// let r = Math.abs(x) / 6;
104-
// let g = 0.5;
105-
// let b = Math.abs(z) / 6;
106-
let x = Math.random() * 12 - 6;
107-
let y = Math.random() * 8;
108-
let z = Math.random() * 12 - 6;
109-
let r = Math.random() * 0.7 + 0.3;
110-
let g = Math.random() * 0.7 + 0.3;
111-
let b = Math.random() * 0.7 + 0.3;
112-
let intensity = Math.random() * 20 + 20;
113-
lights[i] = new light(new Float32Array([x, y, z]), new Float32Array([r, g, b]), intensity, i);
114-
}
98+
// for (let i = 0; i < cnt; i++) {
99+
// // let x = (i % dimension) / dimension * 12 - 6;
100+
// // let y = 5;
101+
// // let z = Math.floor(i / dimension) / dimension * 12 - 6;
102+
// // // generate color correlated to the position randomly
103+
// // let r = Math.abs(x) / 6;
104+
// // let g = 0.5;
105+
// // let b = Math.abs(z) / 6;
106+
// let x = Math.random() * 12 - 6;
107+
// let y = Math.random() * 8;
108+
// let z = Math.random() * 12 - 6;
109+
// let r = Math.random() * 0.7 + 0.3;
110+
// let g = Math.random() * 0.7 + 0.3;
111+
// let b = Math.random() * 0.7 + 0.3;
112+
// let intensity = Math.random() * 5 + 10;
113+
// lights[i] = new light(new Float32Array([x, y, z]), new Float32Array([r, g, b]), intensity, i);
114+
// }
115115

116116
this.lightBuffer = this.device.device.createBuffer({
117117
label: 'light buffer',
@@ -176,7 +176,7 @@ class rayTracing {
176176
unit[i] *= speed;
177177
this.lightVelocity[i] = unit;
178178
}
179-
// this.lightVelocity[0] = [0, 4., 0];
179+
this.lightVelocity[0] = [2, 0., 0];
180180
}
181181
private buildBindGroupLayout() {
182182
this.bindGroupLayoutInit = this.device.device.createBindGroupLayout({
@@ -574,8 +574,8 @@ class rayTracing {
574574
uboFloat.set(this.camera.camera.position.toArray(), 0);
575575
this.device.device.queue.writeBuffer(this.uniformBuffer, 0, this.uboBuffer);
576576
// update light position
577-
const minBound = [-6, 1, -1];
578-
const maxBound = [6, 8, 1];
577+
const minBound = [-5, 1, -1];
578+
const maxBound = [5, 8, 1];
579579
const center = [0, 5, 0];
580580
for (let i = 0; i < this.lightCount; i++) {
581581
for (let j = 0; j < 3; j++) {

src/shaders/display.wgsl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ fn main(@builtin(global_invocation_id) GlobalInvocationID: vec3u) {
3737
// |
3838
// v
3939
// Y
40-
let motionVec: vec2f = unpack2x16float(visibility.w);
40+
let motionVec: vec2f = unpack2x16snorm(visibility.w) * vec2f(origin_size.xy);
4141
// textureStore(currentDisplay, screen_pos, vec4f(motionVec.xy * 0.05 + 0.5, 0.0, 1.0));
4242
let trianlgeID = visibility.z;
4343
// textureStore(currentDisplay, screen_pos, vec4f(vec3f(f32(visibility.z) / 3.), 1.));

src/shaders/tracing/BSDF.wgsl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,10 @@ fn FmetallicLuminance(baseColorLuminance: f32, roughness: f32, ndoth: f32, h: ve
5858

5959
fn BSDF(shadingPoint: PointInfo, wo: vec3f, wi: vec3f) -> vec3f {
6060
let h = normalize(wi + wo);
61-
let ndoti = max(0.000, dot(shadingPoint.normalShading, wi));
62-
let ndoto = max(0.000, dot(shadingPoint.normalShading, wo));
61+
let ndoti = max(0.01, dot(shadingPoint.normalShading, wi));
62+
let ndoto = max(0.01, dot(shadingPoint.normalShading, wo));
6363
let hdoto = dot(h, wo);
64-
let ndoth = max(0.000, dot(shadingPoint.normalShading, h));
64+
let ndoth = max(0.01, dot(shadingPoint.normalShading, h));
6565
let diffuse = Fdiffuse(shadingPoint.baseColor, shadingPoint.metallicRoughness.y, ndoti, ndoto, hdoto);
6666
let metallic = Fmetallic(shadingPoint.baseColor, shadingPoint.metallicRoughness.y, ndoth, h, hdoto, ndoti, ndoto);
6767
return (1.0 - shadingPoint.metallicRoughness.x) * diffuse + (shadingPoint.metallicRoughness.x) * metallic;

src/shaders/tracing/accumulate.wgsl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ fn main(@builtin(global_invocation_id) GlobalInvocationID: vec3u) {
6464
reservoirGI.w_sum = 0.;
6565
} else {
6666
bsdf = BSDF(pointInfo, wo, wi);
67-
// geometryTerm = reservoirGI.Lo / Jacobian(shadingPoint, reservoirGI);
6867
geometryTerm = reservoirGI.Lo;
68+
// geometryTerm = reservoirGI.Lo / Jacobian(shadingPoint, reservoirGI);
6969
color += reservoirGI.W * bsdf * geometryTerm * 4.;
7070
}
7171
}

src/shaders/tracing/rayGen.wgsl

Lines changed: 54 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ fn main(@builtin(global_invocation_id) GlobalInvocationID: vec3u, @builtin(workg
7676
var pointPrev: PointAttri;
7777

7878

79-
let globalPreId = vec2f(GlobalInvocationID.xy) + 0.5 - primaryTri.motionVec;
79+
let globalPreId = vec2f(GlobalInvocationID.xy) + 0.5 - primaryTri.motionVec * vec2f(screen_size);
8080
let launchPreIndex = select(-1, i32(globalPreId.y) * i32(screen_size.x) + i32(globalPreId.x), all(globalPreId >= vec2f(0.0)) && all(globalPreId < vec2f(screen_size)));
8181
let shadingPoint: vec3f = pointInfo.pos;
8282

@@ -125,41 +125,43 @@ fn main(@builtin(global_invocation_id) GlobalInvocationID: vec3u, @builtin(workg
125125
}
126126

127127
// indirect illumination
128-
if ENABLE_GI {
129-
let sampleVec: vec4f = samplingHemisphere();
130-
// let sampleVec: vec4f = vec4f(0.0, 0.0, 1.0, 1.0);
131-
let wi: vec3f = normalize(generateTBN(pointInfo.normalGeo) * sampleVec.xyz);
132-
let tracePdf = max(0.001, sampleVec.w);
133-
if dot(wi, pointInfo.normalGeo) >= 0. {
134-
let rayInfo: RayInfo = traceRay(pointInfo.pos, wi);
135-
if rayInfo.isHit == 1 {
136-
let triangle: PrimaryHitInfo = PrimaryHitInfo(rayInfo.hitAttribute, rayInfo.PrimitiveIndex, vec2f(0));
137-
let pointSampleInfo: PointInfo = unpackTriangleIndirect(triangle, wi);
138-
let samplePoint = pointSampleInfo.pos;
128+
// if ENABLE_GI {
129+
// let sampleVec: vec4f = samplingHemisphere();
130+
// // let sampleVec: vec4f = vec4f(0.0, 0.0, 1.0, 1.0);
131+
// let wi: vec3f = normalize(generateTBN(pointInfo.normalGeo) * sampleVec.xyz);
132+
// let tracePdf = max(0.01, sampleVec.w);
133+
// if dot(wi, pointInfo.normalGeo) >= 0. {
134+
// let rayInfo: RayInfo = traceRay(pointInfo.pos, wi);
135+
// if rayInfo.isHit == 1 {
136+
// let triangle: PrimaryHitInfo = PrimaryHitInfo(rayInfo.hitAttribute, rayInfo.PrimitiveIndex, vec2f(0));
137+
// let pointSampleInfo: PointInfo = unpackTriangleIndirect(triangle, wi);
138+
// let samplePoint = pointSampleInfo.pos;
139139

140-
light = sampleLight();
141-
let lightPdf = sampleLightProb(light);
142-
wo = light.position - samplePoint;
143-
dist = length(wo);
144-
wo = normalize(wo);
145-
// check the visibility from sample point to light
146-
if dot(wo, pointSampleInfo.normalShading) > 0.0 && dot(wo, pointSampleInfo.normalGeo) > 0.0 {
147-
if !traceShadowRay(samplePoint, wo, dist) {
148-
let geometryTerm = light.color * light.intensity / (dist * dist);
149-
let bsdf = BSDF(pointSampleInfo, wo, -wi);
150-
let Lo = bsdf * geometryTerm / lightPdf;
151-
updateReservoirGI(&reservoirCurGI, pointInfo.pos, pointInfo.normalShading, pointSampleInfo.pos, pointSampleInfo.normalShading, luminance(Lo) / tracePdf, Lo, light.id);
152-
}
153-
}
154-
}
155-
}
156-
reservoirCurGI.M = 1;
157-
}
140+
// light = sampleLight();
141+
// let lightPdf = sampleLightProb(light);
142+
// wo = light.position - samplePoint;
143+
// dist = length(wo);
144+
// wo = normalize(wo);
145+
// // check the visibility from sample point to light
146+
// if dot(wo, pointSampleInfo.normalShading) > 0.0 && dot(wo, pointSampleInfo.normalGeo) > 0.0 {
147+
// if !traceShadowRay(samplePoint, wo, dist) {
148+
// let geometryTerm = light.color * light.intensity / (dist * dist);
149+
// let bsdf = BSDF(pointSampleInfo, wo, -wi);
150+
// let Lo = bsdf * geometryTerm / lightPdf;
151+
// updateReservoirGI(&reservoirCurGI, pointInfo.pos, pointInfo.normalShading, pointSampleInfo.pos, pointSampleInfo.normalShading, luminance(Lo) / tracePdf, Lo, light.id);
152+
// }
153+
// }
154+
// }
155+
// }
156+
// reservoirCurGI.M = 1;
157+
// }
158158

159159
// temperal reuse
160160

161-
let depth = distance(shadingPoint, origin);
162-
if distance(shadingPoint, pointPrev.pos) < 0.1 * depth && dot(pointInfo.normalShading, pointPrev.normalShading) > 0.9 {
161+
// plane distance
162+
let posDiff = pointPrev.pos - pointInfo.pos;
163+
let planeDist = abs(dot(posDiff, pointInfo.normalShading));
164+
if dot(pointInfo.normalShading, pointPrev.normalShading) > 0.5 && planeDist < 0.05 {
163165
if reservoirPrevDI.W > 0.0 {
164166
const capped = 8u;
165167
reservoirPrevDI.M = min(reservoirPrevDI.M, capped * reservoirCurDI.M);
@@ -177,27 +179,30 @@ fn main(@builtin(global_invocation_id) GlobalInvocationID: vec3u, @builtin(workg
177179
}
178180
}
179181
if ENABLE_GI {
180-
reservoirPrevGI.M = min(reservoirPrevGI.M, 30);
181-
wo = reservoirPrevGI.xs - shadingPoint;
182-
dist = length(wo);
183-
wo = normalize(wo);
182+
if reservoirPrevGI.W > 0.0 {
183+
reservoirPrevGI.M = min(reservoirPrevGI.M, 20);
184+
wo = reservoirPrevGI.xs - shadingPoint;
185+
dist = length(wo);
186+
wo = normalize(wo);
184187

185-
var flag = true;
186-
if f32(_seed & 0x7fffffff) / f32(0x80000000) < 1. / 8. {
188+
var flag = true;
189+
if f32(_seed & 0x7fffffff) / f32(0x80000000) < 1. / 8. {
187190
// check visibility from light to sample point
188-
light = getLight(reservoirPrevGI.lightId);
189-
let dir = light.position - reservoirPrevGI.xs;
190-
let dist = length(dir);
191-
let wo = normalize(dir);
192-
if traceShadowRay(reservoirPrevGI.xs, wo, dist) {
193-
flag = false;
191+
light = getLight(reservoirPrevGI.lightId);
192+
let dir = light.position - reservoirPrevGI.xs;
193+
let dist = length(dir);
194+
let wo = normalize(dir);
195+
if traceShadowRay(reservoirPrevGI.xs, wo, dist) {
196+
flag = false;
197+
}
194198
}
195-
}
196-
if flag && dot(wo, pointInfo.normalShading) > 0.0 && dot(wo, pointInfo.normalGeo) > 0.0 {
197-
pHat = luminance(reservoirPrevGI.Lo);
198-
reservoirPrevGI.w_sum = pHat * reservoirPrevGI.W * f32(reservoirPrevGI.M);
199+
if flag && dot(wo, pointInfo.normalShading) > 0.0 && dot(wo, pointInfo.normalGeo) > 0.0 {
200+
pHat = luminance(reservoirPrevGI.Lo);
201+
// pHat = luminance(reservoirPrevGI.Lo) / Jacobian(pointInfo.pos, reservoirPrevGI);
202+
reservoirPrevGI.w_sum = pHat * reservoirPrevGI.W * f32(reservoirPrevGI.M);
199203

200-
combineReservoirsGI(&reservoirCurGI, reservoirPrevGI);
204+
combineReservoirsGI(&reservoirCurGI, reservoirPrevGI);
205+
}
201206
}
202207
}
203208
}

src/shaders/tracing/sampleInit.wgsl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ fn primaryHit(screen_pos: vec2u) -> PrimaryHitInfo {
1010
let bataGamma = bitcast<vec2f>(visibilityInfo.xy);
1111
primaryHitInfo.baryCoord = vec3f(1.0 - bataGamma.x - bataGamma.y, bataGamma.x, bataGamma.y);
1212
primaryHitInfo.primId = visibilityInfo.z;
13-
primaryHitInfo.motionVec = unpack2x16float(visibilityInfo.w);
13+
primaryHitInfo.motionVec = unpack2x16snorm(visibilityInfo.w);
1414
return primaryHitInfo;
1515
}
1616

src/shaders/tracing/spatialReuse.wgsl

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -55,27 +55,33 @@ fn main(@builtin(global_invocation_id) GlobalInvocationID: vec3u) {
5555
var neighbor_reservoirGI = ReservoirGI();
5656
loadReservoir(&previousReservoir, neighbor_launchIndex, &neighbor_reservoirDI, &neighbor_reservoirGI, &_seed);
5757
let neighbour_pointAttri: PointAttri = loadGBufferAttri(&gBufferAttri, neighbor_launchIndex);
58-
// check distance and normal diff
59-
if neighbor_reservoirDI.W > 0. && distance(shadingPoint, neighbour_pointAttri.pos) <= 0.04 * depth && dot(pointInfo.normalShading, neighbour_pointAttri.normalShading) >= .9 {
60-
light = getLight(neighbor_reservoirDI.lightId);
61-
wo = light.position - pointInfo.pos;
62-
dist = length(wo);
63-
wo = normalize(wo);
64-
if dot(wo, pointInfo.normalShading) > 0. {
58+
// check plane distance
59+
let posDiff = pointInfo.pos - neighbour_pointAttri.pos;
60+
let planeDist = abs(dot(posDiff, pointInfo.normalShading));
61+
if planeDist < 0.04 && dot(pointInfo.normalShading, neighbour_pointAttri.normalShading) > .8 {
62+
// color += vec3f(0.2);
63+
if neighbor_reservoirDI.W > 0. {
64+
light = getLight(neighbor_reservoirDI.lightId);
65+
wo = light.position - pointInfo.pos;
66+
dist = length(wo);
67+
wo = normalize(wo);
68+
if dot(wo, pointInfo.normalShading) > 0. {
6569
// color += vec3f(0.2);
66-
neighbor_reservoirDI.M = min(neighbor_reservoirDI.M, 256);
67-
geometryTerm_luminance = light.intensity / (dist * dist);
68-
bsdfLuminance = BSDFLuminance(pointInfo, wo, wi);
69-
pHat = geometryTerm_luminance * bsdfLuminance;
70-
neighbor_reservoirDI.w_sum = pHat * neighbor_reservoirDI.W * f32(neighbor_reservoirDI.M);
71-
combineReservoirsDI(&reservoirDI, neighbor_reservoirDI);
70+
neighbor_reservoirDI.M = min(neighbor_reservoirDI.M, 256);
71+
geometryTerm_luminance = light.intensity / (dist * dist);
72+
bsdfLuminance = BSDFLuminance(pointInfo, wo, wi);
73+
pHat = geometryTerm_luminance * bsdfLuminance;
74+
neighbor_reservoirDI.w_sum = pHat * neighbor_reservoirDI.W * f32(neighbor_reservoirDI.M);
75+
combineReservoirsDI(&reservoirDI, neighbor_reservoirDI);
76+
}
7277
}
7378
if ENABLE_GI {
7479
wo = neighbor_reservoirGI.xs - pointInfo.pos;
7580
dist = length(wo);
7681
wo = normalize(wo);
7782
if dot(wo, pointInfo.normalShading) > 0. {
78-
neighbor_reservoirGI.M = min(neighbor_reservoirGI.M, 256);
83+
neighbor_reservoirGI.M = min(neighbor_reservoirGI.M, 200);
84+
// pHat = luminance(neighbor_reservoirGI.Lo) / Jacobian(pointInfo.pos, neighbor_reservoirGI);
7985
pHat = luminance(neighbor_reservoirGI.Lo);
8086
neighbor_reservoirGI.w_sum = pHat * neighbor_reservoirGI.W * f32(neighbor_reservoirGI.M);
8187
combineReservoirsGI(&reservoirGI, neighbor_reservoirGI);

0 commit comments

Comments
 (0)