Not sure what I'm doing then, I've been having a look at fixed point and found I need 8 bit fraction for the edge interpolation and just getting away with 10 bits for u and v
The "4 bits" are just to convert the floating-point 2d screen coordinates of each vertex to an integer format with a reasonable fractional part (of course you can use as much precision as you like but you won't need more to perform sub-pixel correction with sufficient precision).
The actual interpolation along y and across the scanline requires higher precision of course.
This isn't to reduce overdraw, if only a small part of a triangle passes in the z pass then the bounding box surrounds the part that passed so that when the textured tri is drawn most of the hidden part of the tri isn't scanned, if a tri in the scene is 50 pixels high but only the top 10 rows of pixels are visible then only the top 10 rows are scanned.
Yes, I already figured that out.
With the inital z-pass each pixel is guaranteed to be drawn only once in the second pass.
So there's basically no overdraw but a bit of overhead for the z-pass.
But without the z-pass and a rough front-to-back ordering you'll skip most pixels in the z-test anyway (except of some pixels where the pre-ordering just didn't make it).
So I was wondering how many pixels you actually save in the second pass by doing an initial z-pass.
I guess you can't really figure out if a polygon is completely invisible as you might draw polygons later which obscure parts of polygons which were already drawn.
I was thinking I could either use the value from the buffer or an interpolated value but using an interpolated value would mean I don't need the z buffer in the cache while doing the texturing.
Oh, of course, z is already in the buffer...
I did a post-processing fogging-pass using the z-buffer
here.
That wasn't particularly much faster but saved me a few bytes of file-size as I didn't had to implement a separate polyfiller to do texture+fog.
I'm mipmapping on a triangle basis, there's a bit of popping but it's ok
That doesn't work well with a large ground plane for example.
That's why they use it as the
typical showcase for mipmaps

I've not quite got the idea of span buffers yet, do you know any decent links explaining it?
Unfortunately not, there are some articles on the net but none of them shows the gory details.
For every scanline of your screen you have a list of "spans" (which is just one scanline of your polygon).
Each span stores all the attributes which are required to draw and clip it:
struct Span {
int startX;
int EndX;
int u;
int v;
int z;
int polyId;
};The "polyId" references another list with attributes which are constant for the whole polygon so you don't have to store it for each span (like deltaU/V/Z, texture, etc).
When rasterizing your polygon you create a span for each scanline and insert it into the according list.
When inserting the span you have to check several cases:
- an existing span (or a set of continous spans) is completely in front of it.
So you can simply discard the current span
- an existing span is completely behind it.
So you can discard the existing span
- the current span intersects an existing span.
So you have to clip the two against each other (and check the rest of your span against the following spans)
- the current span is in front but somewhere in the middle of an existing span
So you split the existing span into two parts and insert the current span in between
To make the testing a bit easier I initially inserted two dummy span into each scanline with (startX=0, z=FarClippingDistance) and (startX=ScreenWidth, z=FarClippingDistance)
This way you have no empty parts in a scanline and the end of one span is always the start of the next (so you don't need "endX").
To have quick access to an arbitrary position of the span-list you should organize it as a (self balancing) binary search tree (otherwise you always have to search your list from the beginning until "startX" is reached).
When rastering your polygon top-to-bottom you're always inserting one new span into a different span-list.
This is a bad idea as the data in each list will be scatter all over the memory. So you should pre-allocate continuous span-data for each list in advance.
Once your span-buffer is build up you can draw each scanline left to right.