声明变体

HLSL
#pragma multi_compile_fog
点击展开查看更多

会产生三个变体:

  • FOG_LINEAR:线性雾
  • FOG_EXP:指数雾
  • FOG_EXP2:指数平方雾 需要确保项目设置了合理的雾效参数:Window > Rendering > Lighting Settings > Fog

实现算法

URP 封装

HLSL
#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 封装

通用方法

HLSL
#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##idx
  • UNITY_TRANSFER_FOG(appdata, positionCS):计算雾浓度系数并赋值到fogCoord
  • UNITY_APPLY_FOG(fogCoord, color):混合雾颜色

使用世界坐标优化

在通用方法中,宏UNITY_FOG_COORDS会自动定义一个float类型的变量用于单独存储雾浓度系数,这无疑是占用资源的。我们知道float4类型的世界坐标的w分量并无实际用处,我们可以使用其w分量存储雾浓度系数,Unity中也提供了相关的宏。当然,这种方法仅适用于原本就需要使用世界坐标的渲染逻辑,而并非为了使用该方法平白无故地创造一个无用变量。

HLSL
#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);
}
点击展开查看更多

手动实现

HLSL
#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🔺

版权声明

作者: Cheyne Xie

链接: https://chaim.eu.org/posts/33bfff6b/

许可证: CC BY-NC-SA 4.0

This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. Please attribute the source, use non-commercially, and maintain the same license.

开始搜索

输入关键词搜索文章内容

↑↓
ESC
⌘K 快捷键