文章目录
- 前言
- 一、在片元着色器中使用如下公式计算
- `最终的颜色 = lerp(雾效颜色,物体颜色,雾效混合因子)`
- 1、获取雾效颜色
- 2、物体的颜色一般通过纹理采样得到,此处用 1 代替测试
- 3、获取 雾效混合因子(由 雾的距离 和 雾的浓度决定)
- 二、在顶点着色器中,计算不同类型的雾效混合因子(在顶点着色器计算节省性能)
- Unity预定义好方便我们计算的四维变量 unity_FogParams
- 1、计算线性雾的雾效混合因子
- 2、计算指数雾1 的雾效混合因子
- 3、计算指数雾2 的雾效混合因子
- 三、最终测试代码
前言
Unity中Shader雾效的实现方法一,按照之前的公式, 我们自己来实现一下
- Unity中Shader雾效的原理
基于上一篇文章继续:
- Unity中Shader的雾效
一、在片元着色器中使用如下公式计算
最终的颜色 = lerp(雾效颜色,物体颜色,雾效混合因子)
不管是什么类型的雾,这个雾效的公式都是统一的
1、获取雾效颜色
unity_FogColor
2、物体的颜色一般通过纹理采样得到,此处用 1 代替测试
3、获取 雾效混合因子(由 雾的距离 和 雾的浓度决定)
雾效混合因子是由,之前的三个雾效衰减公式计算得到的
- Unity中Shader雾效的原理
因为在片元着色器中计算雾效需要使用该因子
所以在 v2f 中定义一个 TEXCOORD 类型的 float 变量 fogFactor
float fogFactor : TEXCOORD1;
二、在顶点着色器中,计算不同类型的雾效混合因子(在顶点着色器计算节省性能)
Unity预定义好方便我们计算的四维变量 unity_FogParams
1、计算线性雾的雾效混合因子
- 获取 z :这个z是摄像机到物体的距离
z = (用摄像机的世界坐标 - 顶点的世界坐标)的 模长
计算需要准备:
摄像机的世界坐标:_WorldSpaceCameraPos
顶点的世界坐标:mul(unity_ObjectToWorld,v.vertex)
float z = length(_WorldSpaceCameraPos - worldPos);
- 获取 start 和 end
上面的公式可以等价为:
fogFactor
= (end - z) / (end - start)
= (end / (end - start)) + z * (-1 / (end - start))
使用Unity预定义的公式后:
= unity_FogParams.w + z * unity_FogParams.z ;
//(end - z) / (end - start)= (end / (end - start)) + z * (-1 / (end - start))
o.fogFactor = z * unity_FogParams.z + unity_FogParams.w;
效果:
2、计算指数雾1 的雾效混合因子
fogFactor
= exp2(-density * z)
使用Unity预定义的公式后:
= exp2(-unity_FogParams.y * z)
//exp2(-density * z)
o.fogFactor = exp2(-unity_FogParams.y * z);
效果:
3、计算指数雾2 的雾效混合因子
fogFactor
= exp2(-(density * z)^2)
使用Unity预定义的公式后:
= exp2(-(unity_FogParams.x * z)^2)
//exp2(-(density * z)^2)
float density = unity_FogParams.x * z;
o.fogFactor = exp2(-density * density);
效果:
三、最终测试代码
//unity的雾效
//雾效的实现方法一
Shader "MyShader/P1_9_3"
{SubShader{Tags { "RenderType"="Opaque" }Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#pragma multi_compile_fog#include "UnityCG.cginc"struct appdata{float4 vertex : POSITION;};struct v2f{float4 vertex : SV_POSITION;float fogFactor : TEXCOORD1;};v2f vert (appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);float4 worldPos = mul(unity_ObjectToWorld,v.vertex);float z = length(_WorldSpaceCameraPos - worldPos);#if defined(FOG_LINEAR)//(end - z) / (end - start)= (end / (end - start)) + z * (-1 / (end - start))o.fogFactor = z * unity_FogParams.z + unity_FogParams.w;#elif defined(FOG_EXP)//exp2(-density * z)o.fogFactor = exp2(-unity_FogParams.y * z);#elif defined(FOG_EXP2)//exp2(-(density * z)^2)float density = unity_FogParams.x * z;o.fogFactor = exp2(-density * density);#endifreturn o;}fixed4 frag (v2f i) : SV_Target{fixed4 c = 0;#if defined(FOG_LINEAR) || defined(FOG_EXP) || defined(FOG_EXP2)c = lerp(unity_FogColor,c,i.fogFactor);#endifreturn c;}ENDCG}}
}