Decal渲染是一个引擎中重要的一部分,记忆中印象最深刻的就是以前CS中的弹痕与爆炸痕迹了。目前来说,Decal的实现方法也比较多,而且感觉还跟游戏类型有关,比如子弹乱飞的射击类FPS游戏中对贴花系统的要求就比较高,因为本来Decal的变化就比较丰富。一般来说贴花渲染主要有两种实现方法:

  • Texture projection关于投影纹理的原理网上也有很多文章,基本就是需要对地形渲染两遍,一遍正常渲染,一遍用投影的纹理渲染,然后把这两个混合的结果融合。显然,如果场景中的贴花较多,且场景规模复杂的话,这种方法就会比较费。
  • Mesh projection 这种方法应该来说使用比较多,包括早期Source中的Decal等使用的应该就是这种方法,其主要原理就是将Decal处理为附着于其所能贴到的几何表面上的几何网格,然后当做polygon list来渲染。当然这些网格也是经过修饰的(比如贴到一个桌子的边角上时,就需要根据桌角几何网格的分布来裁剪Decal所对应的网格)。关于该方法这里有一篇文章介绍得非常好:http://blog.wolfire.com/2009/06/how-to-project-decals/。另外,基于此种方法的改进类型也不少,比如Frosbite引擎中就利用Geometry Shader来生成类似该类型的Decal(Shadows and Decals in the Frostbite Engine)。

结合最近普遍应用的后处理渲染流程,于是自然而然地也就出现了Deferred Decal,这里一个最基本的条件就是需要有一个基于延迟渲染的系统才能使用这种方法。关于Deferred decal的实现原理也比较简单,过程如下:

  1. 在后处理渲染中完成正常的G-Buffer渲染后,即可得到对应的Normal-depth buffer,以及Diffuse Buffer,但是此时仍没有进行光照计算,这时就需要将Decal给渲染到对应的Diffuse buffer中。为了实现Decal,这里需要在G-Buffer后再增加一个Pass,并使用Diffse buffer作为Render target,并使用Decal shader进行渲染,计算并更新Decal所能够影响到的那些Pixel的Diffuse。
  2. 为了确定每个Decal所能够影响到的范围以便更新相应的Diffuse buffer,一般需要绘制出Decal所对应的一个包围几何体,这里可以是Sphere或Box(例如Volume decal中使用的就是Sphere,CryEnigne中使用的就是Box),当然,如果不计代价还可以使用更复杂的形体。
  3. 最后,关键的一步就是计算需要Decal的那些Pixel所对应的Decal uv,这里根据包围体的不同方法也不同。Sphere的映射方法比较简单,可以直接将Pixel的世界坐标转到局部球体坐标即可,再根据对应的Volume texture或2D texture再做一次映射,然后访问纹理即可。如果使用Box的话可能就稍麻烦些,这时需要知道Decal box所对应的一个局部坐标系转化。这个Decal坐标系由以下几个量来确定:Decal所贴的位置,Decal贴到处的Normal,Decal的水平方向,Decal的大小变换;然后由这三个基本量来构靠世界到Decal局部的变换矩阵:
    [cpp] view plaincopy
    1. float3 gDecalScale;
    2. float3 gDecalPosition;
    3. float3 gDecalNormal;
    4. float3 gDecalLRVector;
    5. float3 zAxis = normalize(gDecalNormal);
    6. float3 xAxis = normalize(gDecalLRVector);
    7. float3 yAxis = normalize(cross(xAxis , zAxis));
    8. float4x4 decalMatrix =
    9. {
    10. {xAxis.x , yAxis.x , zAxis.x , 0.0f} ,
    11. {xAxis.y , yAxis.y , zAxis.y , 0.0f} ,
    12. {xAxis.z , yAxis.z , zAxis.z , 0.0f} ,
    13. {-dot(xAxis , gDecalPosition) , -dot(yAxis , gDecalPosition) , -dot(zAxis , gDecalPosition) , 1.0f}
    14. };

    这里的变换矩阵其实也相当于在Decal的位置上放置一个Camera,即从Decal的角度来观察整个场景~_~

  4. 得到变换矩阵之后即可对Pixel变换,然后在局部坐标中计算出对应的Decal UV就可以做相应的Decal纹理读取了。

比如将下面这个很有追求的Decal贴到Sponza场景中的效果如下

 

Enhanced effect with Bump:

此外,为了增强Decal的渲染效果可以使用带有Bump的Decal,不过这里要加入到整个渲染流程中的话可能会稍稍有些麻烦。为了使用Decal的Normal并在此上进行光照着色,就需要把Decal的Bump给附加到G-Buffer中的Normal上,这一步虽然与Decal texture的附加类似,但通常情况下Normal与Depth会在一个Buffer里边存储,而在进行Diffuse的decal pass时由于需要反求像素的世界位置,因而就要使用ND buffer,这样就不能在该pass里完成decal bump normal的合并。不过可以再建立一个跟Diffuse类似的中间Buffer,其只用来存储渲染Decal时生成的Normal值;然后在当前的Decal pass结束以后,再使用另外一个Pass,使用Normal Depth作为目标RT来合并原始Normal与Decal的Normal。

但是,这其中又涉及到另外一个变换:Decal normal由局部坐标到世界坐标的变换,这其实是相当于对应于decal space的一次tangent变换,需要对于上述的decalMatrix求逆转矩阵来做变换,而这一步的代价还是比较费的,因而此功能就需要谨慎使用。

Some Tips:
  • 处理不同类型物体时的操作。在使用Defferd Decal的方法时,这个问题其实最为常见,也最需要解决。其实这里的不同类型较为广泛,比如说下述几何上不属于同一类物体(见下图),本来是想只将Decal贴在旗子上,但是其却也出现在了后面的墙上;另外,还在就是比如地面上的decal,但如是主角走过该处时,decal可能就同样会出现在角色身上。这个问题一般有两种解决方法:Stencil testing,Object index。前一种方法使用模板测试来标识不同的物体,相对来说其实现较为方便些,而第于二种方法可能需要改变G-Buffer的内容,在使用上可能还不如第一种方法,虽然其通用性更强。
  • 关于Corner Wrap问题,这种情况的表现就像下图所示。该情况的产生是由于通常情况下只考虑Decal水平方向上的坐标投影变换来计算UV,而并没有考虑Decal normal方向上的影响。知道原因后这个问题比较容易解决,可以利用法向量的变化来计算Decal垂直方向上的UV分布就可以了。 
  • Decal texture采样寻址方式需要设置成CLAMP,否则就会出边重复的情况,视觉上的不正确。另外,也要注意Alpha的混合状态设置。
  • 关于Camera进行Decal Box或Sphere内部的问题。由Defferred decal的实现原理可知,画出包围Decal的Box或Sphere其实是用来标记其所影响的Pixel以便更改diffuse,但这样就会有一个问题,那就是当Camera进入Box或Sphere内部后可能就会导致在视点处直接看到原始mesh,而不是box的mesh,这样肯定就不会进行Decal所对应的shader了,于是也就没法画上decal。这个问题也好解决,既然想增加对原始Mesh的遮挡,那么就可以将原始的Box或Sphere细分,即在其内部增加绘制的triangle以增加遮挡的机会,这样即使Camera进入其内部,仍然可以有内部的子部件来遮挡原始Mesh。不过简单起见可以只在Box内部再多画几个对角线上的triangle就可以应付大多数情况了。
  • 对于Decal数量较多的情况,加入Decal Box或Sphere的实例化渲染以及对应Camera的可见性检测也是很有必要的。

Deferred Decal相关推荐

  1. Deferred Decal(延迟贴花)

    Decal渲染是一个引擎中重要的一部分,记忆中印象最深刻的就是以前CS中的弹痕与爆炸痕迹了.目前来说,Decal的实现方法也比较多,而且感觉还跟游戏类型有关,比如子弹乱飞的射击类FPS游戏中对贴花系统 ...

  2. (41)Decal [ 贴花] Actor

    添加decal到关卡中 向场景中添加decal的最简单的方法是:在内容浏览器中选中适当的decal材质,然后右击并从关联菜单中选择 Add Actor(添加 Actor) > Add Defer ...

  3. Decal Buffer相关

    延迟渲染与前向渲染 前向渲染或叫正向渲染,每一个图元都经过顶点着色器,图元着色器,片段着色器,在片段着色器内连同光照一起计算,效率和图元数量有关. 延迟渲染会先计算出G-BUFFER,就是不含光照计算 ...

  4. Unity内置Shader解读3——Decal

    1.Shader在什么情况下使用 Decal(贴花)贴花就是类似于CF里的喷漆,或者汽车/墙上等贴一个贴纸. image.png 2.Shader的价值(用的多不多),Shader的难度 这个应该是极 ...

  5. UE4使用贴花(Decal)

    一.创建贴花材质 1:新建一个Material材质,修改Material Domain 为Deferred Decal (延迟贴花),设置Blend Mode 为Translucent(半透明) 2: ...

  6. UE4 Material Properties

    材质 & 贴图 On this page: Physical Material Material Translucency Translucency Self Shadowing Usage ...

  7. UNREAL ENGINE 4.12 正式发布!下载地址

    UNREAL ENGINE 4.12 正式发布! 下载地址:https://www.unrealengine.com/ Alexander Paschall 在 June 1, 2016 |功能新闻社 ...

  8. 90天入门UE引擎开发--学习日记(60/100)

    教程 Game艺视界 - Ben UE5着色器材质节点 快捷键 D键   缩小图片节点 A键   Add M键  Multiply D键   Divide 介绍面板 节点里第三层是最重要的 新建工程 ...

  9. UE4Material_材质属性(1)

    材质中的属性: 物理材质 Phys Material(物理材质) 与该材质关联的物理材质 .物理材质(Physical Material)提供了物理属性的定义,例如碰撞(弹力)以及其他基于物理的方面会 ...

最新文章

  1. ssh,FTP到远程服务器时,显示自定义的警告信息
  2. 服务器cpu天梯图_九月手机处理器排名 2020年9月最新版手机CPU天梯图
  3. mysql map 键值对获取_mysql map_get function,用于解析map结构数据,根据key返回相对应value...
  4. 字符识别(模板匹配BP神经网络训练)
  5. 双网卡主机配置oracle监听,VirtualBox设置双网卡实现虚机上网及主宿机互访
  6. java 多线程学习
  7. Solr 新增、更新、删除索引
  8. python 第四天
  9. java并发编程 Lock
  10. window 软件 C盘 文件 搬家(配置文件搬家)
  11. SOP 封装 和 SOIC 封装的区别——细微差别,可以混用
  12. 【MapReuce】读取本地美国疫情数据存储结果到MySQL
  13. 保研之路——上交大电子系直博
  14. python 数学公式显示_python 数学公式·
  15. AE MG动画脚本motion2 脚本使用方法学习笔记
  16. SOS关于组建星际物质研究自愿者协会的倡议
  17. 【数字图像处理】图像几何变换之 图像的极坐标变化展开鱼眼图
  18. Python 用26个英文字母生成序列
  19. VMWare虚拟机下载|最新版|破解版
  20. jQuery选择器之类选择器

热门文章

  1. 看 PrisonBreak,学美语
  2. 手机、浏览器的分辨率、状态栏参数
  3. 通向Golang的捷径【21. Go 语言的实际应用】
  4. 快手本地生活可以入场吗
  5. 计算机时间怎么改24小时模式,怎么修改电脑的时间为24小时制啊?
  6. Axure RP 9 最新版授权码(亲测有效)
  7. Gnirehtet使用教程 —— 将电脑网络通过USB共享给Android 设备
  8. ubuntu WPS字体缺失 解决方法
  9. windows 没有应用商店,直接安装所需应用的解决方案
  10. 计算机adminstor用户不见了,Win10管理员账户不见了如何用Administrator登录