首页>
技术资讯>
详情

Alpha混合物体的深度排序

2016-05-24 来源:CloudBest 阅读量: 0
关键词: 游戏图形图像

    先说个题外话, 本来我想解答一下最近Creators Club论坛上经常出现的一个问题, 意外的是在网上竟然找不到什么全面的答案
    这是个有着复杂答案的简单问题:
    “为什么我的透明物体的绘制顺序不对, 或者有些不见了?”
    当绘制一个3D场景时, 对图形进行深度排序是非常重要的, 这样离镜头近才画在远处物体的前面。 我们不会希望看到远处的山把近在眼前的建筑给挡住了!
    如今有三种深度排序方法得到了广泛的应用:
    深度缓冲 (也叫做 z-buffering)
    油画家算法
    背面剔除
    不幸的是, 每种都有其局限性。 为了达到好的结果, 大多数游戏是把三种方法结合起来使用的。
    深度缓冲
    深度缓冲简单而有效, 结果也很完美。 但是对于透明的物体它就无能为力了!
    这是因为深度缓冲只记录了当前已经绘制的最近像素。 对于不透明的物体, 这已经能够满足我们的需要了。 看一下这个绘制两个三角形的例子, A和B:

    如果我们先画B再画A, 深度缓冲会看到新的像素(A的)比之前的(B的)要近, 那么它就画在了前面。 如果我们用相反的顺序画(先A后B), 深度缓冲会看到B的像素比之前A已经画的要远, 所以就把它们给丢弃掉了。 无论哪种情况我们都会得到正确的结果: A在前面, B隐藏在后面。
    但是当这些几何图形是透明的, 即B透过A是部分可见的时会怎样呢? 如果我们先画B再画A的话是没有问题的, 但反过来就不行了。 在这种情况下, 深度缓冲会从B取一个像素, 同时注意到已经绘制了一个更近的像素(A的), 然后它就没辙了! 唯一的选择是绘制B(这会得到一个错误的结果, B会画在A前面, 但A的alpha 混合却没有起作用), 或者完全抛弃B. 不爽!
    结论: 深度缓冲对于不透明的物体是很完美的, 但对于透明的物体却不实用。
    油画家算法
    深度缓冲没法应付以错误的顺序来绘制透明物体的情况, 这很好解决, 对吧? 保证它们按正确的顺序绘制就可以了! 如果对场景中的所有物体进行排序, 那我们就可以先画远处的, 再画近处的, 这样就可以确保前面例子中的B可以在A之前绘制。
    不幸的是, 这说起来容易做起来难。 对物体进行排序在很多情况下并不适用, 如A和B相交的情况该怎么办?

    如果A是个玻璃杯而B是它里面的一个玻璃球时就是这样。 现在我们就没法对它们进行排序了, 因为A的一部分比B近, 而另一部分又比B远。
    甚至我们不需要两个不同的物体来复现这个问题。 组成玻璃杯的那些三角形会怎样? 要让它们显示正确, 需要在前面的绘制之前先绘制后面的。 所以, 只对物体进行排序是不够的: 我们要对每一个三角形进行排序。
    问题是, 对每个三角形进行排序的代价太大! 就算我们能够承受, 这也不是在所有的场合下都能得到正确的结果的。 比如说两个透明的三角形相交时会怎样呢?

    没有方法对这样的三角形进行排序, 因为我们需要把B的上半部分画在A的前面, A的下半部分画在B的前面。 唯一的解决方案就是把三角形从相交处分割开来, 但是这样的消耗是不可承受的。
    结论: 油画家算法需要你在选择排序的粒度好好权衡一下。 如果你仅仅对一些大的的物体进行排序, 速度很快但不是很精确; 如果你对一些小物体进行排序(包括三角形个体的极限情况), 速度会慢一些, 但更加精确。
    背面剔除
    一般不把背面剔除当成是一种排序技术, 但它确实是一种重要的方法。 它的局限性就是只适用于凸面体。
    考虑一下一个简单的凸面体, 如一个球体或立方体。 无论你从哪个角度看, 每个屏幕上的像素都会被覆盖两遍: 一次是物体的前面, 一次是后面。 如果你用背面剔除丢弃了背面的三角形, 那就只剩前面了。 哈哈, 如果每个屏幕上的像素只进行一次判断, 那你就自动得到了一个完美的混合结果, 没有必要排序任何东西。
    当然, 大多数的游戏不会只画球体或立方体J 所以只是背面剔除的话不是一个妥善的解决方案。
    结论: 背面剔除对于凸面体是完美的, 但是对于其它的就无能为力了。
    我该怎样让我的游戏看起来更好一些?
    最常用的方法:
    1. 设置DepthBufferEnable 和DepthBufferWriteEnable 为true
    2. 绘制所有的不透明物体
    3. 保持DepthBufferEnable 为true, 但是设置DepthBufferWriteEnable为false
    4. 对alpha混合的物体按照与摄像机的距离进行排序, 然后从后到前画出来
    这依赖于三种排序技术的结合:
    不透明的物体按深度缓冲排序
    透明物体和不透明物体仍然会被深度缓冲处理(所以你永远不会通过一个不透明物体看到一个透明的)
    油画家算法对透明的物体排序(两个透明物体相交时仍然会有排序错误)
    依赖背面剔除来对单个透明物体上的三角形排序(如果物体不是凸面体也会产生错误)
    结果并不是非常完美, 但是非常高效, 易于实现, 对于大多数游戏来说也够用了。

热门推荐 查看更多