上面两点下面一个三角形_[500行代码学懂OpenGL]之三填充三角形

7a471099b4c6c592b5bff5a1a722ddc1.png

填充三角形

线性插值

来复习一下画线,我们知道画线的时候我们做的实际上是这样的事情:对于要画的线AB,在满足我们设定的条件(斜率 ≤ 1, A < B)之后,因为我们要画的是整数的像素点,对于x每增加1,我们算出对应的y,然后来画点(x,y),这样重复直到x增加到B点:

36264dd6b5f3a5194ebf189ad683f065.png

对于 AB 上的任意一点 P 满足:

也可以写成:

这个公式是著名的线性插值,实际上也是我们画线的基础。因为在画线部分核心代码长这样:

for 

对于P点,我们根据增加后的x算出t值,然后算出y,得到应该画的点。

其实在画框架的时候我们已经画过三角形了,就画三条线就OK。现在我们要做的是来填充三角形。

扫描法

若要填充一个三角形,最简单的能想到的办法是对于三角形的每一个y,我们找到对应的左侧和右侧,x_left和x_right,我们画上x_left到x_right的线,那么从三角形最上面的点按y增加扫到最下面的点既可。

为了简单起见,我们先把三角形拆成上下两部分:

a94c32f37dd5481d692fae134aad85a7.png

那么对于一个特定的y,我们想要找到它的左边和右边 A B 两点,思路是这样:

  • 首先排序,保证 t0 ≤ t1 ≤ t2
  • 整个三角形的高度必为 t2.y - t0.y
  • 那么对于上半部分,y每增加1(注意有可能t0 == t1),我们用插值法算出对应的两点A和B

这样就能算出对应的 A 和 B

void 

6ca5a87326cfa85251f973a450fcdd40.png

那么有了 A 和 B 之后,我们在AB之间调用我们的画线函数,再用同样的方法给下半部分填满,问题既解决。

void 

这样三角形填充就解决。代码里有很多重复的部分,然后这里决定让代码短一点,代价是读起来没那么清楚了:

void 

wavefront obj

上一章我们画了框架,这下我们来填上三角形:

dd21fdc4504d0b51a48ddbe9de6760fd.png

好吧,并不是很动人=。=之所以不动人是因为光影光影,我们只有颜色,没有考虑光,

KrisYu/tinyrender​github.com
acd748191b58801453ed9e2702829742.png

compile:

g++ -std=c++11 main.cpp tgaimage.cpp model.cpp -o main

重心坐标法

除了上面提到的扫描法之外,另外一个可以想到的办法是,因为我们终究是画到二维平面上的像素,一个一个的点,那么对于我们要画的区域内的每一个点,我们是否可以检测看它是否在三角形之内,如果是的话,画它,否则不理之。这样的思路是可行的,对于三角形内及其边上的任意一点,我们都可以用重心坐标系来表示:

这个长得也很像线性插值。

运算:

PA是AB和AC的线性组合。

拆一拆:

实际上我们都可以看做是我们在寻找向量 (u, v, 1) 同时垂直于向量

和向量
--就是叉乘。

关于重心坐标系以及代码的更多推理可以读这里:

二圈妹:三角形重心坐标​zhuanlan.zhihu.com
a5568b148a99b34b343ab8c1f01b56b8.png

代码我们这样写:

Vec3f 

我们当然也不用把平面区域的每个点代入P去做检查,我们只需要找到三角形的 bounding_box,然后看其中的每一个整数点,如果在其中,那就画之。

用同样的方法来给模型填色,效果一样。

KrisYu/tinyrender​github.com
acd748191b58801453ed9e2702829742.png

效果跟之前依旧一致,我们给每个三角形随机填上色:

f5f73c9022ca83686bb66a1d2a013476.png

随机填色这个我们看起来倒是有点cool.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值