Unity3D舊電視濾鏡shader的實(shí)現(xiàn)示例
實(shí)現(xiàn)思路
既然是要實(shí)現(xiàn)舊電視的后處理效果,那么只要回憶一下那些古舊的電視的顯示效果然后進(jìn)行模擬就可以了。
1.首先那種大頭電視一般屏幕有一些曲率,并不是完全的一個(gè)平面,而且一般是向外凸起,這種凸起會(huì)造成中間的顯示區(qū)域會(huì)比原來更近一些,邊緣的顯示區(qū)域會(huì)比原來更遠(yuǎn)一些。這種效果我們直接用簡(jiǎn)單的二次函數(shù)來實(shí)現(xiàn)。
2.那種老舊電視會(huì)有不斷運(yùn)動(dòng)的噪聲,我們直接使用噪聲函數(shù)加上時(shí)間變量來實(shí)現(xiàn)。
3.屏幕上會(huì)有一些條紋效果,這種周期性的條紋效果一般用三角函數(shù)來實(shí)現(xiàn)。
當(dāng)然不可能模擬的完全準(zhǔn)確。。也沒有完全準(zhǔn)確一說。畢竟每個(gè)人對(duì)老電視的印象也是不同的,我這里也只是把我印象里的效果來實(shí)現(xiàn)一下,看起來差不多就行了。
實(shí)現(xiàn)代碼
首先實(shí)現(xiàn)第一點(diǎn),實(shí)現(xiàn)屏幕的曲率。
我們采用的方法是先計(jì)算該uv坐標(biāo)離(0.5,0.5)的距離,這個(gè)(0.5,0.5)的uv坐標(biāo)其實(shí)可以看成屏幕的中心點(diǎn)。計(jì)算出距離之后根據(jù)這個(gè)距離的大小來對(duì)uv進(jìn)行偏移,這其中用到了一個(gè)參數(shù)_Expand 為偏移的距離。
需要注意的是dot函數(shù)里填入兩次同樣的向量,算出的是向量模的平方而不是向量的模,不過這正是我們需要的,可以達(dá)到平方衰減的效果。
float d2 = dot(i.uv - half2(0.5, 0.5), i.uv - half2(0.5, 0.5)); half2 coord = (i.uv - half2(0.5, 0.5)) * (_Expand + d2 * (1 - _Expand)) + half2(0.5, 0.5);
接下來用這個(gè)偏移后的uv坐標(biāo)來對(duì)紋理進(jìn)行采樣。
half4 color = tex2D(_MainTex, coord);
調(diào)整參數(shù)后就會(huì)出現(xiàn)一些屏幕凸出的效果,當(dāng)然這里整個(gè)顯示范圍也變小了,這里是因?yàn)槿绻@示原范圍的話,需要的公式太復(fù)雜了,我們這里簡(jiǎn)單起見使用了簡(jiǎn)單的公式。
原圖
添加shader后
接下來添加噪聲,我們用一個(gè)變量控制噪聲強(qiáng)度,同時(shí)傳入時(shí)間變量來得到噪聲一直變化的效果。
float n = simpleNoise(coord.xy * _Time.x); half3 result = color.rgb * (1-_NoiseIntensity) + _NoiseIntensity * n;
而噪聲函數(shù)具體的實(shí)現(xiàn)如下
至于為什么這個(gè)函數(shù)就可以得到噪聲,其實(shí)也不好解釋。大致就是sin函數(shù)倍增之后加上取小數(shù)的frac函數(shù)可以近似得到一種隨機(jī)數(shù)的效果吧。
float simpleNoise(float2 uv) { return frac(sin(dot(uv, float2(12.9898, 78.233))) * 43758.5453); }
效果如下
最后添加上條紋效果
這個(gè)公式也不是什么經(jīng)過精心推導(dǎo)的公式,只是因?yàn)槲覀冃枰粋€(gè)周期出現(xiàn)的條紋效果,然后就想到用sin和cos函數(shù),然后隨便調(diào)整一下看起來有點(diǎn)樣子就可以了
half2 sc = half2((sin(coord.y * _StripeIntensity) + 1) / 2, (cos(coord.y * _StripeIntensity) + 1) / 2); result += color.rgb * sc.xyx;
添加條紋之后
效果2
完整代碼
c#代碼
namespace Colorful { using UnityEngine; [ExecuteInEditMode] public class OldTV : MonoBehaviour { public Shader shader; [Range(0, 1)] public float Expand = 0.7f; [Range(0, 1)] public float NoiseIntensity = 0.3f; public int StripeIntensity = 500; protected void OnRenderImage(RenderTexture source, RenderTexture destination) { Material material = new Material(shader); material.SetFloat("_Expand", Expand); material.SetFloat("_NoiseIntensity", NoiseIntensity); material.SetInt("_StripeIntensity", StripeIntensity); Graphics.Blit(source, destination, material, 0); } } }
shader代碼
Shader "LX/OldTV" { Properties { _MainTex ("Base (RGB)", 2D) = "white" {} } CGINCLUDE #include "UnityCG.cginc" sampler2D _MainTex; float _Expand; float _NoiseIntensity; int _StripeIntensity; float simpleNoise(float2 uv) { return frac(sin(dot(uv, float2(12.9898, 78.233))) * 43758.5453); } half4 frag(v2f_img i) : SV_Target { float d2 = dot(i.uv - half2(0.5, 0.5), i.uv - half2(0.5, 0.5)); half2 coord = (i.uv - half2(0.5, 0.5)) * (_Expand + d2 * (1 - _Expand)) + half2(0.5, 0.5); half4 color = tex2D(_MainTex, coord); float n = simpleNoise(coord.xy * _Time.x); half3 result = color.rgb * (1-_NoiseIntensity) + _NoiseIntensity * n; half2 sc = half2((sin(coord.y * _StripeIntensity) + 1) / 2, (cos(coord.y * _StripeIntensity) + 1) / 2); result += color.rgb * sc.xyx; return half4(result, color.a); } ENDCG SubShader { ZTest Always Cull Off ZWrite Off Fog { Mode off } Pass { CGPROGRAM #pragma vertex vert_img #pragma fragment frag ENDCG } } FallBack off }
另外代碼也傳到github倉(cāng)庫(kù)里了,大家也可以關(guān)注一下哦~
我的github
到此這篇關(guān)于Unity3D舊電視濾鏡shader的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)Unity3D舊電視濾鏡shader內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Unity 如何通過反射給gameObject添加組件
- Unity實(shí)現(xiàn)模型點(diǎn)擊事件的方法
- 詳解Unity使用ParticleSystem粒子系統(tǒng)模擬藥水在血管中流動(dòng)(粒子碰撞)
- Unity之跑馬燈抽獎(jiǎng)效果單抽與連抽(附demo)
- Unity實(shí)現(xiàn)老虎機(jī)滾動(dòng)抽獎(jiǎng)效果的示例代碼
- Unity給物體添加多個(gè)Tag的實(shí)現(xiàn)
- Unity實(shí)現(xiàn)3D射箭小游戲
- Unity實(shí)現(xiàn)瞄準(zhǔn)鏡效果
- 詳解Unity入門之GameObject
相關(guān)文章
C#Js時(shí)間格式化問題簡(jiǎn)單實(shí)例
這篇文章介紹了C#Js時(shí)間格式化問題簡(jiǎn)單實(shí)例,有需要的朋友可以參考一下2013-10-10C#中FlagsAttribute屬性在enum中的應(yīng)用詳解
這篇文章主要介紹了C#中FlagsAttribute屬性在enum中的應(yīng)用詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-10-10如何在C# 中查找或結(jié)束程序域中的主、子進(jìn)程
這篇文章主要介紹了如何在C# 中查找或結(jié)束程序域中的主、子進(jìn)程,幫助大家更好的理解和使用c#編程語言,感興趣的朋友可以了解下2020-11-11