这里使用一种更高效地从深度纹理中重建世界坐标的方法。
首先计算摄像机的视锥体的四条射线向量进行线性插值,插值后的值便是该像素在世界空间坐标下到摄像机的方向。
然后通过与深度值相乘即可得到摄像机位置到该像素的向量,加上摄像机的位置则是该像素在世界空间中的位置。
转载请注明出处:https://www.cnblogs.com/jietian331/p/9443343.html
c#代码:
1 using UnityEngine; 2 3 public class HighFog2 : PostEffectRenderer 4 { 5 [SerializeField] 6 Color m_fogColor = Color.white; 7 [Range(0f, 1f)] 8 [SerializeField] 9 float m_fogDensity = 0.9f; 10 [SerializeField] 11 float m_fogPosY = 0.1f; 12 [SerializeField] 13 float m_fogDisappearHeight = 8; 14 15 16 protected override string ShaderName 17 { 18 get { return "Custom/Study/HighFog2"; } 19 } 20 21 protected override void OnRenderImage(RenderTexture src, RenderTexture dest) 22 { 23 float fov = base.SelfCamera.fieldOfView; 24 float near = base.SelfCamera.nearClipPlane; 25 Transform camT = base.SelfCamera.transform; 26 27 float halfFOV = fov * Mathf.PI / 360f; 28 float toTopDis = near * Mathf.Tan(halfFOV); 29 float toRightDis = toTopDis * (Screen.width / Screen.height); 30 Vector3 toTop = camT.up * toTopDis; 31 Vector3 toRight = camT.right * toRightDis; 32 Vector3 toCenter = camT.forward * near; 33 Vector3 topLeft = (toCenter + toTop - toRight) / near; 34 Vector3 topRight = (toCenter + toTop + toRight) / near; 35 Vector3 bottomLeft = (toCenter - toTop - toRight) / near; 36 Vector3 bottomRight = (toCenter - toTop - toRight) / near; 37 38 Matrix4x4 matrix = Matrix4x4.identity; 39 matrix.SetRow(0, bottomLeft); 40 matrix.SetRow(1, bottomRight); 41 matrix.SetRow(2, topLeft); 42 matrix.SetRow(3, topRight); 43 44 base.Mat.SetMatrix("_CameraRays", matrix); 45 base.Mat.SetColor("_FogColor", m_fogColor); 46 base.Mat.SetFloat("_FogDensity", m_fogDensity); 47 base.Mat.SetFloat("_FogPosY", m_fogPosY); 48 base.Mat.SetFloat("_FogDisappearHeight", m_fogDisappearHeight); 49 base.OnRenderImage(src, dest); 50 } 51 }
shader:
1 Shader "Custom/Study/HighFog2" 2 { 3 Properties 4 { 5 _MainTex ("Texture", 2D) = "white" {} 6 } 7 8 SubShader 9 { 10 Pass 11 { 12 ZTest Always 13 ZWrite Off 14 Cull Off 15 16 CGPROGRAM 17 #pragma vertex vert 18 #pragma fragment frag 19 20 #include "UnityCG.cginc" 21 22 struct appdata 23 { 24 float4 vertex : POSITION; 25 float2 uv : TEXCOORD0; 26 }; 27 28 struct v2f 29 { 30 float2 uv : TEXCOORD0; 31 float4 vertex : SV_POSITION; 32 float3 ray : TEXCOORD1; 33 }; 34 35 sampler2D _MainTex; 36 sampler2D _CameraDepthTexture; 37 uniform float4x4 _CameraRays; 38 uniform float4 _FogColor; 39 uniform float _FogDensity; 40 uniform float _FogPosY; 41 uniform float _FogDisappearHeight; 42 43 v2f vert (appdata v) 44 { 45 v2f o; 46 o.vertex = UnityObjectToClipPos(v.vertex); 47 o.uv = v.uv; 48 49 int index; 50 if(v.vertex.x < 0.5 && v.vertex.y < 0.5) 51 { 52 index = 0; 53 } 54 else if(v.vertex.x > 0.5 && v.vertex.y < 0.5) 55 { 56 index = 1; 57 } 58 else if(v.vertex.x > 0.5 && v.vertex.y > 0.5) 59 { 60 index = 2; 61 } 62 else 63 { 64 index = 3; 65 } 66 o.ray = _CameraRays[index].xyz; 67 68 return o; 69 } 70 71 fixed4 frag (v2f i) : SV_Target 72 { 73 fixed4 col = tex2D(_MainTex, i.uv); 74 75 float d = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv)); 76 float3 worldPos = _WorldSpaceCameraPos + i.ray * d; 77 78 float fogWeight; 79 if(worldPos.y < _FogPosY) 80 { 81 fogWeight = 1; 82 } 83 else if(worldPos.y > _FogPosY + _FogDisappearHeight) 84 { 85 fogWeight = 0; 86 } 87 else 88 { 89 fogWeight = 1 - (worldPos.y - _FogPosY) / _FogDisappearHeight; 90 } 91 92 return lerp(col, _FogColor, fogWeight * _FogDensity); 93 } 94 95 ENDCG 96 } 97 } 98 99 Fallback Off 100 }
效果图如下: