« 编程的首要原则 | 返回首页 | libstdc++ 卸载问题 »

关于地表贴图

首先,我不是混 3d 圈的人,所以我对圈子里各种地表的渲染方法并不熟悉。今天写这一篇,纯粹是因为前段时间帮负责 3d 模块开发的同事解决了一个算法问题。

从我有限的 3d engine 相关知识来看,我最早了解的是类似 2d tile 拼接的地面渲染方式。玩过星际的地图编辑器的就知道我指的什么。等到魔兽三,虽然 engine 改成 3d 的了,但是方法没有大的变化。就是用贴图做成图素去拼接起来。依稀记得无冬之夜也是这种方法,时间太久,不敢确认。

后来,我看了 big world 的方案,就是在地面高度网格的顶点上记录一个贴图混合系数。最多在一个 chunk (记得似乎是 25 格)里最多可以用四张不同的贴图,然后根据地面网格的顶点混合系数,混出最终的效果。

这个方法比较节省资源,听说很多 3d engine 对地面的渲染都这么干。

不过 big world 默认的地面网格,每个格子单位长为 4 米。结果地面的过度就显得非常粗糙了。这点,天下2 的场景美术私下跟我抱怨过。说是不能做出 wow 里的效果。到了创世西游,应美术的强烈要求,单位格被改成了 2 米,很大程度是为了让地表渲染的更漂亮。当然数据量也增加了 4 倍。

如果想近一步增加地表贴图的精细度该怎么办?简单的增加地表格的精度是不合适的。其实高度图不需要太高的精度就可以做的很漂亮。增加的数据量却是很惊人的。

我们的 3d 程序员提出一个方法。其实,贴图的精度可以高于网格的精度。

当然,在渲染时,就不能按以前的方式。我们可以把混合信息保存在独立贴图里,而不是存放在顶点上。

例如,如果一个 chunk 有 32x32 格,如果你用一张 32x32 的贴图,4444 有 4 个通道即可,可以描述出 5 张贴图的混合信息(由于混合系数之和为 1 ,所有第 5 层可以通过前四层计算出来)。效果和保存在顶点上一致,但会多消耗一张贴图。

假设我们采用 64x64 的贴图,贴图混合精度就增加了 4 倍,最高支持到 256x256 甚至 1024 都可以。不过太高的精度混合贴图本身也有很大消耗,可能还不如直接把整张混合结果保存下来。

理论上,我们可以让美术制作的时候,仅在最被玩家关注的地方使用高精度混合贴图,不太关注,尤其是远景,使用 2x2 甚至 1x1 贴图即可。

但是,制作期,编辑工具如何决定该生成怎样精度的混合信息?

这里面有一个 chunk 间接缝的问题。如果一个 chunk 的混合精度较高,衔接的一个 chunk 比较低,缝隙就有可能被看出来。

另外,程序上虽然可以生成不同级别的混合信息,但到底实际该用哪一份也是一个问题。尤其在编辑器中,美术会自由修改。且不应该让美术关系精度问题。


早期我们的编辑器在这个方面做的不太好。前几天,我花了点时间思考这个问题,发现了一个简单可行的方案。

首先,在原来的编辑器中,太多的精度级别是没有意义的。这跟地图刷的定义有关。地图刷虽然有大有小,但无论大小,都是一个中心向四周过度的图案。而且在编辑器中,混合信息是按浮点数保存。

其结果是,如果期望完全无缝,那么最终的混合精度只会留下两类:一是所支持的最高精度。另外就是最低精度(就是纯色)。

那么,如何利用程序支持的多级精度?我的方法是,提供不同粒度(而非大小)的刷子供美术选择。不需要精雕细凿的部分推荐给美术稍微粗粒度的刷子(看起来有更多的马赛克)。

而混合数据,可以以自适应的四叉树方式保存。且直接保存成 4444 的通道形式,而不用浮点数。虽然浮点数有更高精度,但实际渲染结果是用 16 级方式呈现出来。美术是根据视觉反馈来修改场景的。更高的级数没有意义。

这样,四叉树可以用来合并相临的相等混合信息。最终可以根据四叉树的最大深度决定贴图的精度。


btw, 在写四叉树的代码时,发现四叉树的数据序列化非常有趣,可以只用很少的额外信息记录四叉树的形态。(简单的在数据流里插入 bit 表示当前分枝是否需要扩展)

如果用四叉树去表示一个 2 的整数次幂宽度的矩形,也有一个巧妙的方法定位四叉树的叶子。你可以简单的合并需要索引的 x,y 的每个 2 进制位。比如 x 和 y 都是 [0,255] ,表达一个 256 单位长的空间。x 和 y 都是 8bit 。

把 x 和 y 的第 7 bit 合并成一个 2bit 数字,第 6 bit 也合并,依此类推,得到一个 8 个元素的数列。按这个数列去逐级访问四叉树每级上的对应 0~3 象限即可。

这个技巧同样可以用于 8 叉树,由于不需要做任何判断,所以可以提高性能。 :D


这段时间太忙,所以 blog 就只是简单记录下思路了。

Comments

= =我搜索allegro程序库 结果就搜到您博客了 居然看见那关于dos和win95的讨论……想必您必定是骨灰级程序员吧……
不错,不错,味道好极啦.
现在游戏的主流地形都是高度图生成网格,再局部每个tile上上细节纹理即splatting纹理混合,用shader很容易混合起来,混合的权重可以用一张courage图里对应通道的分量来记录,效果还不错,也可以像你说的那样,32*32的tile用64*64的细节纹理,wow估计也是这么做的吧
我们也有相同的问题,但我觉得一个更简单实用的方法是用噪声纹理和权值结合混合。
我实现的Terrain Editor,是通过每层Render一张贴图,并附带一张Alpha贴图来代表这一层的贴图权重,Terrain的最后效果就是Blend每层的贴图得到的。效果还可以。
权重图不就是wow的方法么
莫非是这个 http://xyx.163.com/
从rss中看到这里有个板凳等着我。。
抢占了

Post a comment

非这个主题相关的留言请到:留言本