重心模型选址代码_[500行代码学懂OpenGL]之四z-buffer

68a3fc52449c37bc8f2ef8bb29971000.png

z-buffer

简单光

我们现在先复习一下,我们经过了画点、画线,填三角形之后已经能画出来一些东西了,现在我们有好几条路可以走,那就是

  • 光(上帝说“要有光”)
  • 纹理(不然就填白色和随机颜色么?)
  • 数学(之前做的所有事情就是简单的把x,y对应的画到图像上来)

这里我们做的事就是简单的给我们的模型一点‘方向光’,注意我这里说了一专有名词‘方向光’,所以还会有别光(暂且不表)。方向光就是类似太阳光一样的,我们只考虑它的方向:

3f9bb9a8e91683db34f92c30cf77bc1e.png

对于一束光,我们到达物体表面的能量实际上是:

ee18202f990b6207401488052f2ca473.png

它的强度 Icosα, α是物体光与物体的法向量的夹角。

如果我们用

表示光的方向,
指向物体光照处'向内的'法向量,那么

这里我们就必须要考虑一些数学问题了,物体我们放在这,然后有光的方向:

f8bada1a6c4e3c822b0c248b3123b36e.png

那么'朝内的'法向量可以这样得到

,然后正交化:

1bfcb688194c2e6e7c9588bc0bd844dd.png

这里我们先做很多简化操作:

  • 光的方向是 Vec3f light(0, 0, -1), 强度就是1
  • 假设每个三角形收到光照的强度相同,都是 Icosα
  • 三角形法向量
  • 当然我们还要知道 cosα 大于0才有意义,我们不可能减去光o(╯□╰)o

核心代码:

Vec3f 

看效果:

3925dbc7c93be614a3fb9bc2f2a676ba.png

妈妈他是凸嘴。我们换一个光的方向。

855d3be2d5fa2fc3301598cd0436a5a2.png

更吓人了。。。。他嘴巴怎么长后面了。。

simplelight​github.com
b1088e51545ada5749a87d9ac2b09e44.png

compile & run:

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

z-buffer

造成这个问题的原因很简单,我们就是一股脑的把三角形画出来了,没有考虑三角形的先后顺序,正如画画一样,我们应该先画远处的东西,如果近处有什么东西把它给覆盖了,我们就不会看到远处的东西,这里我们就是画三角形的时候没有考虑先后顺序。那么这个问题要怎么解决呢?

这里我们先继续回顾一下三角形重心坐标:

这里其实有一个很cool的点,就是我们把P表示成三角形三个顶点的线性组合,再回忆一下线性插值,其实对于P点的任何性质,我们都可以利用类似线性插值,把它变成三个顶点的组合:

所以这里就给了我们提示,对于任意一点P,我们算出它的z值,如果z值更靠近我们,那么我们就用它来替换已经画上的点,否则我们则不更新P点。

同样我们也只用考虑画布上的所有的点的P值,可以用一个二维的数组来表示,不过我们这里偷懒,就用一维的数组,因为画布上的(x,y)点可以写成(x + y *width),可以这样来转换:

int 

同时注意我们在把物体坐标系做映射时,需要保留z值,所以一些计算我们最好就用float.同时我们也需要注意在转换坐标系的时候我们需要注意还是需要把 x 和 y 变成int,否则有些地方会因为浮点数的原因for loop不会覆盖所有的像素,会有黑色部分产生:

Vec3f 

第二个需要注意的点是我们物体的位置和朝向,这里我们把z-buffer初始化为负无穷大,然后如果P.z更大意味更靠近我们。

void 

看结果:

5cee166d6a0698052398bee05de510ef.png
KrisYu/tinyrender​github.com
b1088e51545ada5749a87d9ac2b09e44.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值