标签:颜色 app 计算 步骤 包含 inline else border mode
应用雾到游戏对象
基于距离或深度的雾
支持deferred fog
在14之前,一直假定着光线在真空中传播,在真空中可能是精确的。但是当光线穿过大气或水就不一样了,光线在击中物体表面时会发生被吸收、散射和反射。
一个精确的大气干扰光线渲染将需要及其昂贵的体积测量方法,那是大多数现代GPU负担不起的。相反,勉强采用一些常量雾参数近似模拟。
Unity光照设置包含了场景雾设置选项,默认是不启用。启用后,默认是灰色雾。Unity自带的雾只适用于使用了Forward渲染路径的物体。若激活Deferred path,提示:
图1 deferred 提示
图2 不明显的雾
图2不明显,是因为Fog color灰色雾将散射和反射更多的光线,吸收较少。把Fog Color改为纯黑色试试
图3 linear fog
Linear Fog Mode:雾的浓度是随视距线性增长的,在视距开头正常显示,超过这个距离就只有雾的颜色可见。
线性雾公式:
c 是雾坐标;
S 是视距起始距离;
E 是视距终止距离;
f值 被限定在[0, 1]范围,被用在雾和物体着色之间插值。
最终计算在fragment color着色到物体对象上,雾不会影响到skybox
更接近真实感的雾
图4 指数雾
指数雾公式:
d 是fog的密度因子;
c 是距离因子
图5 指数平方雾
指数平方雾公式:
增加Fog到自己的shader中,增加Fog需要使用内置关键字:multi_compile_fog指令。该指令会额外增加:FOG_LINEAR、FOG_EXP、FOG_EXP2变体。
#pragma multi_compile_fog
新增ApplyFog()函数,用于在Fragment计算最终着色:获取当前颜色和插值数据作为参数,返回最终颜色。
计算步骤:
任何雾公式都是基于视距的,首先计算出视距值备用;
然后使用UnityCG.cginc宏UNITY_CALC_FOG_FACTOR_RAW根据具体雾公式计算出雾因子。
最后根据雾因子,在fog_color和当前color取插值返回。
float4 ApplyFOG(float4 color, Interpolators i) { float viewDistance = length(_WorldSpaceCameraPos - i.worldPos); UNITY_CALC_FOG_FACTOR_RAW(viewDistance); return learp(unity_FogColor, color, unityFogFactor); }
//宏UNITY_CALC_FOG_FACTOR_RAW #if defined(FOG_LINEAR) // factor = (end-z)/(end-start) = z * (-1/(end-start)) + (end/(end-start)) #define UNITY_CALC_FOG_FACTOR_RAW(coord) float unityFogFactor = (coord) * unity_FogParams.z + unity_FogParams.w #elif defined(FOG_EXP) // factor = exp(-density*z) #define UNITY_CALC_FOG_FACTOR_RAW(coord) float unityFogFactor = unity_FogParams.y * (coord); unityFogFactor = exp2(-unityFogFactor) #elif defined(FOG_EXP2) // factor = exp(-(density*z)^2) #define UNITY_CALC_FOG_FACTOR_RAW(coord) float unityFogFactor = unity_FogParams.x * (coord); unityFogFactor = exp2(-unityFogFactor*unityFogFactor) #else #define UNITY_CALC_FOG_FACTOR_RAW(coord) float unityFogFactor = 0.0 #endif //宏UNITY_CALC_FOG_FACTOR #define UNITY_CALC_FOG_FACTOR(coord) UNITY_CALC_FOG_FACTOR_RAW(UNITY_Z_0_FAR_FROM_CLIPSPACE(coord)) //unity_FogParams 定义在ShaderVariables // x = density / sqrt(ln(2)), useful for Exp2 mode // y = density / ln(2), useful for Exp mode // z = -1/(end-start), useful for Linear mode // w = end/(end-start), useful for Linear mode float4 unity_FogParams;
注意雾因子必须限定在[0,1]
return learp(unity_FogColor, color, saturate(unityFogFactor));
同时雾也不能影响Alpha值
color.rgb = learp(unity_FogColor.rgb, color.rgb, saturate(unityFogFactor));
图6 linear:standard vs. mine
图7 exp:standard vs. mine
图8 exp2:standard vs. mine
与Standard Shader不同的原因是计算fog坐标方法不同。虽然使用world-space视图距离是有意义的,但标准着色器使用裁剪空间深度值。因此视角不影响雾坐标。此外,在某些情况下,距离是受相机的近裁切面距离的影响,这将把雾推开一点。
图9 深度 (三角) vs. 距离(园)
使用深度代替距离优点是:不必计算平方根,计算速度更快,适用于非真实渲染。缺点是:忽略视角,也即相机原点会影响雾密度,因为旋转时密度会改变。
图10 红到蓝旋转,深度改变密度
标签:颜色 app 计算 步骤 包含 inline else border mode
原文地址:https://www.cnblogs.com/baolong-chen/p/12902985.html