没有贴图拉伸的陡峭悬崖

时间:2021-12-27 11:16:11

没有贴图拉伸的陡峭悬崖
有贴图拉伸问题的悬崖

没有贴图拉伸的陡峭悬崖
解决了贴图拉伸问题的悬崖

  如果你玩过一些早期以室外地形为主的3D游戏,比如《起义》,就会发现遇到陡峭山崖的时候地面贴图会被严重拉伸。随着Shader的引入和显卡机能的提高,在近期发行的很多高品质3D游戏中悬崖贴图变得非常精细,不再有拉伸现象了。在FarCry中有一关好像桂林山水那样的风景,陡峭的山崖和深谷中的清澈的河水给人留下了深刻的印象。其实只要一个小小的技巧就可以解决贴图拉伸问题,并且不一定非要Shader支持,只不过没有Shader支持你通常需要3个顶点UV流才能实现这些效果,对于显卡的总线带宽和显存容量要求高了些。下面就结合插图来说说这个小技巧,为了方便我们还是采用2D图片说明问题,只需要稍稍费点脑力就可以想像在3D空间中的效果。

没有贴图拉伸的陡峭悬崖
  
  想像图中AB、BC是一个悬崖的两个侧面,从图中可以看到,将AB向Y轴投影,BC向X轴投影可以获得较大的投影长度(相比将AB向X轴投影,BC向Y轴投影),如果有一张贴图分别沿X和Y轴平铺,则AB向Y轴投影、BC向X轴投影可以分别跨越较大范围的纹理尺度。根据悬崖的走向选择不同的投影坐标轴以获得最大的投影长度,将这个投影值作为悬崖贴图的UV坐标就可以避免采用固定UV带来的贴图拉伸问题。对于三维空间,假设XY平面是水平面,则XZ、YZ是两个垂直平面,根据悬崖的走向选择向XZ或YZ平面投影(原则是获得较大的投影跨度),在这两种情况下分别把投影得到的X、Z或者Y、Z值做为顶点的U、V坐标。通常UV坐标每跨越1.0纹理映射就会跨越整张贴图,所以把投影值直接作为UV坐标在多数情况下显得太大了,通常会再乘上一个比例因子。比如投影得到的跨度是100,在你的世界中代表10米,你希望这样的距离刚好跨过一张贴图,那就需要把投影得到的值乘以0.01。

  传统管道顶点UV可以通过预计算并保存在顶点Buffer中,如果使用可编程管道,则可以把UV计算放在VS中实现,不再需要通过顶点Buffer传入。不管用哪种方式,计算都是简单的点乘。假设沿三个坐标轴的单位向量分别是NX、NY、NZ,缩放因子是S,顶点坐标是P,下面就是悬崖UV的计算方式
  向XZ平面投影的时候:
    u = (P dot NX) * S
    v = (P dot NZ) * S
  向YZ平面投影的时候:
    u = (P dot NY) * S
    v = (P dot NZ) * S
实际计算的时候可以先把单位向量NX、NY、NZ乘以缩放因子S,再和顶点坐标做点乘,这样可以省去乘以缩放因子的开销