Scanline based filled Polygons
19 Nov 2013Introduction<
In a previous post I laid down some foundation code to get access to the pixel buffer when in context of a HTML canvas. Good for those who have experience writing graphics code directly against the video buffer - it almost feels like you’re writing to 0xA000 :-)<
Today’s post will focus on drawing polygons to the screen using scan lines.
Scan lines
The whole idea here is that a polygon can be represented on screen as a series of horizontal lines. Take the following picture for example. You can see the red and blue horizontal lines making up the filling of the polygon.
So, to define this all we do is take note of the minimum and maximum x values for every y-axis instance that there is a line on. We run through the array of values drawing horizontal lines at each instance, and then we have a polygon on screen - pretty easy.
Code
First of all, we’ll define our drawing primitive for a horizontal line.
We pass in the two x (x1
and x2
) values for the line to go between, the y
value for the line to sit on. To help with the offset calculation we also pass in the width w
to correctly calculate the pitch. Finally the colour components and buffer to draw to are passed in. Setting this code up in a run loop, you end up with something like this:
Yep, there’s lots of horizontal lines. Referring to our horizontal line diagram above, we still need a way to walk the edges of the polygon so that we can get the minimum and maximum x values to start drawing. Because our basic unit is the pixel (considering we’re rasterising to a pixelated display), we can easily calculate the gradient of the line that we need by:
Taken out of context of maths, this just says to us: we want to walk from x1
to x2
using (y2
- y1
) steps.
From the code above, we treat x1
, y1
as the starting point and x2
, y2
as the ending point. Our for-loop is biased in the positive direction, so it’s important for us to flip the values if they come in inverted. The edges
array that’s passed in is prepared by the caller of this function. It’s initialized with very unreasonable minimum and maximum values. We than run over all 4 polygon edges
At the end of this process, edges
is full of minimum/maximum values ready for drawing. Here’s the code for the polygon.
This really is just putting all the pieces together. The building of the edges array is important - as is using the y co-ordinate (adjusted back to zero by proxy of the minimum y value) as an array index. Once you’ve got this setup in a random position & colour loop, you’ll end up with something like this:
mmmm… Tasty.