Unity 内置雾
缺点:要为场景中所有物体的 shader 添加代码,实现的效果有限。
全局雾效
基于屏幕后处理的全局雾效,不需要改 shader 代码。自由度很高
关键:根据深度图来重建每个像素在世界空间下的位置。
在简单的雾效实现中,我们需要计算一个雾效系数$f$,作为混合原始颜色和雾的颜色的混合系数;
这个雾效系数 $f$ 有很多计算方法。在 Unity 内置的雾效实现中,支持三种雾的计算方式——线性(Linear)、指数(Exponential)以及指数的平方(Exponential Squared)。
当给定距离 $z$ 后,$f$ 的计算公式分别如下:
- Linear:$d_{min}$ 和 $d_{max}$ 分别表示受雾影响的最小距离和最大距离
$$
f=\frac{d_{max}-\mid z\mid}{d_{max}-d_{min}}
$$
- Exponential:$d$ 是控制雾的浓度的参数
$$
f=e^{-d\cdot|z|}
$$
- Exponential Squared:$d$ 是控制雾的浓度的参数
$$
f=e^{-(d-|z|)^2}
$$
基于高度的雾效
本节使用线性雾来计算:
当给定一点在世界空间下的高度 $y$ 后,$f$ 的计算公式为:
$$
f=\frac{H_{end}-y}{H_{end}-H_{start}}
$$
$H_{far}$, 和 $H_{end}$ 分别表示受雾影响的起始高度和终止高度
h:16,191 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
float2 ScreenUV = i.positionCS.xy / _ScaledScreenParams.xy;
#if UNITY_REVERSED_Z
real depth = SampleSceneDepth(ScreenUV); #else
real depth = lerp(UNITY_NEAR_CLIP_VALUE, 1, SampleSceneDepth(ScreenUV)); #endif
float3 rebuildPosWS = ComputeWorldSpacePosition(ScreenUV, depth, UNITY_MATRIX_I_VP);
float fogDensity = (_FogEnd-rebuildPosWS.y)/(_FogEnd-_FogStart); fogDensity = saturate(fogDensity*_FogDensity); float4 color = SAMPLE_TEXTURE2D(_BlitTexture, sampler_BlitTexture, i.uv); color.rgb = lerp(color.rgb, _FogColor, fogDensity);
|
基于深度的雾效
h:9,121 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| float2 ScreenUV = i.positionCS.xy / _ScaledScreenParams.xy; #if UNITY_REVERSED_Z float depth = SampleSceneDepth(ScreenUV); #else float depth = lerp(UNITY_NEAR_CLIP_VALUE, 1, SampleSceneDepth(ScreenUV)); #endif
float linearDepth = LinearEyeDepth(depth, _ZBufferParams);
float fogDensity = (linearDepth-_FogStart)/(_FogEnd-_FogStart); fogDensity = saturate(fogDensity*_FogDensity); float4 color = SAMPLE_TEXTURE2D(_BlitTexture, sampler_BlitTexture, i.uv); color.rgb = lerp(color.rgb, _FogColor, fogDensity);
return color;
|