初探雾效果!Shader 源码分析与讲解! Cocos Creator 3D Shader Fog !

效果

3469c7667ce24d6b40832bd9e7277e4c.jpeg

原理

雾效(fog)是游戏中常用的一种效果,根据远近产生不同的深度的雾效果。

这个效果涉及两个关键字。

  • 距离

  • 颜色

在着色器中,雾效的距离,一般转换成计算雾效因素(factor_fog),这个数字范围是0-1

  • 1 表示完全不受雾影响

  • 0 表示完全被雾笼罩

接着再根据这个雾效因素去计算颜色,混合当前颜色color和雾factor_fog的颜色即可。

mix(cc_fogColor.rgb, color.rgb, factor_fog)
d2fccc57a86dd934d642ad4e4645fce6.jpeg

接下来就是如何去计算这个雾效因素了。

雾效因素一般是通过由摄像机位置(cc_cameraPos)和当前点位置(世界坐标,由世界空间矩阵和模型坐标计算的wPos)的距离去计算的。

float cam_dis = distance(cc_cameraPos, wPos);

不同的雾效果,采用不同的方式去计算雾效因素。

线性雾

线性一般会有两个参数去计算。雾开始的地方fogStart和雾最远的地方fogEnd

  • 当距离小于雾开始的地方,表示没有雾,即雾效因素为1

  • 当距离大于雾最远的地方,完全被雾给覆盖了,即雾效因素为0

33580626b690a8ab1e4668651447e5ab.jpeg
factor_fog = clamp((fogEnd - cam_dis) / (fogEnd - fogStart), 0., 1.);
5baa86495c959dd8673c29fbf6a0afa8.jpeg

当然也可以改造一下,在0-1之间平滑一些。

factor_fog = 1.0 - smoothstep(fogStart, fogEnd, fogDistance);
30f8f1267101bc66e94c7cc92fc3b462.jpeg

指数雾

指数雾就是用指数函数根据距离计算雾效因素。

一般会有一个雾浓度fogDensity去控制这个指数函数。

一般指数雾:

factor_fog = exp(-cam_dis * fogDensity);

平方指数雾:

factor_fog = exp(-cam_dis * cam_dis * fogDensity * fogDensity);
6c5acf0d76414d9a62a598e190c89240.png

这里的 cam_dis 通过如下方式实现:

float cam_dis = distance(cc_cameraPos,wPos)/ fogAtten * 4.;

新增 fogAtten属性的主要目的在于可以自定义无效衰减系数到合适的位置。

层级雾

层级雾计算过程相对复杂,大致过程就是计算水平面的距离和高度距离以及浓度参数,具体实现过程可以参考源代码 cc-fog.chunk

fDensity = (sqrt(1.0 + ((fDeltaD / fDeltaY) * (fDeltaD / fDeltaY)))) * fDensityIntegral;
factor_fog = exp(-fDensity);

移植

Cocos Creator 3D v1.2 版本之前还未提供雾效果,那么该如何移植或定制呢?

把控一个重点,雾效果的关键就是计算雾效因素。

因为材质默认使用的是 builtin-standard.effect,可以拷贝一份重新写个build-in-fog.effect,然后再将需要雾化的材质选择这个effect

先在顶点着色器中加一个雾效因素的计算方法。

out float v_fogFactor;
float computeFogFactor(float fogDistance){
    const float start = 1000.0;
    const float end = 3000.0;
    const float density = 0.0002;
    // return clamp((end-fogDistance)/(end-start), 0.0, 1.0); //雾化因子线性变化
    return 1.0 - smoothstep(start,end,fogDistance); //雾化因子非线性变化
    // return exp(-(density*fogDistance)); // 指数雾
    // return exp(-density*density*fogDistance*fogDistance); // 指数雾2
}

把雾效因素传给片元着色器。

v_fogFactor = computeFogFactor(length(cc_cameraPos.xyz - pos.xyz));

在片元着色器中接收雾效因素。

in float v_fogFactor;

计算混合颜色。

color.rgb = mix(fogColor, color.rgb, v_fogFactor);

效果预览(示例项目可以联系原作者获取):

a6623e3d4dc694a4a2124bc6dfdb8894.gif

小结

fog !计算雾效系数 !混合颜色 !shader

雾效是在游戏中是广泛应用的一种特效,尤其是广阔的地形和无限跑酷类游戏中特别实用。Cocos Creator 3D v1.2 引擎中正式引入了场景级别雾效的支持,还带来了诸多重要的新特性和优化,目前正在论坛公测中。

公测链接:
https://forum.cocos.org/t/cocos-creator-3d-v1-2/97907/11

很感谢白玉无冰对这部分实现的详细解析,相信可以帮助开发者更好地理解和使用雾效这项新功能。欢迎分享本文给身边的朋友,也欢迎您在评论区或进入作者原文一起交流!

如果您在使用 Cocos 引擎的过程中,获得了独到的开发心得、见解或是方法,并且乐于分享出来,帮助更多开发者解决技术问题,加速游戏开发效率,期待您与我们联系!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值