三角形分成 上线两个,以中间高度的点为准,横切一刀.然后横着向上,或者向下进行一条一条画线填充
为了更加清晰显示 填充过程,我把上半三角形的条纹每间隔2 像素画一条横线,
void fillTriangle(ImVec2 t0, ImVec2 t1, ImVec2 t2, TGAImage& image, TGAColor color)
{
//根据 点的y坐标 从上到下排序
if (t0.y < t1.y)
{
std::swap(t0, t1);
}
if (t0.y < t2.y)
{
std::swap(t0, t2);
}
if (t1.y < t2.y)
{
std::swap(t1, t2);
}
if (t1.y == t2.y)
{
fillUpTriangle(t0, t1, t2, image, color);
}
else if (t1.y == t0.y)
{
fillDownTriangle(t2, t1, t0, image, color);
}
else
{
//直线表达 两点式
ImVec2 t4;
t4.y = t1.y;
t4.x = (t0.x - t2.x) / (t0.y - t2.y) * (t4.y - t2.y) + t2.x;
fillUpTriangle(t0, t1, t4, image, color);
fillDownTriangle(t2, t1, t4, image, color);
line(t1, t4, image, white);
}
}
void fillUpTriangle(ImVec2 t0, ImVec2 t1, ImVec2 t2, TGAImage& image, TGAColor color)
{
for (int i = 0; i < (t0.y - t1.y); i += 3)
{
ImVec2 p1, p2;
p1.y = p2.y = t1.y + i;
p1.x = (t0.x - t1.x) / (t0.y - t1.y) * (p1.y - t1.y) + t1.x;
p2.x = (t0.x - t2.x) / (t0.y - t2.y) * (p2.y - t2.y) + t2.x;
line(p1, p2, image, color);
}
}
void fillDownTriangle(ImVec2 t0, ImVec2 t1, ImVec2 t2, TGAImage& image, TGAColor color)
{
for (int i = 0; i < (t1.y - t0.y); i++)
{
ImVec2 p1, p2;
p1.y = p2.y = t1.y - i;
p1.x = (t0.x - t1.x) / (t0.y - t1.y) * (p1.y - t1.y) + t1.x;
p2.x = (t0.x - t2.x) / (t0.y - t2.y) * (p2.y - t2.y) + t2.x;
line(p1, p2, image, color);
}
}
画图的最基本的代码框架来自于开源库
最基本软渲染的框架https://github.com/ssloy/tinyrenderer