Some notes:
if x1<x2 then
zz1 = z1
zz2 = z2
_zz1 = _z1
_zz2 = _z2
itx1 = x1
itx2 = x2
Uu1 = u1
Uu2 = u2
Vv1 = v1
Vv2 = v2
sr1 = r1
sr2 = r2
sg1 = g1
sg2 = g2
sb1 = b1
sb2 = b2
else
zz1 = z2
zz2 = z1
_zz1 = _z2
_zz2 = _z1
itx1 = x2
itx2 = x1
Uu1 = u2
Uu2 = u1
Vv1 = v2
Vv2 = v1
sr1 = r2
sr2 = r1
sg1 = g2
sg2 = g1
sb1 = b2
sb2 = b1
end if
better use a vertexstructure and just swap the pointers.
you don't even have to care about this if all polygons are defined in equal orientation and backface-culling is used to remove all polygons not facing the viewer (so the orientation of x1/x2 will never change).
xDiv = 1/(itx2 - itx1)
dR = xDiv * (sr2 - sr1)
dG = xDiv * (sg2 - sg1)
dB = xDiv * (sb2 - sb1)
dZ = xDiv * (zz2 - zz1)
these gradients across your polygon are linear, this means they are the same for every scanline.
just calculate them once for the longest scanline (biggest deltax: highest precision).
this also means you just have to keep track of u,v,z of the left side of your polygon.
if y>=0 and y<yResyou don't have to do this for every pixel of a scanline.
check this before you enter the inner loop.
if i>=0 and i<xRes thendon't do this for every pixel either.
instead just test how many pixels are "out" on the left side and update u,v,z (eg. deltaU*pixelsToSkip).
the pixels on the right can just be skipped.
when you interpolating x along your polygon edges, the starting "x" for each scanline is actually a floating-point value.
you should take this into account and update the starting u,v,z of each scanline by a fraction of your deltas (how much is missing from the actual floating-point "x" to the rounded integer-pixel-position).
this is necessary for "y", too and can incorporate clipping on the x/y-axes for free.
If (FOV - (-Camera.pos.z + CurZ))>0 thenif this is some approach of z-clipping, drop it. it doesn't work.
you must perform z-clipping before doing perspective division.
when z gets near 0 (and even flips sign right afterwards) your 2d-coordinates break.
ValU = U/Cur_Z
ValV = V/Cur_Zthis won't result in useful framerates because division is expensive.
instead calculate 1/z (and respective u,v) every 8 or 16 pixels and interpolate linearly between two pairs of perspective correct u,v. if you manage the latter with integer-precision only, you can get the division for free (fpu and cpu run in parallel), but you'll probably need some assembly here.
You can even interpolate u,v bi-linearly (across scanlines, for eaxmple between 4 points of a 8x8-grid):
on an average you just need to calculate two (depending on deltax) additional u,v on a scanline and can skip perspective divide for the next 7 scanlines.
If you want to look deeper into how certain
division-algorithms work, you can even approximate the next 1/z (since deltaz is usually small) by a single successive iteration and using the previous result as a starting point.
Cb = ((CurTex and 255))*b*0.003921 '' 1/255
Cg = ((CurTex shr 8) and 255)*g*0.003921
Cr = ((CurTex shr 16) and 255)*r*0.003921as jim pointed out already, the float-to-integer conversion is expensive, too (and the precision is not necessary).
keep the interpolated r,g,b as integers with some additional fixed-point-precision (for example multiply all values by 2^16):
Cb = ((CurTex and 255) * (b shr 16) shr 8(but this is essentially what they invented
mmx for)
CurTex = Texture.GFX[int(ValU*Texture.Size.x)+Texture.Size.x*int(ValV*Texture.Size.y)]Same here (interpolate in integers). You can also try to make your textures' width a power of two, so you can replace the multiply by a shift.
use the cross-product equation to determine if the points are clockwise or counter clockwise
Rotating the vertices and doing a cross product calc is cheap [...]
The cross-product of the
rotated vertices of a triangle gives you the
transformed normal-vector of the face.
you can compare it to the view-vector (by a dot-product) to see if it's facing in the same direction.
In camera-space the view-vector is simply (0,0,1) so you just have to look at the sign of the z-component of your (transformed) face-normal (which you can get by just a single dot-product).