|
10 | 10 | override WorkgroupSizeX : u32;
|
11 | 11 | override WorkgroupSizeY : u32;
|
12 | 12 |
|
| 13 | +const NumReflectionRays = 5; |
| 14 | + |
13 | 15 | @compute @workgroup_size(WorkgroupSizeX, WorkgroupSizeY)
|
14 | 16 | fn main(@builtin(global_invocation_id) invocation_id : vec3u) {
|
15 |
| - // Calculate the fragment's NDC coordinates for the intersection of the near |
16 |
| - // clip plane and far clip plane |
17 |
| - let uv = vec2f(invocation_id.xy) / vec2f(textureDimensions(framebuffer).xy); |
18 |
| - let ndcXY = (uv - 0.5) * vec2(2, -2); |
19 |
| - |
20 |
| - // Transform the coordinates back into world space |
21 |
| - var near = common_uniforms.inv_mvp * vec4f(ndcXY, 0.0, 1); |
22 |
| - var far = common_uniforms.inv_mvp * vec4f(ndcXY, 1, 1); |
23 |
| - near /= near.w; |
24 |
| - far /= far.w; |
25 |
| - |
26 |
| - // Create a ray that starts at the near clip plane, heading in the fragment's |
27 |
| - // z-direction, and raytrace to find the nearest quad that the ray intersects. |
28 |
| - let ray = Ray(near.xyz, normalize(far.xyz - near.xyz)); |
29 |
| - let hit = raytrace(ray); |
30 |
| - let quad = quads[hit.quad]; |
| 17 | + if (all(invocation_id.xy < textureDimensions(framebuffer))) { |
| 18 | + init_rand(invocation_id); |
| 19 | + |
| 20 | + // Calculate the fragment's NDC coordinates for the intersection of the near |
| 21 | + // clip plane and far clip plane |
| 22 | + let uv = vec2f(invocation_id.xy) / vec2f(textureDimensions(framebuffer).xy); |
| 23 | + let ndcXY = (uv - 0.5) * vec2(2, -2); |
| 24 | + |
| 25 | + // Transform the coordinates back into world space |
| 26 | + var near = common_uniforms.inv_mvp * vec4f(ndcXY, 0.0, 1); |
| 27 | + var far = common_uniforms.inv_mvp * vec4f(ndcXY, 1, 1); |
| 28 | + near /= near.w; |
| 29 | + far /= far.w; |
| 30 | + |
| 31 | + // Create a ray that starts at the near clip plane, heading in the fragment's |
| 32 | + // z-direction, and raytrace to find the nearest quad that the ray intersects. |
| 33 | + let ray = Ray(near.xyz, normalize(far.xyz - near.xyz)); |
| 34 | + let hit = raytrace(ray); |
| 35 | + |
| 36 | + let hit_color = sample_hit(hit); |
| 37 | + var normal = quads[hit.quad].plane.xyz; |
31 | 38 |
|
| 39 | + // Fire a few rays off the surface to collect some reflections |
| 40 | + let bounce = reflect(ray.dir, normal); |
| 41 | + var reflection : vec3f; |
| 42 | + for (var i = 0; i < NumReflectionRays; i++) { |
| 43 | + let reflection_dir = normalize(bounce + rand_unit_sphere()*0.1); |
| 44 | + let reflection_ray = Ray(hit.pos + bounce * 1e-5, reflection_dir); |
| 45 | + let reflection_hit = raytrace(reflection_ray); |
| 46 | + reflection += sample_hit(reflection_hit); |
| 47 | + } |
| 48 | + let color = mix(reflection / NumReflectionRays, hit_color, 0.95); |
| 49 | + |
| 50 | + textureStore(framebuffer, invocation_id.xy, vec4(color, 1)); |
| 51 | + } |
| 52 | +} |
| 53 | + |
| 54 | + |
| 55 | +// Returns the sampled hit quad's lightmap at 'hit.uv', and adds the quad's |
| 56 | +// emissive value. |
| 57 | +fn sample_hit(hit : HitInfo) -> vec3f { |
| 58 | + let quad = quads[hit.quad]; |
32 | 59 | // Sample the quad's lightmap, and add emissive.
|
33 |
| - let color = textureSampleLevel(lightmap, smpl, hit.uv, hit.quad, 0).rgb + |
34 |
| - quad.emissive * quad.color; |
35 |
| - textureStore(framebuffer, invocation_id.xy, vec4(color, 1)); |
| 60 | + return textureSampleLevel(lightmap, smpl, hit.uv, hit.quad, 0).rgb + |
| 61 | + quad.emissive * quad.color; |
36 | 62 | }
|
0 commit comments