如图,三角形边框会有虚线,明明顶点是相同的,是扫描线的哪里写的有问题吗
void DeviceContext::scanLineFill(const VertexOut& left, const VertexOut& right, int yIndex)
{
double dx = right.fragPos.x - left.fragPos.x;
for (double x = left.fragPos.x; x <= right.fragPos.x; x += 1.0)
{
int xIndex = x;
if (xIndex >= 0 && xIndex < m_device->getClientWidth())
{
//插值系数
double lerpFactor = 0;
if (dx != 0)
{
lerpFactor = (x - left.fragPos.x) / dx;
}
//深度测试
//1/z’与x’和y'是线性关系的
double oneOverZ = Lerp(left.oneOverZ, right.oneOverZ, lerpFactor);
if (oneOverZ >= m_device->getZ(xIndex, yIndex))
{
m_device->setZ(xIndex, yIndex, oneOverZ);
//透视矫正
double w = 1.0 / oneOverZ;
VertexOut out = Lerp(left, right, lerpFactor);
out.fragPos = out.fragPos * w;
out.fragPos.y = yIndex;
out.tex.x *= w;
out.tex.y *= w;
out.normal.x *= w;
out.normal.y *= w;
out.normal.z *= w;
out.color.x *= w;
out.color.y *= w;
out.color.z *= w;
//画像素点颜色
//m_device->DrawPixel(xIndex, yIndex, m_shader->pixelShader(out));
m_device->DrawPixel(xIndex, yIndex, Vec4(0.0,1.0,0.0));
}
}
}
}
void DeviceContext::drawTriangleTop(const VertexOut& v1, const VertexOut& v2, const VertexOut& v3)
{
double slope1 = (v3.fragPos.x - v1.fragPos.x) / (v3.fragPos.y - v1.fragPos.y);
double slope2 = (v3.fragPos.x - v2.fragPos.x) / (v3.fragPos.y - v2.fragPos.y);
double curx1 = v1.fragPos.x;
double curx2 = v2.fragPos.x;
double dy = 0;//每次y增加一个像素
for (double y = v1.fragPos.y; y <= v3.fragPos.y; y += 1)
{
int yIndex = y;
if (y >= 0 && y < m_device->getClientHeight())
{
double t = dy / (v3.fragPos.y - v1.fragPos.y);
//插值生成左右顶点
VertexOut new1 = Lerp(v1, v3, t);
VertexOut new2 = Lerp(v2, v3, t);
new1.fragPos.x = floor(curx1);
new2.fragPos.x = ceil(curx2);
//扫描线填充
if (new1.fragPos.x <= new2.fragPos.x)
{
scanLineFill(new1, new2, yIndex);
}
else
{
scanLineFill(new2, new1, yIndex);
}
}
dy += 1.0;
curx1 += slope1;
curx2 += slope2;
}
}
//画平底三角形 v1为上顶点
void DeviceContext::drawTriangleBottom(const VertexOut& v1, const VertexOut& v2, const VertexOut& v3)
{
double slope1 = (v2.fragPos.x - v1.fragPos.x) / (v2.fragPos.y - v1.fragPos.y);
double slope2 = (v3.fragPos.x - v1.fragPos.x) / (v3.fragPos.y - v1.fragPos.y);
double curx1 = v2.fragPos.x;
double curx2 = v3.fragPos.x;
double dy = 0;//每次y增加一个像素
for (double y = v2.fragPos.y; y > v1.fragPos.y; y -= 1)
{
int yIndex = y;
if (y >= 0 && y < m_device->getClientHeight())
{
double t = dy / (v2.fragPos.y - v1.fragPos.y);
//插值左右顶点
VertexOut new1 = Lerp(v2, v1, t);
VertexOut new2 = Lerp(v3, v1, t);
new1.fragPos.x = floor(curx1);
new2.fragPos.x = ceil(curx2);
//扫描线填充
if (new1.fragPos.x <= new2.fragPos.x)
{
scanLineFill(new1, new2, yIndex);
}
else
{
scanLineFill(new2, new1, yIndex);
}
}
dy += 1.0;
curx1 -= slope1;
curx2 -= slope2;
}
}
void DeviceContext::triangleRasterization(const VertexOut& v1, const VertexOut& v2, const VertexOut& v3)
{
std::vector<VertexOut> vertices{ v1,v2,v3 };
std::sort(vertices.begin(), vertices.end(), [](VertexOut v1, VertexOut v2) { return v1.fragPos.y < v2.fragPos.y; });
VertexOut top = vertices[0];
VertexOut middle = vertices[1];
VertexOut bottom = vertices[2];
if (middle.fragPos.y == bottom.fragPos.y)
{
drawTriangleBottom(top, middle, bottom);
}
else if (top.fragPos.y == middle.fragPos.y)
{
drawTriangleTop(top, middle, bottom);
}
else
{
//插值求中间点
double middleX = top.fragPos.x + (middle.fragPos.y - top.fragPos.y) / (bottom.fragPos.y - top.fragPos.y)*(bottom.fragPos.x - top.fragPos.x);
double dy = middle.fragPos.y - top.fragPos.y;
double t = dy / (bottom.fragPos.y - top.fragPos.y);
VertexOut newMiddle = Lerp(top, bottom, t);
newMiddle.fragPos.x = middleX;
newMiddle.fragPos.y = middle.fragPos.y;
//平顶
drawTriangleTop(middle, newMiddle, bottom);
//平底
drawTriangleBottom(top, middle, newMiddle);
}
}