Well I see that there are definitely still incorrect wobbles.
I think the problem is that I need to adjust the coordinates in the y direction aswel to compensate for the flooring.
But this is more difficult. In the attached image, if I just go backwards using the slopes for the top left point, they end up crossing over and giving me two points. What I want is the texture coordinate at the top left corner of that pixel, but first I need to determine which direction is up in the texture and the rate of change from the corner of the ideal triangle to the corner of the feasible triangle in texture space. Not sure how to do that.
I've never seen rasterizer tutorials talk about these details though so maybe my approach is wrong or I'm missing something else?
Also in the attached picture the red pixel confuses me. I tried manually drawing the squared according to top left rule and right edge - 1 to prevent overlapping.
But for the red pixel it is the right most pixel -1 of the purple triangle and also the left most edge of the green one.
void Rasterizer::textureTriangleFloat(textureTriangle2D & tri)
{
real temp;
real slopeLeft;
real slopeRight;
real ul, vl, ur, vr, zl, zr, u1, v1, u2, v2, z1, z2;
real x1, x2, y1, y2, y3, h;
real currentLocation;
real clip;
//sort top to bottom
//y is 0 at top of screen
if (tri.y1 > tri.y3)
{
SWAP(tri.z1, tri.z3, temp);
SWAP(tri.y1, tri.y3, temp);
SWAP(tri.x1, tri.x3, temp);
SWAP(tri.u1, tri.u3, temp);
SWAP(tri.v1, tri.v3, temp);
}
if (tri.y1 > tri.y2)
{
SWAP(tri.z1, tri.z2, temp);
SWAP(tri.y1, tri.y2, temp);
SWAP(tri.x1, tri.x2, temp);
SWAP(tri.u1, tri.u2, temp);
SWAP(tri.v1, tri.v2, temp);
}
if (tri.y2 > tri.y3)
{
SWAP(tri.z2, tri.z3, temp);
SWAP(tri.y2, tri.y3, temp);
SWAP(tri.x2, tri.x3, temp);
SWAP(tri.u2, tri.u3, temp);
SWAP(tri.v2, tri.v3, temp);
}
//height of top and bottom half of triangle
real topHeight = tri.y2 - tri.y1;
real bottomHeight = tri.y3 - tri.y2;
y1 = floor(tri.y1);
y2 = floor(tri.y2);
y3 = floor(tri.y3);
real pixelheight = y3 - y1;
real pixeltop = y2 - y1;
slopeRight = ((floor(tri.x2) - floor(tri.x1))) / pixeltop;
slopeLeft = ((floor(tri.x3) - floor(tri.x1))) / pixelheight;
ul = (((tri.u3 / tri.z3) - (tri.u1 / tri.z1))) / pixelheight;//
vl = (((tri.v3 / tri.z3) - (tri.v1 / tri.z1))) / pixelheight;//
zl = (((1.0f / tri.z3) - (1.0f / tri.z1))) / pixelheight;//
ur = (((tri.u2 / tri.z2) - (tri.u1 / tri.z1))) / pixeltop;//
vr = (((tri.v2 / tri.z2) - (tri.v1 / tri.z1))) / pixeltop;//
zr = (((1.0f / tri.z2) - (1.0f / tri.z1))) / pixeltop;//
//real yfrac = tri.y1-y1 ;
x1 = tri.x1 ;//+ yfrac*ul;
x2 = tri.x1 ;//+ yfrac*ur;
;//
u1 = (tri.u1 / tri.z1) ;// -(ul*yfrac);
v1 = (tri.v1 / tri.z1) ;// -(vl*yfrac);
z1 = (1.0f / tri.z1) ;// -(zl*yfrac);
u2 = (tri.u1 / tri.z1) ;// - (ur*yfrac);
v2 = (tri.v1 / tri.z1) ;// - (vr*yfrac);
z2 = (1.0f / tri.z1) ;// - (zr*yfrac);
real uOffset = 0;
real vOffset = 0;
real uOffset2 = 0;
real vOffset2 = 0;
real zOffset = 0;
real zOffset2 = 0;
currentLocation = (pitch * y1);
h = y2 - y1; //floor(topHeight);
if (h > 0)
{
if (slopeRight > slopeLeft)
{
triangleFloat(x1, slopeLeft, x2, slopeRight, h, currentLocation, u1 + uOffset, u2 + uOffset2, ul, ur, zl, z1 + zOffset, v1 + vOffset, v2 + vOffset2, vl, vr, zr, z2 + zOffset2);
}
else
triangleFloat(x2, slopeRight, x1, slopeLeft, h, currentLocation, u2 + uOffset2, u1 + uOffset, ur, ul, zr, z2 + zOffset2, v2 + vOffset2, v1 + vOffset, vr, vl, zl, z1 + zOffset);
}
bottom half code removed...
}
__forceinline void triangleFloat(real x1, real slopeLeft, real x2, real slopeRight, real height, real currentLocation, real u1, real u2, real ul, real ur, real zl, real z1, real v1, real v2, real vl, real vr, real zr, real z2)
{
int index, endex;
real tu = 0, tv = 0, tz = 0;
real textureIndex = 0;
real uSlope = 0, vSlope = 0, zSlope = 0;
do
{
if (floor(x2 - x1) > 0)
{
uSlope = ((u2 - u1)*textureWidth) / ((x2)-(x1));
vSlope = ((v2 - v1)*textureHeight) / ((x2)-(x1));
zSlope = (z2 - z1) / ((x2) - (x1));
}
real xfrac = x1 - floor(x1);
tv = (v1*textureHeight) -(xfrac*vSlope);
tu = (u1*textureWidth) -(xfrac*uSlope);
tz = z1 -(xfrac*zSlope);
index = currentLocation;
index += floor(x1);
endex = currentLocation+floor(x2);
while (index < endex)
{
real div1 = tu / tz;
real div2 = tv / tz;
int t1, t2;
floorToInt(&t1, div1);
t1 %= textureWidth;
floorToInt(&t2, div2 );
t2 %= textureHeight;
screenBuffer[index] = texture[t1 + textureWidth*t2];
tu += uSlope;
tv += vSlope;
tz += zSlope;
index++;
}
x1 += slopeLeft;
x2 += slopeRight;
u1 += ul;
v1 += vl;
u2 += ur;
v2 += vr;
z1 += zl;
z2 += zr;
currentLocation += pitch;
} while (--height > 0);
}