声明变体
#pragma multi_compile_fog会产生三个变体:
FOG_LINEAR:线性雾FOG_EXP:指数雾FOG_EXP2:指数平方雾 需要确保项目设置了合理的雾效参数:Window > Rendering > Lighting Settings > Fog
实现算法
URP 封装
#pragma multi_compile_fog
struct Varyings
{
float fogFactor: TEXCOORD2;
}
Varyings vert (Attributes IN) {
Varyings OUT;
OUT.fogFactor = ComputeFogFactor(IN.positionCS.z); // 计算
return OUT;
}
half4 frag(Varyings IN): SV_TARGET {
half4 color = 1;
color.rgb = MixFog(color, IN.fogFactor); // 混合
return color;
}ComputeFogFactor():计算雾浓度系数MixFog:混合雾颜色
Built-In 封装
通用方法
#pragma multi_compile_fog
struct appdata
{
float vertex: POSITION;
}
struct v2f
{
float4 pos: SV_POSITION;
UNITY_FOG_COORDS(0)
}
v2f vert(appdata v) {
v2f o;
o.pos = UnityObjectClipPos(v.vertex);
UNITY_TRANSFER_FOG(o, o.pos);
}
fixed4 frag(v2f i): SV_Target {
fixed4 color = 1;
UNITY_APPLY_FOG(i.fogCoord, color);
}UNITY_FOG_COORDS(idx):自动定义变量fogCoord的宏,等价于float fogCoord: TEXCOORD##idxUNITY_TRANSFER_FOG(appdata, positionCS):计算雾浓度系数并赋值到fogCoordUNITY_APPLY_FOG(fogCoord, color):混合雾颜色
使用世界坐标优化
在通用方法中,宏UNITY_FOG_COORDS会自动定义一个float类型的变量用于单独存储雾浓度系数,这无疑是占用资源的。我们知道float4类型的世界坐标的w分量并无实际用处,我们可以使用其w分量存储雾浓度系数,Unity中也提供了相关的宏。当然,这种方法仅适用于原本就需要使用世界坐标的渲染逻辑,而并非为了使用该方法平白无故地创造一个无用变量。
#pragma multi_compile_fog
struct appdata
{
float vertex: POSITION;
}
struct v2f
{
float4 pos: SV_POSITION;
float4 worldPos: TEXCOORD0;
}
v2f vert(appdata v) {
v2f o;
o.pos = UnityObjectClipPos(v.vertex);
o.worldPos = mul(unity_ObjectToWorld, v.vertex);
UNITY_TRANSFER_COMBINED_WITH_WORLD_FOG(o, o.worldPos);
}
fixed4 frag(v2f i): SV_Target {
fixed4 color = 1;
UNITY_APPLY_FOG(i.worldPos.w, color);
}手动实现
#pragma multi_compile_fog
struct v2f
{
float4 vertex : SV_POSITION;
float fogFactor:TEXCOORD0;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
float3 worldPos = mul(unity_ObjectToWorld, v.vertex); // 世界坐标
float z = length(_WorldSpaceCameraPos - worldPos); // 深度
#if defined(FOG_LINEAR) // 线性雾
o.fogFactor = z * unity_FogParams.z + unity_FogParams.w;
#elif defined(FOG_EXP) // 指数雾
o.fogFactor = exp2(-unity_FogParams.y * z);
#elif defined(FOG_EXP2) // 指数平方雾
float density = unity_FogParams.x * z;
o.fogFactor = exp2(-density * density);
#endif
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 color = 1;
#if defined(FOG_LINEAR) || defined(FOG_EXP) || defined(FOG_EXP2)
color = lerp(unity_FogColor, color, i.fogFactor);
#endif
return color;
}- 原理:->
unity_FogParams->
半透明材质问题
- Unity🔺