视差贴图的展示
图一:注意轮胎印中的自阴影,实际上路面只是一个平地
![](https://images0.cnblogs.com/blog2015/554065/201503/111203422922627.jpg)
图二:孤岛危机的成功,视差贴图功不可没
![](https://images0.cnblogs.com/blog2015/554065/201503/111203533552008.jpg)
![](https://images0.cnblogs.com/blog2015/554065/201503/111203533552008.jpg)
图三:视差贴图同样可用于人物,装备及道具
![](https://images0.cnblogs.com/blog2015/554065/201503/111204038248572.jpg)
本讲分四个部分
一:优点特性
一:优点特性
二:基本原理
三:使用方法
四:视差计算
第一部分 视差贴图的优点及特性
上一讲讲了法线贴图。法线贴图,无论是RGB法线贴图还是DXT5nm,都有一个缺点就是。越接近面的水平视角,则画面越不真实。因为使用法线贴图后,凸起的部分只是看起来凸起而已,网格模型却并没有凸起依然是平的。正常来说凸起的部分会遮挡后面的部分,法线贴图却没有这个效果。于是我们有了法线贴图的改进版 - 视差贴图
视差贴图的好处:
(1)在相对视角会发生变化时,很有立体感
(2)在入视角接近水平时,依然有不错的质量
下面两图对比可以看出,在入视角接近水平时,视差贴图要比法线贴图清晰不少。
注意:在入视角等于或接近垂直时,视差贴图与法线贴图的效果是几乎一样的。
![](https://images0.cnblogs.com/blog2015/554065/201503/111205028394501.png)
![](https://images0.cnblogs.com/blog2015/554065/201503/111205109808622.png)
第二部分 视差贴图的原理
视差贴图,由Tomomichi Kaneko在2001年发明,但是限于计算机的性能,真正的商业运用是从2007年开始的。视差贴图通过uv偏移实现。uv的偏移值由高度及由点指向摄像机的向量计算得出。所以视差贴图依然不改变真正的模型表面构造。
注意:如果使用的是Unity自带的Parallax 类shader,则高度必须位于A通道中(对应color.w),如果高度图是灰度图的话,则需转换至A通道,下面的使用部分有详细方法。有关高度的知识,参阅17讲的前半部分。
左图:凹凸不平的鹅卵石 右图:实际只是一个平面
![](https://images0.cnblogs.com/blog2015/554065/201503/111205282456863.jpg)
![](https://images0.cnblogs.com/blog2015/554065/201503/111205364801013.jpg)
第三部分 视差贴图的使用
(1)准备好贴图,法线贴图,高度图。
(2)如果高度图的高度储存在透明通道,略过此步。如果是灰度图则需:选中图,勾选Alpha from Grayscale,然后Apply即可
![](https://images0.cnblogs.com/blog2015/554065/201503/111205471835350.png)
(3)创建plane及材质,Shader选Parallax Diffuse或者Parallax Diffuse
(4)把三个图拖到材质对应的栏里
(5)调整Height高度。
如果是初次使用视差贴图的话,把Height调到最高,然后旋转plane查看,这样能快速理解视差贴图的好处。
如果是真正运用的话,Height稍微低些,否则会失真。
第四部分 视差贴图的计算
打开Build-in shader里的 Normal-Parallax.Shader,即Parallax Diffuse。有如下代码:
- half h = tex2D (_ParallaxMap, IN.uv_BumpMap).w;
- float2 offset = ParallaxOffset (h, _Parallax, IN.viewDir);
- IN.uv_MainTex += offset;
- IN.uv_BumpMap += offset;
(1)纹理映射 取得 高度值h
(2) 由高度值h及指向摄像机的向量计算偏移offset
(3) 对纹理贴图以及法线贴图进行uv偏移offset
其中第二步是重点。打开UnityCG.cginc , 看到如下代码。
- // Calculates UV offset for parallax bump mapping
- inline float2 ParallaxOffset( half h, half height, half3 viewDir )
- {
- h = h * height - height/2.0;
- float3 v = normalize(viewDir);
- //单位指向相机向量.z +0.42
- v.z += 0.42;
- // 偏移.x = 高度*(单位指向相机向量的x / 单位指向相机向量的z)
- // 偏移.y = 高度*(单位指向相机向量的y / 单位指向相机向量的z)
- return h * (v.xy / v.z);
- }
计算方法出来了。具体算法的理论依据感兴趣的同学可以自己去研究。
部分内容出自: