透视矫正
加入了透视矫正, 像素的覆盖遵循了左上的原则。
对1/Z进行插值,将结果在除以1/Z得到正确的插值。
//透视矫正纹理
void FillBottomTriangleByTexCorrect(const Triangle &t)
{
Vertex3D bottom, left, right;
if (t.vertex[0].newPos.y == t.vertex[1].newPos.y)
{
bottom = t.vertex[2];
left = t.vertex[0];
right = t.vertex[1];
}
else if (t.vertex[1].newPos.y == t.vertex[2].newPos.y)
{
bottom = t.vertex[0];
left = t.vertex[1];
right = t.vertex[2];
}
else
{
bottom = t.vertex[1];
left = t.vertex[0];
right = t.vertex[2];;
}
if (left.newPos.x > right.newPos.x)
{
Swap(left, right);
}
float leftDxDivDy = (bottom.newPos.x - left.newPos.x) / ((float)bottom.newPos.y - (float)left.newPos.y);
float rightDxDivDy = ((float)right.newPos.x - (float)bottom.newPos.x) / ((float)right.newPos.y - (float)bottom.newPos.y);
float xleft = (float)left.newPos.x;
float xRight = (float)right.newPos.x;
int y = left.newPos.y;
//1/Z
float leftDxDivDyReciprocalZ = ((1 / bottom.newPos.z) - (1 / left.newPos.z)) / (bottom.newPos.y - left.newPos.y);
float rightDxDivDyReciprocalZ = ((1 / right.newPos.z) - (1 / bottom.newPos.z)) / (right.newPos.y - bottom.newPos.y);
float xLeftReciprocalZ = 1 / left.newPos.z;
float xRightReciprocalZ = 1 / right.newPos.z;
//U
float leftDxDivDyColorU = (bottom.uv.x / bottom.newPos.z - left.uv.x / left.newPos.z) / (bottom.newPos.y - left.newPos.y);
float rightDxDivDyColorU = (right.uv.x / right.newPos.z - bottom.uv.x / bottom.newPos.z) / (right.newPos.y - bottom.newPos.y);
float xLeftColorU = left.uv.x / left.newPos.z;
float xRightColorU = right.uv.x / right.newPos.z;
//V
float leftDxDivDyColorV = (bottom.uv.y / bottom.newPos.z - left.uv.y / left.newPos.z) / (bottom.newPos.y - left.newPos.y);
float rightDxDivDyColorV = (right.uv.y / right.newPos.z - bottom.uv.y / bottom.newPos.z) / (right.newPos.y - bottom.newPos.y);
float xLeftColorV = left.uv.y / left.newPos.z;
float xRightColorV = right.uv.y / right.newPos.z;
while (y < bottom.newPos.y)
{
float dxReciprocalZ = (xRightReciprocalZ - xLeftReciprocalZ) / (xRight - xleft);
float reciprocalZ = xLeftReciprocalZ;
float dxColorU = (xRightColorU - xLeftColorU) / (xRight - xleft);
float ColorStarU = xLeftColorU;
float dxColorV = (xRightColorV - xLeftColorV) / (xRight - xleft);
float ColorStarV = xLeftColorV;
for (int i = (int)(xleft); i < (int)(xRight); i++)
{
float u = (ColorStarU / reciprocalZ) * (t.texWidth-1);
float v = (ColorStarV / reciprocalZ) * (t.texHeight-1);
if (u < 0 || v < 0 || u >= t.texWidth || v >= t.texHeight)
{
int haa = 0;
}
UINT color = t.texBuffer[(UINT)u + (UINT)v * (UINT)t.texWidth];
DrawPoint(i, y, color);
ColorStarU += dxColorU;
ColorStarV += dxColorV;
reciprocalZ += dxReciprocalZ;
}
y++;
xleft += leftDxDivDy;
xRight += rightDxDivDy;
xLeftReciprocalZ += leftDxDivDyReciprocalZ;
xRightReciprocalZ += rightDxDivDyReciprocalZ;
xLeftColorU += leftDxDivDyColorU;
xRightColorU += rightDxDivDyColorU;
xLeftColorV += leftDxDivDyColorV;
xRightColorV += rightDxDivDyColorV;
}
}
发现了个新问题,背面剔除貌似有问题。
Github项目地址