Skip to content

Instantly share code, notes, and snippets.

@dwilliamson
Created August 22, 2014 13:26
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dwilliamson/cd1e1d531d7172a2ccca to your computer and use it in GitHub Desktop.
Save dwilliamson/cd1e1d531d7172a2ccca to your computer and use it in GitHub Desktop.
Dumb but accurate triangle rasteriser with top-left fill
void RasteriseTriangle3(char* buffer, int width, int height, float2 v0, float2 v1, float2 v2)
{
// Sort vertices along the y-axis, lowest first
if (v1.y < v0.y)
std::swap(v0, v1);
if (v2.y < v1.y)
std::swap(v1, v2);
if (v1.y < v0.y)
std::swap(v0, v1);
// Setup top half gradients
float dxdy1 = (v1.x - v0.x) / (v1.y - v0.y);
float dxdy2 = (v2.x - v0.x) / (v2.y - v0.y);
// Round-up the start/end y for top-left fill convention
int y = (int)ceil(v0.y);
int nb_y_steps = (int)ceil(v1.y) - y;
buffer += (int)y * width;
// Start x with a pre-step based on how much rounding was performed for fill convention
float x1 = v0.x + dxdy1 * (y - v0.y);
float x2 = v0.x + dxdy2 * (y - v0.y);
// Draw the two halves of the triangle
for (int i = 0; i < 2; i++)
{
for (int y_step = 0; y_step < nb_y_steps; y_step++)
{
// Determine which edge is left/right
float l = x1, r = x2;
if (r < l)
std::swap(l, r);
// Round-up the start/end x for top-left fill convention
int left = (int)ceil(l);
int right = (int)ceil(r);
memset(buffer + left, 255, right - left);
// Increment for next line
buffer += width;
x1 += dxdy1;
x2 += dxdy2;
}
// Setup gradient, y-steps and x with pre-step for the final edge
dxdy1 = (v2.x - v1.x) / (v2.y - v1.y);
y = (int)ceil(v1.y);
nb_y_steps = (int)ceil(v2.y) - y;
x1 = v1.x + dxdy1 * (y - v1.y);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment