Unity shader学习之屏幕后期处理效果之Bloom效果
Bloom特效是游戏中常见的一种屏幕效果。这种特效可以模拟真实摄像机的一种图像效果,它让画面中较亮的区域“扩散”到周围的区域中,造成一种朦胧的效果。
Bloom的实现原理很简单,首先根据一个阈值提取出图像中较亮的区域,把它们存储在一张渲染纹理中,再利用高斯模糊对这张渲染纹理进行模糊处理,模拟光线扩散的效果,最后再将其和原图像进行混合,得到最终的效果。
转载请注明出处:http://www.cnblogs.com/jietian331/p/7243444.html
如实现代码如下:
1 using UnityEngine; 2 3 public class BloomRenderer : PostEffectRenderer 4 { 5 [Range(0f, 4f)] 6 public float m_threshold = 0.4f; // 光阈值 7 [Range(1, 8)] 8 public int m_downSample = 2; // 降采样率 9 [Range(0, 4)] 10 public int m_iterations = 3; // 迭代次数 11 [Range(0.2f, 3f)] 12 public float m_blurSpread = 0.6f; // 模糊扩散量 13 14 protected override void OnRenderImage(RenderTexture src, RenderTexture dest) 15 { 16 int w = (int)(src.width / m_downSample); 17 int h = (int)(src.height / m_downSample); 18 19 RenderTexture buffer0 = RenderTexture.GetTemporary(w, h); 20 RenderTexture buffer1 = RenderTexture.GetTemporary(w, h); 21 buffer0.filterMode = FilterMode.Bilinear; 22 buffer1.filterMode = FilterMode.Bilinear; 23 24 // 提取亮光图 25 Mat.SetFloat("_Threshold", m_threshold); 26 Graphics.Blit(src, buffer0, Mat, 0); 27 28 // 将亮光图高斯模糊化 29 for (int i = 0; i < m_iterations; i++) 30 { 31 Mat.SetFloat("_BlurSpread", 1 + i * m_blurSpread); 32 33 Graphics.Blit(buffer0, buffer1, Mat, 1); 34 Graphics.Blit(buffer1, buffer0, Mat, 2); 35 } 36 37 // 将亮光图与原图混合 38 Mat.SetTexture("_Bloom", buffer0); 39 Graphics.Blit(src, dest, Mat, 3); 40 41 RenderTexture.ReleaseTemporary(buffer0); 42 RenderTexture.ReleaseTemporary(buffer1); 43 } 44 45 protected override string ShaderName 46 { 47 get { return "Custom/Bloom"; } 48 } 49 }
shader如下:
1 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' 2 3 Shader "Custom/Bloom" 4 { 5 Properties 6 { 7 _MainTex("Main Texture", 2D) = "white" {} 8 _Threshold("Threshold", float) = 0.6 9 _Bloom("Bloom", 2D) = "white" {} 10 } 11 12 SubShader 13 { 14 ZTest Always 15 ZWrite Off 16 Cull Off 17 18 Pass 19 { 20 CGPROGRAM 21 #pragma vertex vert 22 #pragma fragment frag 23 24 sampler2D _MainTex; 25 float _Threshold; 26 27 struct appdata 28 { 29 float4 vertex : POSITION; 30 float2 uv : TEXCOORD0; 31 }; 32 33 struct v2f 34 { 35 float4 pos : SV_POSITION; 36 float2 uv : TEXCOORD0; 37 }; 38 39 v2f vert(appdata v) 40 { 41 v2f o; 42 o.pos = UnityObjectToClipPos(v.vertex); 43 o.uv = v.uv; 44 return o; 45 } 46 47 fixed4 frag(v2f i) : SV_TARGET 48 { 49 fixed4 tex = tex2D(_MainTex, i.uv); 50 float lumiance = dot(fixed3(0.2125, 0.7154, 0.0721), tex.rgb); 51 return tex * saturate(lumiance - _Threshold); 52 } 53 54 ENDCG 55 } 56 57 UsePass "Custom/Gaussian Blur/HORIZONTAL" 58 UsePass "Custom/Gaussian Blur/VERTICAL" 59 60 Pass 61 { 62 CGPROGRAM 63 #pragma vertex vert 64 #pragma fragment frag 65 66 sampler2D _MainTex; 67 sampler2D _Bloom; 68 69 struct appdata 70 { 71 float4 vertex : POSITION; 72 float2 uv : TEXCOORD0; 73 }; 74 75 struct v2f 76 { 77 float4 pos : SV_POSITION; 78 float2 uv : TEXCOORD0; 79 }; 80 81 v2f vert(appdata v) 82 { 83 v2f o; 84 o.pos = UnityObjectToClipPos(v.vertex); 85 o.uv = v.uv; 86 return o; 87 } 88 89 fixed4 frag(v2f i) : SV_TARGET 90 { 91 fixed4 tex = tex2D(_MainTex, i.uv); 92 fixed4 bloom = tex2D(_Bloom, i.uv); 93 return fixed4(tex.rgb + bloom.rgb, tex.a); 94 } 95 96 ENDCG 97 } 98 } 99 100 Fallback Off 101 }
调整参数:
效果如下: