找回密碼
 注冊帳號

掃一掃,訪問微社區

士郎 Unity Shader之磨砂玻璃與水霧玻璃效果

22
回復
2973
查看
打印 上一主題 下一主題
[ 復制鏈接 ]
9以壇為家
33145/50000
排名
1
昨日變化

8252

主題

8810

帖子

3萬

積分

Rank: 9Rank: 9Rank: 9

UID
1231
好友
186
蠻牛幣
227
威望
30
注冊時間
2013-7-29
在線時間
4217 小時
最后登錄
2019-11-20

活力之星原創精華達人突出貢獻獎財富之證游戲蠻牛QQ群會員蠻牛妹VIP

馬上注冊,結交更多好友,享用更多功能,讓你輕松玩轉社區。

您需要 登錄 才可以下載或查看,沒有帳號?注冊帳號

x





玻璃效果是游戲場景中常見的效果之一,除卻普通的透明玻璃外,磨砂玻璃也是較為常見的效果。玻璃與場景中的其他物體也會有交互,例如,浴室中的玻璃、雨天的窗戶會在水汽的作用下帶有一定差別的霧效。本文以Unity Frosted Glass項目與開源庫中相關項目為例,介紹磨砂玻璃的做法和在移動端運行的性能。


開源庫鏈接:https://lab.uwa4d.com/lab/5b5613a3d7f10a201fd80bbb


模糊效果

磨砂玻璃的效果特點是模糊與半透明,該項目通過自定義的卷積實現來達到模糊效果。具體代碼實現在FrostedGlass.shader中。
[AppleScript] 純文本查看 復制代碼
//vertex to fragment    
struct v2f {
  float4 pos : POSITION;
  float2 uv : TEXCOORD0;
  float4 uv01 : TEXCOORD1;
  float4 uv23 : TEXCOORD2;
  float4 uv45 : TEXCOORD3;
};

v2f vert (appdata_img v) {
  v2f o;
  o.pos = UnityObjectToClipPos(v.vertex);
  o.uv.xy = v.texcoord.xy;
  o.uv01 =  v.texcoord.xyxy + offsets.xyxy * float4(1,1, -1,-1);
  o.uv23 =  v.texcoord.xyxy + offsets.xyxy * float4(1,1, -1,-1) * 2.0;
  o.uv45 =  v.texcoord.xyxy + offsets.xyxy * float4(1,1, -1,-1) * 3.0;
  return o;
}


(頂點著色器及相關數據結構SeparableGlassBlur.shader)

offsets是一個float4類型的定值,表示偏移量。通過頂點著色器的運算,輸出的v2f結構體中,pos存儲了該頂點從Object Space轉換到相機裁剪空間中的齊次坐標。uv、uv01、uv23、uv45分別儲存了該頂點、偏移量為offsets的兩個頂點、偏移量為2*offsets的兩個頂點、偏移量為3*offsets的兩個頂點的uv坐標。
[AppleScript] 純文本查看 復制代碼
half4 frag (v2f i) : COLOR {
  half4 color = float4 (0,0,0,0);
  color += 0.40 * tex2D (_MainTex, i.uv);
  color += 0.15 * tex2D (_MainTex, i.uv01.xy);
  color += 0.15 * tex2D (_MainTex, i.uv01.zw);
  color += 0.10 * tex2D (_MainTex, i.uv23.xy);
  color += 0.10 * tex2D (_MainTex, i.uv23.zw);
  color += 0.05 * tex2D (_MainTex, i.uv45.xy);
  color += 0.05 * tex2D (_MainTex, i.uv45.zw);
  return color;
}


(片元著色器SeparableGlassBlur.shader)

該卷積核的一維權重分布如下表所示:



[AppleScript] 純文本查看 復制代碼
(進行濾波操作 CommandBufferBlur.cs)_CommandBuffer.SetGlobalVector("offsets", new Vector4(2.0f / sizes[i].x, 0, 0, 0));[/align]
[align=left]_CommandBuffer.Blit(blurredID, blurredID2, _Material);[/align]
[align=left]_CommandBuffer.SetGlobalVector("offsets", new Vector4(0, 2.0f / sizes[i].y, 0, 0));[/align]
[align=left]_CommandBuffer.Blit(blurredID2, blurredID, _Material);



對圖像使用水平方向一維卷積核與豎直方向一維卷積核進行兩次濾波得到最終的圖像。等同于如下圖所示的二維卷積核進行濾波:




(使用水平方向的一維卷積核對圖像進行濾波CommandBufferBlur.cs)


(兩次濾波后得到模糊效果)

卷積核的選擇有很多種,其中較為常用的有高斯模糊、kawase Blur,開源庫中有相關的項目實現了相關效果,例如:Blur for Unity、Gaussian Blur、Super Blur。

高斯模糊

這些模糊方式,所采用的卷積核各不相同,有興趣的讀者可以進行相關試驗。

捕捉屏幕紋理

實現模糊效果后,需要捕捉到玻璃后方的屏幕效果圖片交予模糊效果著色器進行處理。在Unity Shader中有一種特殊的Pass:GrabPass,可以很方便地獲取屏幕圖像。但這種方式開銷太大,并不適合在移動端運行。

該項目采取CommandBuffer來達到這一目的。可以節省開銷、提高性能。
[AppleScript] 純文本查看 復制代碼
//創建名為“Blur screen”的CommandBuffer
_CommandBuffer = new CommandBuffer();
_CommandBuffer.name = "Blur screen";


int screenCopyID = Shader.PropertyToID("_ScreenCopyTexture");
//新建一個臨時RenderTexture
_CommandBuffer.GetTemporaryRT(screenCopyID, -1, -1, 0, FilterMode.Bilinear, _TextureFormat);
//獲取當前屏幕圖像
_CommandBuffer.Blit(BuiltinRenderTextureType.CurrentActive, screenCopyID);
int blurredID = Shader.PropertyToID("_Grab" + i + "_Temp1");
int blurredID2 = Shader.PropertyToID("_Grab" + i + "_Temp2");
_CommandBuffer.GetTemporaryRT(blurredID, (int)sizes[i].x, (int)sizes[i].y, 0, FilterMode.Bilinear, _TextureFormat);
_CommandBuffer.GetTemporaryRT(blurredID2, (int)sizes[i].x, (int)sizes[i].y, 0, FilterMode.Bilinear, _TextureFormat);
_CommandBuffer.Blit(screenCopyID, blurredID);
_CommandBuffer.ReleaseTemporaryRT(screenCopyID);


(獲取屏幕圖像CommandBufferBlur.cs)

但此時獲取到的圖像是一整張屏幕圖象,而我們需要進行模糊處理的圖像,只有玻璃模型背后的圖像,這時我們需要在頂點著色器中對頂點進行處理。
[AppleScript] 純文本查看 復制代碼
v2f vert (appdata v)
{
  v2f o;
  o.vertex = UnityObjectToClipPos(v.vertex);
  //確保材質球中的縮放和偏移位置正確
  o.uvfrost = TRANSFORM_TEX(v.uv, _FrostTex);
  //獲得該頂點在屏幕圖象中正確的紋理坐標
  o.uvgrab = ComputeGrabScreenPos(o.vertex);
  return o;
}


Unity內置的ComputeGrabScreenPos函數,幫助我們完成了坐標轉換,根據o.uvgrab在屏幕圖像中采集到的圖像信息,便是玻璃模型背后的屏幕圖像:


[AppleScript] 純文本查看 復制代碼
half4 ref00=tex2Dproj(_GrabBlurTexture_0,i.uvgrab);


將CommandBuffer掛載到相機上,實現實時更新渲染。


[AppleScript] 純文本查看 復制代碼
_Camera.AddCommandBuffer(CameraEvent.BeforeForwardAlpha, _CommandBuffer);



(效果圖)

水霧玻璃

在磨砂玻璃的基礎上,進一步拓展其他的特殊效果。

浴室中的玻璃、雨天的窗戶會在水汽的作用下帶有一定差別的霧效。這種效果的特點除卻模糊與半透明外,還會有模糊程度的差別。
[AppleScript] 純文本查看 復制代碼
Vector2[] sizes = {
  new Vector2(Screen.width, Screen.height),
  new Vector2(Screen.width / 2, Screen.height / 2),
  new Vector2(Screen.width / 4, Screen.height / 4),
  new Vector2(Screen.width / 8, Screen.height / 8),
};


(定義不同大小的偏移量CommandBufferBlur.cs)

定義不同大小的偏移量,通過SeparableGlassBlur.shader的運算,得到四張模糊程度不同的屏幕圖像,由0~3模糊程度加深:
[AppleScript] 純文本查看 復制代碼
sampler2D _GrabBlurTexture_0;
        sampler2D _GrabBlurTexture_1;
        sampler2D _GrabBlurTexture_2;
        sampler2D _GrabBlurTexture_3;


制定采樣規則從這四張模糊程度不同的屏幕圖像中進行采集,為了讓過渡圓滑,使用lerp函數進行插值。加載一張效果灰度圖(_FrostTex),確定霧效差別的強度(_FrostIntensity):
[AppleScript] 純文本查看 復制代碼
fixed4 frag (v2f i) : SV_Target
{
  float surfSmooth = 1 - tex2D(_FrostTex, i.uvfrost)* _FrostIntensity;
  //如果x 值小于 a,則返回a;如果 x 值大于 b,返回b;否則,返回 x
  surfSmooth = clamp(0, 1, surfSmooth);
  half4 refraction;
  //二維紋理投影映射
  half4 ref00 = tex2Dproj(_GrabBlurTexture_0, i.uvgrab);
  half4 ref01 = tex2Dproj(_GrabBlurTexture_1, i.uvgrab);
  half4 ref02 = tex2Dproj(_GrabBlurTexture_2, i.uvgrab);
  half4 ref03 = tex2Dproj(_GrabBlurTexture_3, i.uvgrab);
  //進行平滑過渡
  float step00 = smoothstep(0.75, 1.00, surfSmooth);
  float step01 = smoothstep(0.5, 0.75, surfSmooth);
  float step02 = smoothstep(0.05, 0.5, surfSmooth);
  refraction = lerp(lerp(lerp(ref03, ref02, step02), ref01, step01), ref00, step00);               
  return refraction;
}


(片元著色器FrostedGlass.shader)

項目中以_FrostTex圖像中r值作為采樣依據。根據1-r值*_FrostIntensity得到的數值(surfSmooth)為權重,分別從上述四張模糊程度不同的屏幕圖像中進行采集,最后得到該頂點最終的顏色。

以下圖作為效果圖,驗證不同的surfSmooth大小,渲染得到不同的模糊程度:


(從左至右R值依次為:0,0.25,0.5,0.75,1)


(效果圖)

由此可以模擬出不同的水霧玻璃效果:


(有點臟的霧玻璃)


(覆蓋著一層小水珠)

性能測試(使用UWA GOT Online工具測評)

選擇低端機型紅米4x進行測試(不開啟多線程渲染):

使用水霧玻璃效果:



FPS均值為26幀:



Camera.Render函數耗時11ms左右開銷不大:



可以看到CPU等待GPU渲染完成時間較長,當前渲染壓力在GPU端:



可見實時抓取屏幕圖片并進行渲染操作在移動端開銷還是巨大的。該效果生成四張模糊效果圖片,每張圖片的生成通過了兩次SeparableGlassBlur.shader的計算。最終每個頂點在FrostedGlass.shader中進行運算。GPU計算量過大。

只使用磨砂玻璃效果時,紅米4xFPS均值為42幀左右。



此時只生成一張模糊效果圖片,該圖片的生成通過了兩次SeparableGlassBlur.shader的計算。相比較而言GPU端計算大幅減少,CPU等待時間縮短,性能提升明顯。


故而開發者在實現此效果時,需要在性能與效果之間平衡,盡可能減少計算量,例如可以使用3x3的卷積核,而不是5x5的,可以在采樣之前做判斷,減少采樣次數。

來源:UWA
回復

使用道具 舉報

7日久生情
3020/5000
排名
2230
昨日變化

1

主題

1971

帖子

3020

積分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
119154
好友
0
蠻牛幣
3495
威望
0
注冊時間
2015-8-21
在線時間
418 小時
最后登錄
2019-11-25
沙發
2019-5-29 13:14:42 只看該作者
謝謝樓主大大。
回復

使用道具 舉報

2初來乍到
102/150
排名
48141
昨日變化

3

主題

73

帖子

102

積分

Rank: 2Rank: 2

UID
116528
好友
0
蠻牛幣
97
威望
0
注冊時間
2015-8-4
在線時間
22 小時
最后登錄
2019-11-27
板凳
2019-5-29 14:21:17 只看該作者
感謝樓主分享哈,學些學習!
回復 支持 反對

使用道具 舉報

7日久生情
2437/5000
排名
1387
昨日變化

0

主題

749

帖子

2437

積分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
135463
好友
0
蠻牛幣
154
威望
0
注冊時間
2016-1-23
在線時間
797 小時
最后登錄
2019-12-10
地板
2019-5-29 14:53:39 只看該作者
發條橙更符合規范化風格很過分
回復 支持 反對

使用道具 舉報

4四處流浪
481/500
排名
10345
昨日變化

1

主題

221

帖子

481

積分

Rank: 4

UID
248391
好友
0
蠻牛幣
523
威望
0
注冊時間
2017-10-12
在線時間
149 小時
最后登錄
2019-12-5
5#
2019-5-29 14:56:00 只看該作者
可以可以,不覺名利
回復 支持 反對

使用道具 舉報

4四處流浪
440/500
排名
11820
昨日變化

0

主題

142

帖子

440

積分

Rank: 4

UID
269725
好友
0
蠻牛幣
669
威望
0
注冊時間
2018-2-27
在線時間
216 小時
最后登錄
2019-12-10
6#
2019-5-29 15:38:57 只看該作者
感謝樓主大大分享
回復 支持 反對

使用道具 舉報

7日久生情
2534/5000
排名
4094
昨日變化

0

主題

1753

帖子

2534

積分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
254705
好友
1
蠻牛幣
2274
威望
0
注冊時間
2017-11-16
在線時間
419 小時
最后登錄
2019-12-10
7#
2019-5-30 08:17:57 只看該作者
66666666666666666666666666666666
回復 支持 反對

使用道具 舉報

5熟悉之中
609/1000
排名
7021
昨日變化

3

主題

154

帖子

609

積分

Rank: 5Rank: 5

UID
293049
好友
2
蠻牛幣
2559
威望
0
注冊時間
2018-8-9
在線時間
264 小時
最后登錄
2019-12-10
8#
2019-5-30 08:24:14 只看該作者
哇哦,真的很棒!希望窩能早日全部看懂,只能看懂一部分
回復 支持 反對

使用道具 舉報

4四處流浪
407/500
排名
8825
昨日變化

0

主題

39

帖子

407

積分

Rank: 4

UID
307305
好友
0
蠻牛幣
1025
威望
0
注冊時間
2018-12-6
在線時間
234 小時
最后登錄
2019-12-10
9#
2019-5-30 08:25:03 只看該作者
謝謝分享
回復

使用道具 舉報

6蠻牛粉絲
1497/1500
排名
10820
昨日變化

3

主題

1171

帖子

1497

積分

Rank: 6Rank: 6Rank: 6

UID
310426
好友
0
蠻牛幣
2242
威望
0
注冊時間
2019-1-2
在線時間
227 小時
最后登錄
2019-12-10
10#
2019-5-30 09:04:49 只看該作者
Unity Shader之磨砂玻璃與水霧玻璃效果
回復 支持 反對

使用道具 舉報

5熟悉之中
638/1000
排名
13275
昨日變化

2

主題

230

帖子

638

積分

Rank: 5Rank: 5

UID
16650
好友
0
蠻牛幣
1023
威望
0
注冊時間
2014-3-6
在線時間
312 小時
最后登錄
2019-12-6
11#
2019-5-30 17:05:35 只看該作者
謝謝樓主分享.
回復

使用道具 舉報

6蠻牛粉絲
1497/1500
排名
10820
昨日變化

3

主題

1171

帖子

1497

積分

Rank: 6Rank: 6Rank: 6

UID
310426
好友
0
蠻牛幣
2242
威望
0
注冊時間
2019-1-2
在線時間
227 小時
最后登錄
2019-12-10
12#
2019-5-31 08:50:51 只看該作者
Unity Shader之磨砂玻璃與水霧玻璃效果
回復 支持 反對

使用道具 舉報

7日久生情
2534/5000
排名
4094
昨日變化

0

主題

1753

帖子

2534

積分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
254705
好友
1
蠻牛幣
2274
威望
0
注冊時間
2017-11-16
在線時間
419 小時
最后登錄
2019-12-10
13#
2019-5-31 13:34:59 只看該作者
666666666666666666666666666666
回復 支持 反對

使用道具 舉報

0

主題

7

帖子

7

積分

Rank: 1

UID
323611
好友
0
蠻牛幣
3
威望
0
注冊時間
2019-5-31
在線時間
0 小時
最后登錄
2019-5-31
14#
2019-5-31 16:55:21 只看該作者
學習學習
回復

使用道具 舉報

6蠻牛粉絲
1210/1500
排名
2066
昨日變化

0

主題

275

帖子

1210

積分

Rank: 6Rank: 6Rank: 6

UID
26073
好友
1
蠻牛幣
4742
威望
0
注冊時間
2014-5-21
在線時間
267 小時
最后登錄
2019-12-10
15#
2019-5-31 17:05:32 只看該作者
這得多厲害的人才搞得懂這些東西
回復 支持 反對

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 注冊帳號

本版積分規則

女校游泳队彩金 广东推倒胡麻将8局开挂 玩快手赚钱秘诀 海南彩票解梦查码 开手机游戏赚钱 手机玩地下城怎么赚钱 今天七星彩走势图 甘肃快三开奖历史结果 全天重庆彩在线计划 河北11选5彩票软件 音频处理 赚钱 南京电动车修理赚钱吗 花呗扫红包他怎么赚钱 排列3走势图彩宝网 江苏快三网赚群 篮彩胜分差玩法规则 有什么容易赚钱的手机项目