zoukankan      html  css  js  c++  java
  • 在Deferred框架中轻松实现Decal

    转载请注明出处为KlayGE游戏引擎,本文的永久链接为http://www.klayge.org/?p=2074

    现代3D游戏经常会需要用到decal,子弹孔、脚印……传统的decal渲染从Quake 2时代开始就没怎么变过,通过画一个紧贴着物体的四边形来实现。问题一直很多,比如光照的不一致,z-fighting造成的闪烁,渲染状态的来回切换,等等。那么到了deferred框架中,这种情况会有所好转吗?

    有趣的是,deferred框架内实现decal不但非常容易:100行之内的代码量,不到20分钟就能完成,而且非常稳定,完全没有上述各种缺点。更有趣的是,deferred的decal被至少三组不同的人都提出过完全相同的算法,都在讨论会出现的相同问题,只是被分别叫成了不同的名字。现在看看这三组:

    • Crytek的Jan Krassnigg在2010年于Game Engine Gems 1里的一篇文章A Deferred Decal Rendering Technique提出了称为Deferred Decal的方法,同时他也在SIGGRAPH 2011的talk CryEngine 3: Reaching the Speed of Light中提到了一次。
    • Avalanche Studios的Emil Persson在2011年的GPU Pro 2的文章中独立提出了Volume Decals,在他网站也给出了一个demo。
    • Relic Entertainment的Pope Kim在SIGGRAPH 2012的一个talk中提出了Screen Space Decals

    既然这三种方法完全相同,我们其实只要讨论一种即可,统称为Deferred Decal。(顺便吐槽一下第三个,Screen Space Decals。作者不但是在看了前两个后提出了个毫无新意的东西,并且起了个奇烂无比的名字——很显然那东西不是screen space的。更恶心的是用了个SSD的缩写,嫌缩写混乱还不够多吗?他的ppt基本就是前两篇的问题,只是换成自己的图。遇到新问题直接就选择了避开,或者胡搞一个解法。)

    Deferred Decal的基本思路就是,在G-Buffer建立之后,把每一个decal当作一个立方体迭加到G-Buffer上。对于G-Buffer中被立方体覆盖的像素,用decal的color和normal来替换掉。在PS中,只要

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // 从eye坐标系转回decal立方体的坐标系
    float4 decal_pos = mul(float4(pos_es, 1), inv_mv);
    // 忽略超过范围的像素
    if (any(abs(decal_pos.xyz) > decal_pos.w))
    {
    discard;
    }
    // 计算像素对应的decal纹理坐标
    decal_pos /= decal_pos.w;
    texcoord = float2(decal_pos.x, -decal_pos.y) * 0.5f + 0.5f;

    由于操作的对象是整个G-Buffer,包括normal、diffuse、specular、shininess,所以这样的decal可以修改掉其中任何一个属性,并且在光照阶段不会增加任何开销。这也是传统的decal系统很难做到的。这里我贴了一个shininess很高的decal:

    Decal specular

    这种方法的最常见问题是,因为立方体的覆盖面积远远大于decal,有时候会在不该贴的地方贴上了拉伸严重的。解决方法是把decal立方体的normal和G-Buffer中的normal作比较,如果差别较大,就忽略掉。但因为写入的目标是G-Buffer,decal的PS就没法读取G-Buffer。所以我的方法是在PS里读取相邻点的depth,计算一个screen space normal(就好像Edge AA里做的一样),把它和decal立方体的normal比较。下面比较了没加此处修正和加上后的区别:

    修正前:

    Decal stretch

    修正后:

    Decal stretch fixed

    另一个常见问题就是视点进入decal立方体后,由于culling的关系,decal消失。解决方法是在那种情况下改成画back face。

    在deferred下实现decal就这么简单!

  • 相关阅读:
    Java基础--线程创建方式
    Java基础--static关键字
    Java基础--异常处理
    mybatis的#{}和${}的区别以及order by注入问题
    前后端分离结构中使用shiro进行权限控制
    Java FTP下载文件
    10个经典智力推理题!据说答对7道,智力在140!
    Java面试题总结之数据结构、算法和计算机基础(刘小牛和丝音的爱情故事1)
    Java面试题总结之JDBC 和Hibernate
    Java面试题总结之数据库与SQL语句
  • 原文地址:https://www.cnblogs.com/gongminmin/p/2747860.html
Copyright © 2011-2022 走看看