1. 程式人生 > 其它 >unity之背景高斯模糊

unity之背景高斯模糊

 1 local RenderTexture = CS.UnityEngine.RenderTexture
 2 local Rect =CS.UnityEngine.Rect
 3 local Screen =CS.UnityEngine.Screen
 4 local Texture2D = CS.UnityEngine.Texture2D
 5 local TextureFormat = CS.UnityEngine.TextureFormat
 6 local GaussianBlurBg = {}
 7 
 8 --主要思路:從螢幕讀取畫素 儲存在texture2d中
 9 --核心API:texture2d:ReadPixels(renderWidth, renderHeight, TextureFormat.RGB24, false, true)
10 11 ---輸出圖片 12 GaussianBlurBg.ExportTexture = function() 13 local cameraArr = GaussianBlurBg.GetCurrCamera() 14 local renderWidth,renderHeight = GaussianBlurBg.DrawingSize() 15 return GaussianBlurBg.ScreenCapture(cameraArr,renderWidth,renderHeight) 16 end 17 18 --獲取相機組 19 GaussianBlurBg.GetCurrCamera = function
() 20 local cameraArr = {} 21 local UIMgrIns = UIManager:Instance() 22 table.insert(cameraArr, UIMgrIns.UICamera) 23 table.insert(cameraArr, UIMgrIns.MainCamera) 24 return cameraArr 25 end 26 27 --算出渲染大小 28 GaussianBlurBg.DrawingSize = function() 29 --高寬比 30 local proportion = (Screen.height * 1.0
/ Screen.width) 31 --乘以0.1 是為了更小 32 local renderWidth = math.min(100,math.ceil(Screen.width * 0.1)) 33 --乘以高寬比是為了與原比例一致 34 local renderHeight = math.ceil(renderWidth * proportion) 35 return renderWidth,renderHeight 36 end 37 38 --螢幕讀取畫素渲染到一張圖片上 39 GaussianBlurBg.ScreenCapture = function(cameraArr,renderWidth,renderHeight) 40 if cameraArr == nil or #cameraArr == nil then return nil end 41 local camerList,cameraMap,oldTargetTexture = {},{},{} 42 for _, v in pairs(cameraArr) do 43 if not IsNull(v) and cameraMap[v] == nil then 44 cameraMap[v] = v 45 table.insert(camerList, v) 46 end 47 end 48 if #camerList <= 0 then return nil end 49 if type(renderWidth) ~= "number" or renderWidth <= 0 then renderWidth = 100 end 50 if type(renderHeight) ~= "number" or renderHeight <= 0 then renderHeight = 100 end 51 local renderTex = RenderTexture.GetTemporary(renderWidth, renderHeight, 0) 52 --快取原先的渲染相機及渲染目標 53 for _, came in pairs(camerList) do 54 if not IsNull(came) and came.gameObject.activeSelf then 55 table.insert(oldTargetTexture, { came = came, targetTexture = came.targetTexture }) 56 came.targetTexture = renderTex 57 came:Render() 58 end 59 end 60 RenderTexture.active = renderTex 61 local _tex = Texture2D(renderWidth, renderHeight, TextureFormat.RGB24, false, true) 62 _tex:ReadPixels(Rect(0, 0, renderWidth, renderHeight), 0, 0) 63 _tex:Apply(false, false) 64 --要還原 否則丟失渲染目標 65 for _, v in pairs(oldTargetTexture) do 66 if not IsNull(v.came) then 67 v.came.targetTexture = v.targetTexture 68 end 69 end 70 RenderTexture.active = nil 71 RenderTexture.ReleaseTemporary(renderTex) 72 return _tex 73 end 74 75 exports.GaussianBlurBg = GaussianBlurBg 76 return GaussianBlurBg

 

模糊 shader

  1 Shader "Effect/ImageBlur"
  2 {
  3     Properties
  4     {
  5         _MainTex("Texture", 2D) = "white" {}
  6         //ugui mask
  7         [HideInInspector]_StencilComp("Stencil Comparison", Float) = 8
  8         [HideInInspector]_Stencil("Stencil ID", Float) = 0
  9         [HideInInspector]_StencilOp("Stencil Operation", Float) = 0
 10         [HideInInspector]_StencilWriteMask("Stencil Write Mask", Float) = 255
 11         [HideInInspector]_StencilReadMask("Stencil Read Mask", Float) = 255
 12         [HideInInspector]_ColorMask("Color Mask", Float) = 15
 13         //================================================================================
 14         _BlurSize("Blur Size", Float) = 2
 15         _Brightness("Brightness", Float) = 1    //調整亮度
 16         _Saturation("Saturation", Float) = 1    //調整飽和度
 17         _Contrast("Contrast", Float) = 1        //調整對比度
 18     }
 19 
 20         CGINCLUDE
 21 
 22 #include "UnityCG.cginc"
 23 
 24         sampler2D _MainTex;
 25         uniform half4 _MainTex_TexelSize;
 26         uniform float _BlurSize;
 27         half _Brightness;
 28         half _Saturation;
 29         half _Contrast;
 30 
 31         static const half weight[4] = { 0.0205, 0.0855, 0.232, 0.324 };
 32         static const half4 coordOffset = half4(1.0h, 1.0h, -1.0h, -1.0h);
 33 
 34         struct appdata_t
 35         {
 36             float4 vertex   : POSITION;
 37             float4 color    : COLOR;
 38             float2 texcoord : TEXCOORD0;
 39         };
 40 
 41         struct v2f_blurSGX
 42         {
 43             float4 pos:SV_POSITION;
 44             half2 uv:TEXCOORD0;
 45             float4 color    : COLOR;
 46             half4 blurFactor:TEXCOORD1;
 47         };
 48 
 49         v2f_blurSGX vert_BlurHorizontal(appdata_t v)
 50         {
 51             v2f_blurSGX o;
 52             o.pos = UnityObjectToClipPos(v.vertex);
 53             o.uv = v.texcoord.xy;
 54             o.blurFactor.xy = _MainTex_TexelSize.xy * 2 * _BlurSize;
 55             o.color = v.color;
 56             return o;
 57         }
 58 
 59 
 60         fixed4 Tex2DBlurring(sampler2D tex, half2 texcood, half2 blur)
 61         {
 62             //快速模糊
 63             //const int KERNEL_SIZE = 3;
 64             //const float KERNEL_[3] = { 0.4566, 1.0, 0.4566 };
 65 
 66             //中等模糊
 67             //const int KERNEL_SIZE = 5;
 68             //const float KERNEL_[5] = { 0.2486, 0.7046, 1.0, 0.7046, 0.2486 };
 69 
 70             //高階模糊
 71             const int KERNEL_SIZE = 7;
 72             const float KERNEL_[7] = { 0.1719, 0.4566, 0.8204, 1.0, 0.8204, 0.4566, 0.1719 };
 73             float4 o = 0;
 74             float sum = 0;
 75             float2 shift = 0;
 76             for (int x = 0; x < KERNEL_SIZE; x++)
 77             {
 78                 shift.x = blur.x * (float(x) - KERNEL_SIZE / 2);
 79                 for (int y = 0; y < KERNEL_SIZE; y++)
 80                 {
 81                     shift.y = blur.y * (float(y) - KERNEL_SIZE / 2);
 82                     float2 uv = texcood + shift;
 83                     float weight = KERNEL_[x] * KERNEL_[y];
 84                     sum += weight;
 85                     uv.x = clamp(uv.x, 0.02, 0.98);
 86                     uv.y = clamp(uv.y, 0.02, 0.98);
 87                     o += tex2D(tex, uv) * weight;
 88                 }
 89             }
 90             fixed4 renderTex = (o / sum);
 91             //brigtness亮度直接乘以一個係數,也就是RGB整體縮放,調整亮度
 92             fixed3 finalColor = renderTex * _Brightness;
 93             //saturation飽和度:首先根據公式計算同等亮度情況下飽和度最低的值:
 94             fixed gray = 0.2125 * renderTex.r + 0.7154 * renderTex.g + 0.0721 * renderTex.b;
 95             fixed3 grayColor = fixed3(gray, gray, gray);
 96             //根據Saturation在飽和度最低的影象和原圖之間差值
 97             finalColor = lerp(grayColor, finalColor, _Saturation);
 98             //contrast對比度:首先計算對比度最低的值
 99             fixed3 avgColor = fixed3(0.5, 0.5, 0.5);
100             //根據Contrast在對比度最低的影象和原圖之間差值
101             finalColor = lerp(avgColor, finalColor, _Contrast);
102             //返回結果,alpha通道不變
103             return fixed4(finalColor, renderTex.a);
104         }
105         
106         fixed4 frag_Blur(v2f_blurSGX i) :SV_Target
107         {
108             fixed4 color = Tex2DBlurring(_MainTex,i.uv,i.blurFactor.xy);
109             color.a = i.color.a;
110             return color;
111         }
112 
113 
114             ENDCG
115 
116             SubShader
117         {
118             //ugui mask No culling or depth
119             Cull Off ZWrite Off
120                 Stencil
121             {
122                 Ref[_Stencil]
123                 Comp[_StencilComp]
124                 Pass[_StencilOp]
125                 ReadMask[_StencilReadMask]
126                 WriteMask[_StencilWriteMask]
127             }
128 
129                 Fog{ Mode Off }
130                 Blend SrcAlpha OneMinusSrcAlpha
131                 ColorMask[_ColorMask]
132 
133                 Pass
134             {
135                 CGPROGRAM
136     #pragma vertex vert_BlurHorizontal
137     #pragma fragment frag_Blur
138                 ENDCG
139             }
140         }
141 }

 

 

 

用法:

1.建立一個材質球 ,把 ImageBlur.shader 掛上

2.加一個Raw Image 元件,GaussianBlurBg.ExportTexture 獲取的值 賦值給 Raw Image的 tetxure 屬性

 

效果:

 

 

 

 

 

總結知識點:
1.CS.UnityEngine.RenderTexture.GetTemporary:系統api 獲取臨時渲染紋理
public static RenderTexture GetTemporary(int width, int height, int depthBuffer);
引數width、height 不能小於等於0
2.Camera.targetTexture 給攝像機設定渲染圖片
3.Camera:Render() 手動渲染攝像機
4.Texture2D
5.Texture2D:ReadPixels // ReadPixels 從螢幕讀取畫素儲存到紋理資料中
6.Texture2D:Apply() 對上述更改的應用
public void Apply([DefaultValue("true")] bool updateMipmaps, [DefaultValue("false")] bool makeNoLongerReadable);
7.Rendertexture的分配和銷燬上有一個地方需要注意:
如果頻繁的要new一個rt出來,不要直接new,而是使用RenderTexture提供的GetTemporary和ReleaseTemporary,
它將在內部維護一個池,反覆重用一些大小格式一樣的rt資源,因為讓GPU為你分配一個新的texture其實是要耗時間的。