-
-
Save LukasKalbertodt/0b809d501ee0262c361616a85dec2846 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Project the triangle's vertices from light space to our disk space. The grid we rasterize | |
// to lives between x/y 0 to 1. | |
let vl0 = v0l - pl; | |
let vl1 = v1l - pl; | |
let vl2 = v2l - pl; | |
var v0 = vl0.xy / (pc.angular_radius.sin * vl0.z); | |
var v1 = vl1.xy / (pc.angular_radius.sin * vl1.z); | |
var v2 = vl2.xy / (pc.angular_radius.sin * vl2.z); | |
v0 = (rotmat * v0 + 1.0) * 0.5; | |
v1 = (rotmat * v1 + 1.0) * 0.5; | |
v2 = (rotmat * v2 + 1.0) * 0.5; | |
// Determine line equation for each edge of the triangle. `s` is the slope of the edge, | |
// but run over rise instead of the typical rise over run. `b` is the base, i.e. the x value | |
// for y = 0. Further down, after multiplying by 16, we want to round this value towards the | |
// nearest integer. To make that easier, we already add 0.5 * (1 / 16) now. Finally, | |
// `xor_mask` determines whether the inside of the triangle is on the left or right of the | |
// edge. It's either 0 or all 1s. | |
// | |
// Note that special vertical edge case (v0.y == v1.y) is not handled here. It probably | |
// should, but I haven't found any artifacts resulting from this and since speed is | |
// important here, I didn't handle the special case. | |
let s0 = (v0.x - v1.x) / (v0.y - v1.y); | |
let b0 = v0.x - v0.y * s0 + (1.0 / 32.0); | |
let xor_mask0 = u32(-(i32((v1.y < v0.y) != (vl0.z < 0.0) != (vl1.z < 0.0)))); | |
let s1 = (v1.x - v2.x) / (v1.y - v2.y); | |
let b1 = v1.x - v1.y * s1 + (1.0 / 32.0); | |
let xor_mask1 = u32(-(i32((v2.y < v1.y) != (vl2.z < 0.0) != (vl1.z < 0.0)))); | |
let s2 = (v2.x - v0.x) / (v2.y - v0.y); | |
let b2 = v2.x - v2.y * s2 + (1.0 / 32.0); | |
let xor_mask2 = u32(-(i32((v0.y < v2.y) != (vl0.z < 0.0) != (vl2.z < 0.0)))); | |
// Two grid lines (one `u32`) are handled at the same time. | |
for (var dl = 0u; dl < 8u; dl += 1u) { | |
// The y value for the two grid lines. | |
let upper_y = (1.0 / 32.0) + (f32(2u * dl) * (1.0 / 16.0)); | |
let lower_y = (1.0 / 32.0) + (f32(2u * dl + 1u) * (1.0 / 16.0)); | |
// Determine a value for each edge separately, that is 0 bits for the triangle's inside, | |
// and 1s outside. The `b0 + y * s0` part calculates the x coordinate for where the edge | |
// intersects the grid line. We use that to shift 16 1s to the right, meaning that | |
// left of the edge are all 0s and right of it are all 1s. Finally, we use the xor_mask | |
// to flip this in case the triangles insides are right of the edge instead. | |
// | |
// This is of course also done for both grid lines, with the one grid line using the | |
// upper 16 bits of an u32, and the other using the lower 16 bits. | |
let upper0 = xor_mask0 ^ (0xFFFF0000u >> u32(saturate(b0 + upper_y * s0) * 16.0)); | |
let lower0 = xor_mask0 ^ (0xFFFFu >> u32(saturate(b0 + lower_y * s0) * 16.0)); | |
let upper1 = xor_mask1 ^ (0xFFFF0000u >> u32(saturate(b1 + upper_y * s1) * 16.0)); | |
let lower1 = xor_mask1 ^ (0xFFFFu >> u32(saturate(b1 + lower_y * s1) * 16.0)); | |
let upper2 = xor_mask2 ^ (0xFFFF0000u >> u32(saturate(b2 + upper_y * s2) * 16.0)); | |
let lower2 = xor_mask2 ^ (0xFFFFu >> u32(saturate(b2 + lower_y * s2) * 16.0)); | |
// For each grid line, bitwise-or together all edge values which results in 0s only | |
// inside of the triangle, and 1s outside. Another bitwise-or with a constant to avoid | |
// polluting the other grid line's bits. The result is then bitwise-and'ed onto the | |
// existing grid, meaning that we potentially clear more bits if this triangle occluded | |
// previously non-occluded grid pixels. | |
grid[dl] &= ((upper0 | upper1 | upper2) | 0xFFFFu) & (lower0 | lower1 | lower2 | 0xFFFF0000u); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment