雾效的实现方法(自定义方法与内置方法)
一、unity中如何开启雾效
二、自定义雾效的实现
1.雾效的实现原理:
使用lerp函数对雾效颜色和模型本身颜色进行插值混合;当模型顶点的深度值较小时,返回模型本身的颜色,当模型的深度值较大时,返回雾效颜色与模型颜色之间的混合值
先补充一下lerp函数的运算规则
lerp(A,B,alpha)
当alpha=0时,返回A ; 当alpha=1时,返回B ; 当alpha在0-1之间时返回A与B之间的混合值
所以我们使用 fogFactor(雾效混合因子)来表示alpha
unity中给了三种不同的雾效混合因子的计算来分别实现三种不同的雾效模型
z:表示物体的深度值
可以用 length(_WorldSpaceCameraPos-worldPos) 表示;(length()函数返回一个向量的模长)
float z=length(_WorldSpaceCameraPos-worldPos);
fixed4 c=1;
//自定义雾效方法
#if defined(FOG_LINEAR)|| defined(FOG_EXP)|| defined(FOG_EXP2)
c=lerp( unity_FogColor , c ,saturate(i.fogFactor) );
#endif
由上面片元着色器中写的雾效颜色的混合的公式可知,当saturate(i.fogFactor)=0时返回雾效的颜色,当saturate(i.fogFactor)=1时,返回模型的颜色
从上面三种雾效混合因子的计算公式也可知,当模型的深度值z越小时,saturate(i.fogFactor)(雾效混合因子)的值越趋近于1,模型大概为原本颜色,而当模型的深度值z越大时,saturate(i.fogFactor)(雾效混合因子)的值越趋近于0,模型呈现雾的颜色;对于线性的雾效混合因子fogFactor
2.自定义雾效的实现Shader
首先添加一个实现雾效所需要的变体
#pragma multi_compile_fog
其中包含三个变体:FOG_LINEAR(Linear)、FOG_EXP(Exponential)、FOG_EXP2(Exponential Squared)
这三个分别表示雾效不同运算模式
在顶点着色器的输出结构体中添加一个用于计算 fogFactor(雾效混合因子)的变量,因为这个变量要在顶点着色器中做运算并输出到片元着色器中
float fogFactor:TEXCOORD;
在顶点着色器中分别计算三种不同的雾效混合因子的值(用于后续lerp函数的计算)
(上述图片引用自其他博主)
//在顶点着色器中计算雾效混合因子可以使运算量相对减少
float3 worldPos=mul(unity_ObjectToWorld,v.vertex);
//深度值
float z=length(_WorldSpaceCameraPos-worldPos);
// float4 unity_FogParams;
// 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
//自定义雾效方法
#if defined(FOG_LINEAR)
// fogFactor=(end-z)/(end-start)=z*(-1/(end-start))+(end/(end-strat))
o.fogFactor=z*unity_FogParams.z+unity_FogParams.w;
#elif defined(FOG_EXP)
// fogFactor=e^-density*z
o.fogFactor=exp2(-unity_FogParams.y*z);
#elif defined(FOG_EXP2)
// fogFactor=e^-(density*z)^2
float density=unity_FogParams.x*z;
o.fogFactor=exp2(-density*density);
#endif
最后在片元着色器中实现雾效的混合效果
fixed4 c=1;
//自定义雾效方法
#if defined(FOG_LINEAR)|| defined(FOG_EXP)|| defined(FOG_EXP2)
c=lerp(unity_FogColor,c,saturate(i.fogFactor));
#endif
return c;
3.ShaderShader "unity/Fog"
{
Properties
{
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fog
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
};
struct v2f
{
float4 pos : SV_POSITION;
//自定义雾效方法
//因为fogFactor要作为顶点着色器的输出,所以要定义在v2f结构体中
float fogFactor:TEXCOORD;
//内置方法一
//相当于 float fogCoord:TEXCOORD;(雾效插值器)
// UNITY_FOG_COORDS(1)
// 内置方法二
// 无需定义额外的雾效插值器,可以把worldPos.w利用起来即可
// float4 worldPos:TEXCOORD1;
};
v2f vert (appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
//在顶点着色器中计算雾效混合因子可以使运算量相对减少
float3 worldPos=mul(unity_ObjectToWorld,v.vertex);
//深度值
float z=length(_WorldSpaceCameraPos-worldPos);
// float4 unity_FogParams;
// 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
//自定义雾效方法
#if defined(FOG_LINEAR)
// fogFactor=(end-z)/(end-start)=z*(-1/(end-start))+(end/(end-strat))
o.fogFactor=z*unity_FogParams.z+unity_FogParams.w;
#elif defined(FOG_EXP)
// fogFactor=e^-density*z
o.fogFactor=exp2(-unity_FogParams.y*z);
#elif defined(FOG_EXP2)
// fogFactor=e^-(density*z)^2
float density=unity_FogParams.x*z;
o.fogFactor=exp2(-density*density);
#endif
//内置方法一
//计算雾效混合因子
// UNITY_TRANSFER_FOG(o,o.pos);
// 返回值为o.fogCoord.x=unityFogFactor
//内置方法二
// o.worldPos.xyz=mul(unity_ObjectToWorld,v.vertex).xyz;
//#define UNITY_TRANSFER_FOG_COMBINED_WITH_WORLD_POS(o,outpos) UNITY_CALC_FOG_FACTOR((outpos).z); o.worldPos.w = unityFogFactor
// UNITY_TRANSFER_FOG_COMBINED_WITH_WORLD_POS(o,o.worldPos);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
// #if defined(FOG_LINEAR)
// return fixed4(1,0,0,1);
// #elif defined(FOG_EXP)
// return fixed4(0,1,0,1);
// #elif defined(FOG_EXP2)
// return fixed4(0,0,1,1);
// #else
// return fixed4(1,1,1,1);
// #endif
// return 1;
fixed4 c=1;
//自定义雾效方法
#if defined(FOG_LINEAR)|| defined(FOG_EXP)|| defined(FOG_EXP2)
c=lerp(unity_FogColor,c,saturate(i.fogFactor));
#endif
//内置方法一
// 插值计算
// UNITY_APPLY_FOG(i.fogCoord,c);
//内置方法二
// #define UNITY_EXTRACT_FOG_FROM_WORLD_POS(name) float _unity_fogCoord = name.worldPos.w
// UNITY_EXTRACT_FOG_FROM_WORLD_POS(i);
// #ifdef UNITY_PASS_FORWARDADD
// #define UNITY_APPLY_FOG(coord,col) UNITY_APPLY_FOG_COLOR(coord,col,fixed4(0,0,0,0))
// #else
// #define UNITY_APPLY_FOG(coord,col) UNITY_APPLY_FOG_COLOR(coord,col,unity_FogColor)
// #endif
// #define UNITY_APPLY_FOG_COLOR(coord,col,fogCol) UNITY_FOG_LERP_COLOR(col,fogCol,(coord).x)
// #define UNITY_FOG_LERP_COLOR(col,fogCol,fogFac) col.rgb = lerp((fogCol).rgb, (col).rgb, saturate(fogFac))
//颜色混合
// UNITY_APPLY_FOG(_unity_fogCoord,c);
// UNITY_APPLY_FOG(i.worldPos.w,c);
return c;
}
ENDCG
}
}
}
三、unity中内置的实现雾效方法
目前先实现方案一
首先还是先声明实现雾效所需要的内置变体
#pragma multi_compile_fog
在顶点着色器的输出结构体中定义雾效插值器(也就是用于计算雾效混合因子的变量fogFactor)
//相当于 float fogCoord:TEXCOORD;(雾效插值器)
UNITY_FOG_COORDS(1)
在顶点着色器中写用于计算雾效混合因子的式子
//计算雾效混合因子
UNITY_TRANSFER_FOG(o,o.pos);
// 返回值为o.fogCoord.x=unityFogFactor (unityFogFactor为上述式子计算所得的雾效混合因子值)
在片元着色器中写使雾效颜色混合的式子
// 插值计算
UNITY_APPLY_FOG(i.fogCoord,c);
(其中i.fogCoord=coord=unityFogFactor=fogFac)
相关知识
一种立体式雾喷水培花卉培育方法
【面向对象学习笔记day03】面向对象基础语法+内置函数+定义简单的类+创建对象+第一个面向对象程序+使用 Cat 类再创建一个对象+方法中的self参数+初始化方法+内置方法和属性+del+str
基因工程自定义蜜蜂属性方法
江苏园林雾景打造,震撼雾效,新颖水造雾,园林景观**
如何提高病虫害的防治效果,提高病虫害防效的方法
人工造雾的几种方法
一种气雾培绿色农用生物制品营养液的配制方法与流程
一种养生保健型植物配置方法与流程
夕雾花的养护要点及繁殖方法
园林雾森系统的基本工作原理和安装方法
网址: 雾效的实现方法(自定义方法与内置方法) https://www.huajiangbk.com/newsview1934689.html
上一篇: 汉中舞台雾效/舞台人造雾工程/景 |
下一篇: Unity shader中的雾效 |
推荐分享

- 1君子兰什么品种最名贵 十大名 4012
- 2世界上最名贵的10种兰花图片 3364
- 3花圈挽联怎么写? 3286
- 4迷信说家里不能放假花 家里摆 1878
- 5香山红叶什么时候红 1493
- 6花的意思,花的解释,花的拼音 1210
- 7教师节送什么花最合适 1167
- 8勿忘我花图片 1103
- 9橄榄枝的象征意义 1093
- 10洛阳的市花 1039