码迷,mamicode.com
首页 > 其他好文 > 详细

翻译14 Fog

时间:2020-05-17 01:16:57      阅读:102      评论:0      收藏:0      [点我收藏+]

标签:颜色   app   计算   步骤   包含   inline   else   border   mode   

应用雾到游戏对象
基于距离或深度的雾
支持deferred fog

1 Forward Fog

在14之前,一直假定着光线在真空中传播,在真空中可能是精确的。但是当光线穿过大气或水就不一样了,光线在击中物体表面时会发生被吸收、散射和反射。

一个精确的大气干扰光线渲染将需要及其昂贵的体积测量方法,那是大多数现代GPU负担不起的。相反,勉强采用一些常量雾参数近似模拟。

1.1 Standard Fog

Unity光照设置包含了场景雾设置选项,默认是不启用。启用后,默认是灰色雾。Unity自带的雾只适用于使用了Forward渲染路径的物体。若激活Deferred path,提示:

技术图片

图1 deferred 提示

技术图片

图2 不明显的雾

1.2 Linear Fog

图2不明显,是因为Fog color灰色雾将散射和反射更多的光线,吸收较少。把Fog Color改为纯黑色试试

技术图片

 技术图片

图3 linear fog

Linear Fog Mode:雾的浓度是随视距线性增长的,在视距开头正常显示,超过这个距离就只有雾的颜色可见。

线性雾公式:

技术图片

c 是雾坐标;
S 是视距起始距离;
E 是视距终止距离;
f值 被限定在[0, 1]范围,被用在雾和物体着色之间插值。

最终计算在fragment color着色到物体对象上,雾不会影响到skybox

1.3 Exponential Fog

更接近真实感的雾

技术图片 

技术图片

图4 指数雾

指数雾公式:

技术图片技术图片

d 是fog的密度因子;
c 是距离因子

1.4 Exponential Squared Fog

技术图片

技术图片

图5 指数平方雾

指数平方雾公式:

技术图片 技术图片

1.5 Adding Fog

增加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;
View Code

注意雾因子必须限定在[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

1.6 Depth-Based Fog

与Standard Shader不同的原因是计算fog坐标方法不同。虽然使用world-space视图距离是有意义的,但标准着色器使用裁剪空间深度值。因此视角不影响雾坐标。此外,在某些情况下,距离是受相机的近裁切面距离的影响,这将把雾推开一点。

技术图片

图9 深度 (三角) vs. 距离(园)

使用深度代替距离优点是:不必计算平方根,计算速度更快,适用于非真实渲染。缺点是:忽略视角,也即相机原点会影响雾密度,因为旋转时密度会改变。

技术图片

图10 红到蓝旋转,深度改变密度



1.7 Depth or Distance

1.8 Disabling Fog

1.9 Multiple Lights

2 Deferred Fog

2.1 Image Effects

2.2 Fog Shader

2.3 Depth-Based Fog

2.4 Fixing the Fog

2.5 Distance-Based Fog

2.6 Calculating Rays

2.7 Deriving Distances

2.8 Fogged Skybox

2.9 No Fog

翻译14 Fog

标签:颜色   app   计算   步骤   包含   inline   else   border   mode   

原文地址:https://www.cnblogs.com/baolong-chen/p/12902985.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!