5月29日 22:35

WebGL 雾效(Fog)是如何实现的?

WebGL 雾效的本质就是根据片段到相机的距离,在物体颜色和雾颜色之间做插值:finalColor = mix(fogColor, objectColor, fogFactor)。三种计算 fogFactor 的方式:线性雾 clamp((end - dist) / (end - start), 0, 1) 需要指定起止距离;指数雾 exp(-density * dist) 更自然,一个 density 参数搞定;指数平方雾 exp(-(density*dist)²) 过渡更柔和。深度值从视图空间的 -viewPos.zlength(viewPos.xyz) 获取,后者基于实际距离而非仅 Z 值,物体旋转时效果更稳定。

追问

线性雾和指数雾怎么选?

线性雾可控性强,适合有明确近远边界的场景(如走廊)。指数雾只需一个 density 参数,远处自然消融,户外场景首选。指数平方雾过渡最柔和,但远处会突然消失,实际项目很少用。

雾颜色一定要和背景色一致吗?

是的,否则远处的物体会被雾染成另一个颜色,而不是"融入背景"。雾颜色 = 清屏颜色 = 天空盒颜色,三者必须统一。

雾效能用来做性能优化吗?

可以。远处的物体被雾覆盖后几乎看不见,可以降低远处物体的 LOD 级别甚至不渲染,雾正好遮住裁剪的接缝——这是开放世界游戏的常用技巧。

Three.js 里的 Fog 和 FogExp2 有什么区别?

THREE.Fog(color, near, far) 是线性雾,THREE.FogExp2(color, density) 是指数雾。设置 scene.fog = new THREE.Fog(...) 后所有材质自动应用,不需要改着色器。自定义 ShaderMaterial 需要手动读取 fogColor/fogDensity/fogFar/fogNear uniform。

如何实现高度雾(Height Fog)?

标准雾只看距离,高度雾额外考虑世界空间 Y 坐标:低处雾浓、高处雾淡。片段着色器中用 worldPos.y 做第二次混合,两个因子相乘就是最终雾浓度。

标签:WebGL