我的世界如何制作错觉?
介绍两个概念,视差(Perspective)与深度(Z-Buffering) 视差好理解,你正前方一块玻璃,一个手电筒照着,你就有了“面前有块玻璃”和“手电筒在远处以太阳光为背景在闪烁“的视差;而深度则是游戏世界里物体离你的远近,以屏幕为中心,越远的地方其深度越大(当然实际中并不是这样的,这里只是为了解释方便) 现在来说说怎么让一个平面看上去像立体一样 有两种方法,一种是在平面上贴上纹理,然后打光,按照真实的物理光影原理,就能实现一定程度的逼真效果 但是这样还是有一些问题,如果不加处理地直接用贴了纹理的平面做背景,那么从正面看过去的时候,由于上下左右都有纹理,就会让人眼误以为前面是个曲面(因为人的眼睛是“相信”正面是无纹理的,为了修复这一缺陷,需要把整个画面都涂上统一的色彩,也就是“统一着色法”) 但是用这种方法做出来的感觉还是不太真实,毕竟人眼看到的东西是有厚度的。要解决这个厚度的问题就要引入第二个概念——深度。将前面平面上的所有物品都以正确的深度排列起来,就可以得到更逼真的效果 但这时如果直接这么弄的话,问题就来了,因为我们在用鼠标控制视角旋转时,视线是会跟着移动的,这就使得我们眼睛看到的景象产生了动态的效果,而上面那个解决方法做的只是静态效果。为了避免这个问题,我们就得想办法让平面上的景物“动”起来,即让它们根据我们的视角变化而改变自身的深度(这其实就是加上了z值的概念,前面说的视差的“+”号就是这个意思,加z值就是往后面加一个距离,所以这实际上是一种“推远”的操作,而不是“拉到眼前”,这也是为什么加入了深度之后物体会显得更“厚”一些的原因)。
至此,一个看似合理的现实世界应该已经形成了(当然,这一切都是基于“假设”我们的世界真是由二维平面组成的,假设错误的话一切白搭) 现在的问题是,怎样让这个由平面向内的世界运转起来呢? 答案是,用一个循环执行的多线程任务来解决。
具体做法是,每过一段时间或者每次鼠标转动视角,就检查一下场景中的物件们是否需要更新深度,如果需要的话,就把它们按照最新的深度信息重新排序并渲染出去。至于那些没有变化的物件,则无需重新计算它们的深度,这样可以大大节约资源,提高运行效率(否则的话,每个物件都要自己判断自己的z值是否需要更改,效率实在太低)。