|
20 | 20 |
|
21 | 21 | /// Compute shader for rasterizing small clusters into a visibility buffer.
|
22 | 22 |
|
23 |
| -// TODO: Subpixel precision and top-left rule |
| 23 | +// TODO: Fixed-point math and top-left rule |
24 | 24 |
|
25 | 25 | var<workgroup> viewport_vertices: array<vec3f, 255>;
|
26 | 26 |
|
@@ -79,98 +79,99 @@ fn rasterize_cluster(
|
79 | 79 | let vertex_2 = viewport_vertices[vertex_ids[0]];
|
80 | 80 | let packed_ids = (cluster_id << 7u) | triangle_id;
|
81 | 81 |
|
82 |
| - // Compute triangle bounding box |
83 |
| - let min_x = u32(min3(vertex_0.x, vertex_1.x, vertex_2.x)); |
84 |
| - let min_y = u32(min3(vertex_0.y, vertex_1.y, vertex_2.y)); |
85 |
| - var max_x = u32(ceil(max3(vertex_0.x, vertex_1.x, vertex_2.x))); |
86 |
| - var max_y = u32(ceil(max3(vertex_0.y, vertex_1.y, vertex_2.y))); |
87 |
| - max_x = min(max_x, u32(view.viewport.z) - 1u); |
88 |
| - max_y = min(max_y, u32(view.viewport.w) - 1u); |
89 |
| - if any(vec2(min_x, min_y) > vec2(max_x, max_y)) { return; } |
| 82 | + // Backface culling |
| 83 | + let triangle_double_area = edge_function(vertex_0.xy, vertex_1.xy, vertex_2.xy); |
| 84 | + if triangle_double_area <= 0.0 { return; } |
90 | 85 |
|
91 | 86 | // Setup triangle gradients
|
92 | 87 | let w_x = vec3(vertex_1.y - vertex_2.y, vertex_2.y - vertex_0.y, vertex_0.y - vertex_1.y);
|
93 | 88 | let w_y = vec3(vertex_2.x - vertex_1.x, vertex_0.x - vertex_2.x, vertex_1.x - vertex_0.x);
|
94 |
| - let triangle_double_area = edge_function(vertex_0.xy, vertex_1.xy, vertex_2.xy); // TODO: Reuse earlier calculations and take advantage of summing to 1 |
95 | 89 | let vertices_z = vec3(vertex_0.z, vertex_1.z, vertex_2.z) / triangle_double_area;
|
96 | 90 | let z_x = dot(vertices_z, w_x);
|
97 | 91 | let z_y = dot(vertices_z, w_y);
|
98 | 92 |
|
| 93 | + // Compute triangle bounding box |
| 94 | + var min_x = floor(min3(vertex_0.x, vertex_1.x, vertex_2.x)); |
| 95 | + var min_y = floor(min3(vertex_0.y, vertex_1.y, vertex_2.y)); |
| 96 | + var max_x = ceil(max3(vertex_0.x, vertex_1.x, vertex_2.x)); |
| 97 | + var max_y = ceil(max3(vertex_0.y, vertex_1.y, vertex_2.y)); |
| 98 | + min_x = max(min_x, 0.0); |
| 99 | + min_y = max(min_y, 0.0); |
| 100 | + max_x = min(max_x, view.viewport.z - 1.0); |
| 101 | + max_y = min(max_y, view.viewport.w - 1.0); |
| 102 | + |
99 | 103 | // Setup initial triangle equations
|
100 |
| - let starting_pixel = vec2(f32(min_x), f32(min_y)) + 0.5; |
| 104 | + let starting_pixel = vec2(min_x, min_y) + 0.5; |
101 | 105 | var w_row = vec3(
|
102 |
| - // TODO: Reuse earlier calculations and take advantage of summing to 1 |
103 | 106 | edge_function(vertex_1.xy, vertex_2.xy, starting_pixel),
|
104 | 107 | edge_function(vertex_2.xy, vertex_0.xy, starting_pixel),
|
105 | 108 | edge_function(vertex_0.xy, vertex_1.xy, starting_pixel),
|
106 | 109 | );
|
107 | 110 | var z_row = dot(vertices_z, w_row);
|
108 |
| - let view_width = u32(view.viewport.z); |
109 |
| - var frag_coord_1d_row = min_y * view_width; |
110 | 111 |
|
111 | 112 | // Rasterize triangle
|
112 |
| - if subgroupAny(max_x - min_x > 4u) { |
| 113 | + if subgroupAny(max_x - min_x > 4.0) { |
113 | 114 | // Scanline setup
|
114 | 115 | let edge_012 = -w_x;
|
115 | 116 | let open_edge = edge_012 < vec3(0.0);
|
116 | 117 | let inverse_edge_012 = select(1.0 / edge_012, vec3(1e8), edge_012 == vec3(0.0));
|
117 |
| - let max_x_diff = vec3<f32>(max_x - min_x); |
118 |
| - for (var y = min_y; y <= max_y; y++) { |
| 118 | + let max_x_diff = vec3(max_x - min_x); |
| 119 | + for (var y = min_y; y <= max_y; y += 1.0) { |
119 | 120 | // Calculate start and end X interval for pixels in this row within the triangle
|
120 | 121 | let cross_x = w_row * inverse_edge_012;
|
121 | 122 | let min_x2 = select(vec3(0.0), cross_x, open_edge);
|
122 | 123 | let max_x2 = select(cross_x, max_x_diff, open_edge);
|
123 |
| - var x0 = u32(ceil(max3(min_x2[0], min_x2[1], min_x2[2]))); |
124 |
| - var x1 = u32(min3(max_x2[0], max_x2[1], max_x2[2])); |
| 124 | + var x0 = ceil(max3(min_x2[0], min_x2[1], min_x2[2])); |
| 125 | + var x1 = min3(max_x2[0], max_x2[1], max_x2[2]); |
125 | 126 |
|
126 |
| - var w = w_row + w_x * f32(x0); |
127 |
| - var z = z_row + z_x * f32(x0); |
| 127 | + var w = w_row + w_x * x0; |
| 128 | + var z = z_row + z_x * x0; |
128 | 129 | x0 += min_x;
|
129 | 130 | x1 += min_x;
|
130 | 131 |
|
131 | 132 | // Iterate scanline X interval
|
132 |
| - for (var x = x0; x <= x1; x++) { |
| 133 | + for (var x = x0; x <= x1; x += 1.0) { |
133 | 134 | // Check if point at pixel is within triangle (TODO: this shouldn't be needed, but there's bugs without it)
|
134 | 135 | if min3(w[0], w[1], w[2]) >= 0.0 {
|
135 |
| - write_visibility_buffer_pixel(frag_coord_1d_row + x, z, packed_ids); |
| 136 | + write_visibility_buffer_pixel(x, y, z, packed_ids); |
136 | 137 | }
|
137 | 138 |
|
138 |
| - // Increment edge functions along the X-axis |
| 139 | + // Increment triangle equations along the X-axis |
139 | 140 | w += w_x;
|
140 | 141 | z += z_x;
|
141 | 142 | }
|
142 | 143 |
|
143 |
| - // Increment edge functions along the Y-axis |
| 144 | + // Increment triangle equations along the Y-axis |
144 | 145 | w_row += w_y;
|
145 | 146 | z_row += z_y;
|
146 |
| - frag_coord_1d_row += view_width; |
147 | 147 | }
|
148 | 148 | } else {
|
149 | 149 | // Iterate over every pixel in the triangle's bounding box
|
150 |
| - for (var y = min_y; y <= max_y; y++) { |
| 150 | + for (var y = min_y; y <= max_y; y += 1.0) { |
151 | 151 | var w = w_row;
|
152 | 152 | var z = z_row;
|
153 | 153 |
|
154 |
| - for (var x = min_x; x <= max_x; x++) { |
| 154 | + for (var x = min_x; x <= max_x; x += 1.0) { |
155 | 155 | // Check if point at pixel is within triangle
|
156 | 156 | if min3(w[0], w[1], w[2]) >= 0.0 {
|
157 |
| - write_visibility_buffer_pixel(frag_coord_1d_row + x, z, packed_ids); |
| 157 | + write_visibility_buffer_pixel(x, y, z, packed_ids); |
158 | 158 | }
|
159 | 159 |
|
160 |
| - // Increment edge functions along the X-axis |
| 160 | + // Increment triangle equations along the X-axis |
161 | 161 | w += w_x;
|
162 | 162 | z += z_x;
|
163 | 163 | }
|
164 | 164 |
|
165 |
| - // Increment edge functions along the Y-axis |
| 165 | + // Increment triangle equations along the Y-axis |
166 | 166 | w_row += w_y;
|
167 | 167 | z_row += z_y;
|
168 |
| - frag_coord_1d_row += view_width; |
169 | 168 | }
|
170 | 169 | }
|
171 | 170 | }
|
172 | 171 |
|
173 |
| -fn write_visibility_buffer_pixel(frag_coord_1d: u32, z: f32, packed_ids: u32) { |
| 172 | +fn write_visibility_buffer_pixel(x: f32, y: f32, z: f32, packed_ids: u32) { |
| 173 | + let frag_coord_1d = u32(y * view.viewport.z + x); |
| 174 | + |
174 | 175 | #ifdef MESHLET_VISIBILITY_BUFFER_RASTER_PASS_OUTPUT
|
175 | 176 | let depth = bitcast<u32>(z);
|
176 | 177 | let visibility = (u64(depth) << 32u) | u64(packed_ids);
|
|
0 commit comments