Recently, I am writing a simple software rasterizer for self-studying and fun. But the texture mapping has problems. The texture I want to map is below:
But the final image of two triangles is problematic, it shows below:
The triangle rasterizing algorithm I use is the Triangle barycentric coordinates interpolation. It seems the mapping of second triangle is not correct. My code is below, As the code shows, the three vertices of the triangle is, p1, p2, p3.
I hope someone can help me to fix the problem. Thanks very much!
if (mRenderState & (RENDERING_TEXTURE | RENDERING_COLOR))
{
int x0 = p1.x();
int x1 = p2.x();
int x2 = p3.x();
int y0 = p1.y();
int y1 = p2.y();
int y2 = p3.y();
//Firstly build the bounding box
int xMin = std::min(x0, std::min(x1, x2));
int xMax = std::max(x0, std::max(x1, x2));
int yMin = std::min(y0, std::min(y1, y2));
int yMax = std::max(y0, std::max(y1, y2));
// Triangle setup.
// Compute the edge equation coefficients.
float edge_a_0 = -(y1 - y0);
float edge_a_1 = -(y2 - y1);
float edge_a_2 = -(y0 - y2);
float edge_b_0 = x1 - x0;
float edge_b_1 = x2 - x1;
float edge_b_2 = x0 - x2;
float edge_c_0 = edge_a_0 * -x0 + edge_b_0 * -y0;
float edge_c_1 = edge_a_1 * -x1 + edge_b_1 * -y1;
float edge_c_2 = edge_a_2 * -x2 + edge_b_2 * -y2;
// Triangle area and inverse area
float area = 0.5f * ((x1 - x0) * (y2 - y0) - (y1 - y0) * (x2 - x0));
float inv2Area = 1.f / (2.f * area);
// Check the triangle is backfacing.
if (area <= 0.)
return;
// Loop over the bounding box of the pixels that the triangle possibly
// covers.
int py;
int px;
for (int py = yMin; py < yMax; ++py)
for (int px = xMin; px < xMax; ++px)
{
float e0 = edge_a_0 * px + edge_b_0 * py + edge_c_0;
float e1 = edge_a_1 * px + edge_b_1 * py + edge_c_1;
float e2 = edge_a_2 * px + edge_b_2 * py + edge_c_2;
//Check the sample is outside the triangle
if (e0 <= 0.f || e1 <= 0.f || e2 <= 0.f)
continue;
float wt0 = e1 * inv2Area;
float wt1 = e2 * inv2Area;
float wt2 = e0 * inv2Area;
// Interpolate z
float z = (wt0 * p1.z() + wt1 * p2.z() + wt2 * p3.z());
float zrhw = 1.0f / z;
if (z < mZBuffer[py*mWidth + px])
{
mZBuffer[py*mWidth + px] = z;
if (mRenderState & RENDERING_COLOR)
{
float r = wt0 * v1->r + wt1 * v2->r + wt2 * v3->r;
float g = wt0 * v1->g + wt1 * v2->g + wt2 * v3->g;
float b = wt0 * v1->b + wt1 * v2->b + wt2 * v3->b;
DrawPixel(px, py, Color(r, g, b));
}
if (mRenderState & RENDERING_TEXTURE)
{
float u = wt0 * v1->u + wt1 * v2->u + wt2 * v3->u;
float v = wt0 * v1->v + wt1 * v2->v + wt2 * v3->v;
unsigned int cc = TextureRead(u, v);
unsigned char r = (cc & (0xff << 16)) >> 16;
unsigned char g = (cc & (0xff << 8 )) >> 8;
unsigned char b = cc & (0xff);
Color color;
color.setColor(r, g, b);
DrawPixel(px, py, color);
}
}
}
}