后处理 - 简单雾效
基于高度的雾
原理
就是计算当前高度时雾的权重:fogWeight=(FogMaxY - CurY) / FogHeight,然后根据权重显示贴图颜色和雾颜色。所以,Y值越小雾越浓,Y值越大雾越淡。
usin UnityEngine; [RequireComponent(typeof(Camera))] public class PostEffectHeightFog : MonoBehaviour { private Camera m_Camera; private Material m_FogMat; private Matrix4x4 m_ClipToWorldMatrix; [Range(0.01f, 3)] public float m_FogStrength = 0.3f; public Color m_FogColor = Color.white; public float m_FogStart = 0; [Min(0.01f)] public float m_FogHeight = 1; void Start() { m_Camera = GetComponent<Camera>(); m_FogMat = new Material(Shader.Find("My/DepthTex/HeightFog")); var VPMatrix = m_Camera.projectionMatrix * m_Camera.worldToCameraMatrix; //叠加变换用矩阵左乘: World -> View -> Projection m_ClipToWorldMatrix = VPMatrix.inverse; //这边相机自身是不发生变换的 } private void OnRenderImage(RenderTexture src, RenderTexture dest) { m_FogMat.SetMatrix("_ClipToWorldMatrix", m_ClipToWorldMatrix); m_FogMat.SetFloat("_FogStrength", m_FogStrength); m_FogMat.SetColor("_FogColor", m_FogColor); m_FogMat.SetFloat("_FogStart", m_FogStart); m_FogMat.SetFloat("_FogHeight", m_FogHeight); Graphics.Blit(src, dest, m_FogMat); } }
用到的shader
Shader "My/DepthTex/HeightFog" { Properties { _MainTex("Texture", 2D) = "white" {} } SubShader { ZTest Always ZWrite Off Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float4 vertex : SV_POSITION; float2 uv : TEXCOORD0; float2 uv_depth : TEXCOORD1; }; sampler2D _CameraDepthTexture; //深度图 sampler2D _MainTex; //后处理提供的屏幕图 float4 _MainTex_TexelSize; float4x4 _ClipToWorldMatrix; //裁剪空间到世界空间转换矩阵, 需要c#部分提供 float _FogStrength; //雾强度 float4 _FogColor; //雾颜色 float _FogStart; //雾开始高度 float _FogHeight; //雾最大高度 v2f vert(appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = v.uv; o.uv_depth = v.uv; #if UNITY_UV_STARTS_AT_TOP if (_MainTex_TexelSize.y < 0) o.uv_depth.y = 1 - o.uv_depth.y; #endif return o; } fixed4 frag(v2f i) : SV_Target { float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv_depth); #if defined(UNITY_REVERSED_Z) depth = 1 - depth; #endif float4 ndcPos = float4(i.uv.x * 2 - 1, i.uv.y * 2 - 1, depth * 2 - 1, 1); //后处理的那张贴图就对应整个屏幕, 所以可以直接用像素创建ndc坐标 float4 worldPos = mul(_ClipToWorldMatrix, ndcPos); //ndcPos和clipPos只是差一个倍数(就是w分量) worldPos /= worldPos.w; //用世界坐标做相关处理 float fogWeight = (_FogStart + _FogHeight - worldPos.y) / _FogHeight; //越高雾浓度越低 fogWeight = saturate(fogWeight * _FogStrength); //限定在[0, 1] fixed4 c = tex2D(_MainTex, i.uv); c.rgb = lerp(c.rgb, _FogColor.rgb, fogWeight); return c; } ENDCG } } FallBack Off }
参考
UnityShader基础(八)——深度纹理与法线纹理_unity 深度纹理_implosion98的博客-CSDN博客
《Shader入门精要》13.2,13.3
分类:
shader / 后处理
, shader
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
2022-03-24 快速打开最近访问的预制体工具