Skip to content

Exponential Height Fog

Magic0Conch edited this page Jun 6, 2023 · 2 revisions

效果

ExpontialHeightFog

实现过程

计算一个雾的比例,设定雾的颜色,对于每个着色点,最终颜色按照下式计算:

col.rgb = col.rgb*fogInscatteringAndOpacity.a + fogInscatteringAndOpacity.rgb;

除了雾以外,太阳光也会对雾有影响,所以需要叠加directionalInscattering。

fogColor = _FogColor.rgb*(1-expFogFactor) + directionalInscattering;

1. 重建世界坐标系

CPU部分

输入:fov、aspect、near
输出:frustumCorners(Matrix4x4)
图片

GPU部分

输入:深度纹理(0~1空间),相机世界坐标
输出:每个片元对应的世界坐标

worldPos = _WorldSpaceCameraPos + linearDepth * rayDir;

2. 计算透光率(Transmittance)

主要思想是传输方程,由于有介质,每个像素的着色为原始着色点的颜色*透光率+光线在介质中的积分。
图片

为了性能考虑,在UE中使用beer定律对raymarching进行近似(光线均匀穿过介质的时候,亮度呈指数衰减)。

雾(exclusionIntersection)的起始密度:

exponent = max(-127.0f,_HeightFallOff*(exclusionIntersectionY-_StartY));
rayOriginalTerms = _FogDensity * exp2(-exponent);

光学厚度(透光率公式的指数)

falloff = _HeightFallOff* rayDirectionY;
//(rayDirectionY是startDistance点和着色点的高度差,散射理论的名称叫光学厚度,是一个关于σt的积分。)

透光率 = exp2(-falloff)/falloff; Li = rayOriginalTerms*(1-透光率)*rayLength

参数

_FogDensity:雾的全局密度
_FogColor:雾的颜色
_StartY:雾起始高度
_EndY:雾的终止高度
_HeightFallOff:高度衰减系数
_StartDistance:雾距离相机的起始距离
_MinFogOpacity:最小透光率(不能让场景的某处全被遮盖住)

3.计算inscattering项:

介质会被光照亮,因此除了自己本身的颜色以外,要加上光的颜色。同样是沿着介质进行积分,同样使用beer定律进行近似。
注意inscatter的计算与视线和直射光的夹角相关。

inscatter= _LightColor0 * pow(dot(normalize(cameraToReceiver),_WorldSpaceLightPos0), _InScatteringExponent);

参数

_LightColor0:直射光颜色
_WorldSpaceLightPos0:直射光方向
_InScatteringExponent
_DirectionalInscatteringStartDistance:被照亮的起始距离

UE文件参考

Engine\Shaders\Private\HeightFogVertexShader.usf
Engine\Shaders\Private\HeightFogPixelShader.usf
Engine\Shaders\Private\HeightFogCommon.ush

理论推导

Clone this wiki locally