【bumpmap之谜】

今天纪念一下我已经将《cg教程》啃到第八章。


首先我觉得诸位玩3d的程序牛们对法线贴图这个东西肯定是不陌生的。我再上3D的时候,也对它感觉挺亲切的:聪明的程序员前辈们怎么会想到用rgb三个量来存储三维向量的xyz呢~


然而这个东西并不像我想的这么亲切可人,它还是有很多概念性的东西,值得去研究的。本文是cg教程第八章凹凸贴图的入门介绍篇,也就是,你只有了解了本文内容,上cg教程第八章才会感觉不这么的云里雾里。


首先先介绍几个非常基础得概念:什么叫图。图这个东西,跟数据结构里边的图不一样,再这里,可以把图理解成一种类似二维数组的东西;大家也不要认为图只能存储颜色,此处的图并不单单指的是“图画”的图,当然,存储了颜色rgb值的图,就是我们所看见的像素图啦。


1.heightmap高度贴图。高度贴图这个东西里只存了高度信息,比如一张10像素x10像素的高度贴图吧,那么(0,0)号”像素格子“里存的是(0,0)号像素的高度值。同理,(0,1)和(1,0)这两个各自里,也存的是对应像素坐标的高度值。

2.normalmap法线贴图。法线贴图如上文所说,它的每一个“像素格子”里边存的是该像素的(注意这里的法线是基于像素的!!不是基于顶点的!!!)法线信息。


看到了法线贴图的描述,你是不是会迷惑,卧槽,一个像素怎么会有法线?另外,你介绍高度贴图有个蛋用啊?!


稍安勿躁,这两个疑问,是可以穿起来的,弄明白即可恍然大悟——首先这个法线贴图里边的数据是怎么来的?答曰:是从高度贴图里来的。比如normalmap中法线贴图中(0,0)的数据是用heightmap中(0,1)<上>,(1,0)<右>计算得到的:比如(0,0)位置的高度贴图的数据(下文简称高度)为5,(0,1)为6,(1,0)为8,咱给这仨点起个名字吧,(0,0)点叫O,(1,0)点叫A,(0,1)点叫B,那么向量AO就是 (1,0,3),向量BO就是(0,1,1)。记住哦,是计算法线的这个格子的上方一个格子和右侧一个格子,来参与计算的~

这算出来的AO,BO不是白算的,cross(AO,BO)可以得到一条垂直于AO,BO的线,而一般情况下,AO,BO也是相互垂直的(- -不信你自己看看去,所谓的特殊情况在于研究顶点法线时候,会出现不垂直,顶点法线是公共面的法线加权计算得到的——草,开始我一直纠结:顶点一般是压根不可导的,怎会有偏导存在,没有偏导存在哪有切面存在,没有切面存在哪有法线存在啊!!!其实人家是加权得到的。。别纠结了)于是构成了三垂直。


三垂直是啥?是坐标系啊!对不对!有木有!!,这个坐标系可以确定一个空间啊!对不对~~~~


这个空间,就是传说中的tan空间。而tan空间的三个坐标轴(就是刚才的三垂直)就是传说中的T(切线)B(副法线)N(法线)!


重新缕一下推到过程啊——咱为了得到一个点的法线信息来把它存入到法线贴图中,要从像素高度图上,取了这点的上边邻点和右边邻点,一作差,做出俩向量对吧,然后一叉乘,得到三垂直的。。。。且慢!!那这个三垂直所确定的原点(也就是这个tan空间的原点)在哪?答曰:当然就是咱们研究的这个点啊!所以呢!!!这个tan空间,是一个非常“迷你”的空间,每个像素,都有自己的一个tan空间!而且这样得到的那个法线,是基于这个tan空间的。


翻译成人话:法线贴图中(0,0)点对应的数值是:(0,0)点的切空间中的法线的三维数值!同理,(8,3)点也有它自己的tan空间,(9,5)也有.....每个像素,都有~


你可能已经预感到要大祸临头了,的确,这不是什么好事情,存储在法线贴图中的法线向量,不是我们在物体坐标空间能直接使用的!其中需要通过相当的矩阵变换才能使用。既然使用了这个法线贴图,我们把所有像素的法线信息都存了进去,那么说我们处理每个像素的时候,都要算一遍矩阵!!!卧槽!!


(ps:此时,法线的用途是在blinphong或者phong的漫反射和镜反射中使用,也就是在fs中,每个像素都要用。)


这是个残酷的现实,必须接受。要么你就别用啦。另外还有一个问题,你已经心甘情愿去用矩阵了,用一个什么样的矩阵呢?答曰:当然是传说中的tbn矩阵的逆矩阵。

这个tbn矩阵是怎么来的呢。其实是由三个向量无脑拼接而成,是否记得刚才所说的的T(切线向量),B(副法线向量),N(法线向量)?把它们仨拼成一个矩阵,就是传说中的tbn矩阵了。

这时候你会发现一个新问题:我手上只有一张蓝紫图,我只能通过它的texcoord读到一个N信息,这个N信息还是基于tan空间的。这时候我应该怎么办呢,我遇见的问题就是:我手里只有一个向量,我是没法确定另两个正交向量的 ,因为他们有无穷多种组合啊!

且慢,你是否听说过这种说法:”模型的顶点中包含了该顶点的法线,切线等信息“?哈哈,正是如此,在顶点中我们可以得到切线信息,这也是现在主流3d软件所支持的呗。顶点中可以传入切线信息,我们怎么把它搞到fs中呢?当然是用光栅插值啦!

说了这么多不人不鬼的话,总结其实就以下几点:

1.normalmap(蓝紫图)中存在的是逐像素的,tan空间中的,法线信息。这个法线是精确的。

2.为了构造那个正交矩阵tbn,我们必须知道t或者b中的一个,这是蓝紫图没法告诉我们的,我们是从光栅器中得到的,插值后的,粗略的,T(切线)信息(因为只有顶点有切线,当然如果你发明一个切线贴图,让每个像素都有切线,那算你牛逼啦)。

3.用数学方法(正交化两个向量),或者求两次正交(cross(N,T)得到一个B',然后再cross(N,B')得到一个T‘,以T’,B‘,N作为正交三巨头构造正交矩阵tbn)撸直那个不精确的T(因为它是插值得来)。

4.crossN和T后得到B,至此,三巨头汇聚一堂,tbn矩阵诞生。


首先,TBN矩阵存在的价值就是:TBN矩阵 * tan空间中的法线 = obj空间中的法线。所以  tan 空间中的法线 = obj空间中的法线 * TBN矩阵的逆矩阵。你再phong的时候是没有办法用一个tan空间的向量去dot一个obj空间的向量的,所以要么俩人都是obj,要么俩人都是tan,前辈牛人的结论是,让俩人都是tan比较好。所以会使用到逆矩阵而不是直接把TBN矩阵挨个dot 切空间中的法线数值再去运算。

所以在fs每一步,都要临时组建一个TBN矩阵,才能正常使用法线贴图中的数据。



好了想记录的就这么多,不是教程,本人菜逼一个,希望大神们唾骂指教!!谢谢。。(可能连cg都没看完的人木有资格发帖子呗。。当自己的学习日记了~~)


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值