OpenGL基础48:高度贴图(上)

前置:OpenGL基础47:法线贴图

一、高度贴图

不少模型都会附带以“bump”为名结尾的贴图,这种帖图统称为凹凸贴图,目的是为了体现出物体的凹凸不平,最经典的例子就是法线贴图,这个在上一章有详细提到过

除此之外还有高度贴图、浮雕贴图等,不过这里暂时先只了解高度帖图吧

高度贴图又称视差贴图,用于直接给予纹理显示上的错觉,视差贴图往往都是黑白图,因为理论上只需要知道每个纹理的深度值,因此RGB三个值都是相等的,就如下:

如果对应的像素是黑色的,意味着此纹理的高度为0,也就是默认值,如果一张高度图为全黑那就相当于没有高度图一样,像素点越接近白色,就代表着当前像素点越“凹”,之前渲染的地板看上去有点花,就如下:

对于红色的墙壁,应用了法线贴图但没有应用高度贴图,地面则即没有法线贴图也没有高度贴图,就是模型比较精细

现在同时应用高度贴图后效果如下:

扫描二维码关注公众号,回复: 12476382 查看本文章

可能看不出来太大的差距,因为参数调的比较小,但如果放大的话就可以明显感受到了

两张图左半边的效果就是带了高度贴图的,会显得凹凸感更加明显

二、视差映射

如果说法线贴图是法向量的偏移,那么高度贴图就是纹理坐标的偏移

图中下面黑色的线为实际的纹理,上面弯弯曲曲的红色线为实际的表面,当视线看过去的时候,如果没有任何的计算,那么A点当然就是显示A点的纹理,而有了高度贴图后,就能让其显示B点正下方的纹理,其中A→B这段距离就是需要计算的纹理偏移

一步一步来,首先看需要什么

从图中来看:计算纹理偏移理论上只需要一个观察方向向量,其次为了保证观察向量的z方向正好是纹理的法线方向,那么在计算的时候,将观察向量转入切线空间是必须的,不然整个计算过程可能会异常复杂

转入切线空间后就好办了,此时观察向量的x和y和切线副切线对齐,z与法向量对齐

很可惜的一点是:并不能准确的算出上面的B点,暂时只能用的一种非常简单的手段来做近似,如下图:

首先可以得到 A 点的高度 H(A),其次取观察向量从 A 开始长度为 H(A) 的一段缩放向量,这段缩放向量的x轴偏移和y轴偏移正是所得的纹理偏移,可见它的偏移位置和真实的B点确实有些误差,但是大部分情况下还是很相近的

不过对于部分纹理,当前像素越偏向白色,对应的效果就越“凹”而不是越“凸”,因此实际上的计算也应该是反着来的,当然也可以直接将图片反色,想要实现非常简单:

vec3 newViewDir = transpose(TBN) * viewDir;
float height = texture(material.texture_height1, texCoords).r;    
vec2 p = newViewDir.xy / newViewDir.z * height * 0.3;
texCoords = texCoords - p;

在计算位移差的时候,viewDir.xy除以viewDir.z,是为了保证你朝向这面纹理的夹角越小(相对于正视物体,斜视的角度越大)的时候,能够通过合理调整缩放向量 P 的大小使其纹理偏移越大,不然的话,你越是斜视这个平面,你就会发现视差的效果越不明显

别忘了viewDir是经过标准化的,viewDir.z一定在[0, 1]的范围

而对于后面乘上的0.3,是视差参数,这个值越大则视差效果越明显

三、注意事项

法线贴图通常根据高度贴图生成、因此往往两个一起用能起到更好的效果,当然别忘了计算纹理偏差一定要在计算光照和法向量之前,不然可能会出现明显的错误

除此之外,上面的实现方法在某些情况下会穿帮,后面会对这个进行优化,不过无论怎么进行优化,高度贴图永远都是一个“欺骗”手段,很难做到十分完美,如果仔细从各个角度去看就能发现一些不自然又或者纹理错误,因此大部分情况下高度贴图只会用在墙壁以及地面上,并且会保证玩家很难以各种奇怪的角度去“看”它们

猜你喜欢

转载自blog.csdn.net/Jaihk662/article/details/108147539