Unity Shader實現(xiàn)動態(tài)霧效果
更新時間:2020年04月28日 17:18:27 作者:ZzEeRO
這篇文章主要為大家詳細介紹了Unity Shader實現(xiàn)動態(tài)霧效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
Unity Shader學(xué)習(xí):動態(tài)霧,供大家參考,具體內(nèi)容如下
先將相機近裁面四個角向量傳給shader,再通過觀察空間下的深度值和相機位置算出像素在世界坐標(biāo)系的位置,通過世界空間高度值來設(shè)定霧的范圍和濃度,然后通過噪聲和uv偏移實現(xiàn)擾動效果。得到了類似寂靜嶺或惡靈附身1的效果。
C#部分:
using System.Collections; using System.Collections.Generic; using UnityEngine; [ExecuteInEditMode] public class RayMarchingCamera : MonoBehaviour { private Matrix4x4 frustumCorners = Matrix4x4.identity; public Material material; public Camera myCamera; public Transform cameraTransform; // Use this for initialization private void Start() { myCamera.depthTextureMode = DepthTextureMode.Depth; } private void OnRenderImage(RenderTexture source, RenderTexture destination) { //field of view float fov = myCamera.fieldOfView; //近裁面距離 float near = myCamera.nearClipPlane; //橫縱比 float aspect = myCamera.aspect; //近裁面一半的高度 float halfHeight = near * Mathf.Tan(fov * 0.5f * Mathf.Deg2Rad); //向上和向右的向量 Vector3 toRight = myCamera.transform.right * halfHeight * aspect; Vector3 toTop = myCamera.transform.up * halfHeight; //分別得到相機到近裁面四個角的向量 //depth/dist=near/|topLeft| //dist=depth*(|TL|/near) //scale=|TL|/near Vector3 topLeft = cameraTransform.forward * near + toTop - toRight; float scale = topLeft.magnitude / near; topLeft.Normalize(); topLeft *= scale; Vector3 topRight = cameraTransform.forward * near + toTop + toRight; topRight.Normalize(); topRight *= scale; Vector3 bottomLeft = cameraTransform.forward * near - toTop - toRight; bottomLeft.Normalize(); bottomLeft *= scale; Vector3 bottomRight = cameraTransform.forward * near - toTop + toRight; bottomRight.Normalize(); bottomRight *= scale; //給矩陣賦值 frustumCorners.SetRow(0, bottomLeft); frustumCorners.SetRow(1, bottomRight); frustumCorners.SetRow(2, topRight); frustumCorners.SetRow(3, topLeft); //將向量傳給定點著色器,將屏幕畫面?zhèn)鱾€shader material.SetMatrix("_FrustumCornorsRay", frustumCorners); material.SetTexture("_MainTex", source); Graphics.Blit(source, destination,material,0); } }
shader部分:
Shader "Unlit/Fog" { Properties { _MainTex ("Texture", 2D) = "white" {} _NoiseTex("NoiseTex",2D)="white"{} //霧起始高度 _FogStartHeight("FogStartHeight",float)=0.0 //霧終點高度 _FogEndHeight("FogEndHeight",float)=1.0 //霧x位移速度 _FogXSpeed("FogXSpeed",float)=0.1 //霧y位移速度 _FogYSpeed("FogYSpeed",float)=0.1 } SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" sampler2D _MainTex; sampler2D _NoiseTex; sampler2D _CameraDepthTexture; float _FogStartHeight; float _FogEndHeight; float _FogXSpeed; float _FogYSpeed; //獲得相機近裁面四個角向量 float4x4 _FrustumCornorsRay; struct a2v{ float4 vertex:POSITION; float2 uv:TEXCOORD0; }; struct v2f{ float4 pos:SV_POSITION; float2 uv:TEXCOORD0; float4 interpolatedRay:TEXCOORD1; }; v2f vert(a2v v){ v2f o; o.pos=UnityObjectToClipPos(v.vertex); o.uv=v.uv; int index=0; if (v.uv.x<0.5&&v.uv.y<0.5) { index = 0; } else if (v.uv.x>0.5&&v.uv.y<0.5) { index = 1; } else if (v.uv.x>0.5&&v.uv.y>0.5) { index = 2; } else { index = 3; } //安排uv4個角對應(yīng)四個角向量 o.interpolatedRay = _FrustumCornorsRay[index]; return o; } float4 frag(v2f i):SV_Target{ //觀察空間下的線性深度值 float linearDepth=LinearEyeDepth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,i.uv)); //像素世界坐標(biāo)=世界空間相機位置+像素相對相機距離 float3 worldPos=_WorldSpaceCameraPos+linearDepth*i.interpolatedRay.xyz; float speedX=_Time.y*_FogXSpeed; float speedY=_Time.y*_FogYSpeed; float noise=tex2D(_NoiseTex,i.uv+float2(speedX,speedY)); //讓噪聲圖向黑色靠攏,黑白差距不要太大 noise=pow(noise,0.5); //霧濃度=世界高度/指定范圍 float fogDensity=(_FogEndHeight-worldPos.y)/(_FogEndHeight-_FogStartHeight); fogDensity=smoothstep(0.0,1.0,fogDensity*noise); float4 color=tex2D(_MainTex,i.uv); //根據(jù)霧濃度混合場景和霧顏色 color.rgb=lerp(color.rgb,float3(0.5,0.5,0.5),fogDensity); return color; } ENDCG } } }
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Unity中的PostProcessScene實用案例深入解析
這篇文章主要為大家介紹了Unity中的PostProcessScene實用案例深入解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-05-05C# List 并發(fā)丟數(shù)據(jù)問題原因及解決方案
這篇文章主要介紹了C# List 并發(fā)丟數(shù)據(jù)問題原因及解決方案,幫助大家更好的理解和使用c#,感興趣的朋友可以了解下2021-02-02unity 如何獲取Text組件里text內(nèi)容的長度
這篇文章主要介紹了unity 獲取Text組件里text內(nèi)容的長度操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-04-04