【百人计划先行版】大世界雾效实现

雾效分类与整体实现原理分析

        雾效分类:按表现/实现 方式

高度雾/顶点雾(该雾效需要对场景中所有物体的Shader 追加雾效Shader)

 深度雾/后期雾(通过后处理进行计算)

         雾效实现原理分析(物理原理与实现方式)

物理原理:在水汽充足、微风及大气稳定的情况下,相对湿度达到100%时空气中的水汽便会凝结成细微的水滴悬浮于空中,使地面水平的能见度下降。这种天气现象称为雾。

实现方式:雾效的核心是使用一个新的颜色(雾色)替换(一部分 )物体本身计算的颜色。其中主要的复杂计算在于正确的雾效浓度,其次是在有光源的散射产生的颜色混合;在向前渲染中,大作使用顶点雾,即在每个场景物体进行着色的最后一步进行雾效计算,直接将混合结果输出到物体上;而后期雾主要是指通过读取buffer中的信息例如深度信息而计算雾的方式,通常用于延迟渲染等渲染管线。

雾效的分解

        雾效果分为对场景中 地面、天空的影响

        天空的部分,从上往下呈现逐渐减淡,黄色部分是模拟光的散射

         地面部分

         指数雾密度的计算

动画3.gif

雾的密度与相对高度呈指数相关(相机与顶点高度差越小,雾密度越低;雾由浓至淡的变化高度本身相对相机存在高度差:雾从海拔高度为0向海拔高度为400m逐渐稀薄,但是摄像机在海拔200m位置,则高度差为-200m)

雾密度

        雾密度 = 全局密度 * 2 ^ (相机高度 - 目标位置高度 - 雾变化高度范围相对摄像机的高度差)

由于角色会在场景中移动,角色视角中最近的物体 雾的强度也最低,因此使用相机的位置和物体顶点的位置的差作为高度雾的指数。(为了让雾气更可控,添加两个参数:对雾整体强度的控制(——GlobalDensity),高度差参数(——FogHeight))

         指数雾强度计算

为什么要用指数来模拟?因为要达到这样一个效果:近处雾的变化较缓,远处雾的变化较快。

雾散强度 = 全局雾散系数 * (目标位置高度 - 相机高度 - 雾变化高度范围相对摄像机的高度差)

参数——FogFallOff对雾的指数变化进行控制;x为距离

雾强度:FogFactor = (1-exp2(-Falloff)/Falloff)

1.gif

 f=kx,这里的 k = _FogFalloff , x = (posWorld.y - _WorldSpaceCamarePos.y - _FogHeight)

当高度产生的数值增加,雾的强度呈指数上升,相对高度越高,雾的强度增长得越大

距离计算

动画4.gif

雾密度与相对距离相关,相机与顶点的距离越远,雾越浓。距离摄像机过近的位置,雾会被稀释,很难看到雾;因此拟合雾与相对距离正相关,并且有一个可控的起始变化距离。

雾随距离变化的强度:

视线向量 = 目标位置世界坐标 - 摄像机世界坐标 

视线距离 = 视线向量 的长度

雾距离强度 = (视线距离 - 手动控制起始距离)/ 距离变化系数

ps:如果实际项目中想要让雾的衰减看起来像一个平面的话,需要单独对顶点到摄像机的这个向量(实现向量)进行处理。

        (总)雾整体的强度

雾 = 雾强度 * 雾密度 * 雾距离强度

        光散射强度

 当然如果雾是一个单色的话,在白天会显得有点儿假,因为实际情况是太阳会发生散射。(收光照射的顶点,其雾的颜色会受到光源颜色的影响,由于雾效是边缘模糊的低精度效果,此处光强可以使用基本光照模型进行近似)

散射强度计算:

        散射强度 = (归一化视线向量的反方向 与 入射方向 的夹角)^ 指数衰减系数

                

 我们在这里参考Lambert光照模型,即光强度 = 顶点法线与入射光夹角;此处由于雾效距离较远(近处的雾浓度低散射强度低,使用dot(n,l)会导致远近强度一样),因此我们最终使用视线方向的逆方向代替顶点法线进行计算,同时给予指数衰减参数_FogInscatteringExp进行控制

散射衰减

 光的衰减与距离有关,较近处由于雾气密度较薄,散射强度小,越远处越强。

 

散射颜色混合

 fogColor = lerp(_FogColor, _LightColor0,saturate(inscatteringFactor));

最终雾效颜色 = 雾效色与光源颜色的散射强度插值

最终效果

雾效Shader编写注意事项(头文件)

函数复用:由于雾效需要对不止一个Shader生效,因此最好将函数封装进头文件使代码更加干净

 

 提供分支开关:雾效应当提供开关以便特殊处理以及查看结果,此处使用Shader feature 关键字进行处理,并保持关键字名称一致,以使用单个全局开关统一控制

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值