开启辅助访问
 找回密码
 注册帐号

扫一扫,访问微社区

开发者专栏

关注:2067

当前位置:游戏蛮牛 技术专区 开发者专栏

__________________________________________________________________________________
开发者干货区版块规则:

  1、文章必须是图文形式。(至少2幅图)
      2、文章字数必须保持在1500字节以上。(编辑器右下角有字数检查)
      3、本版块只支持在游戏蛮牛原创首发,不支持转载。
      4、本版块回复不得无意义,如:顶、呵呵、不错......【真的会扣分的哦】
      5、......
__________________________________________________________________________________
查看: 1136|回复: 21

[bxh883] Shader Playground:Unity UGUI模糊贴图纹理效果实现

[复制链接]  [移动端链接]
排名
942
昨日变化
3

4

主题

71

帖子

1320

积分

Rank: 9Rank: 9Rank: 9

UID
3876
好友
0
蛮牛币
2785
威望
0
注册时间
2013-9-14
在线时间
293 小时
最后登录
2018-1-5

专栏作家

发表于 2017-11-5 21:35:06 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?注册帐号

x
本帖最后由 bxh883 于 2017-11-5 21:42 编辑

效果预览

这是一个简单的线性模糊的效果。不用RenderTexture。
一个shader,一个脚本,一个材质球就能快速实现。
实现思路
要达到这个效果,分两步实现,
  • 用Unity ShaderLab里的GrabPass来抓取屏幕像素
  • 重新计算并修改MainTeture的UV,达到只模糊RawImage的Rect范围内的图像。
GrabPass
下面是来自.4beta官方文档对GrabPass的描述:
GrabPass is a special passtype - it grabs the contents of the screen where the object is about to be drawn into a texture.
This texture can be used in subsequent passes to do advanced image based effects.
GrabPass可以把屏幕内容抓取到一个贴图纹理里,然后这个贴图纹理可以在之后的pass中使用。
他的用法不难,下面是官方给的的例子:
[AppleScript] 纯文本查看 复制代码
Shader "GrabPassInvert"
{
    SubShader
    {
        // Draw ourselves after all opaque geometry
        Tags { "Queue" = "Transparent" }

        // Grab the screen behind the object into _GrabTexture
        GrabPass { }

        // Render the object with the texture generated above, and invert the colors
        Pass
        {
            SetTexture [_GrabTexture] { combine one-texture }
        }
    }
}

实际这是一个Pass,可以抓取到屏幕内容。
直接只用GrabPass{}后,会把内容存储在默认的变量_GrabTexture中
如果想要将内容存放在另外的变量,可以用GrabPass{“TextureName”}
比如我们的变量是_MyGrabTexture这样官方的例子就变成了这样:
[AppleScript] 纯文本查看 复制代码
Shader "GrabPassInvert"
{
    SubShader
    {
        // Draw ourselves after all opaque geometry
        Tags { "Queue" = "Transparent" }

        // Grab the screen behind the object into _MyGrabTexture
        GrabPass { "_MyGrabTexture" }

        // Render the object with the texture generated above, and invert the colors
        Pass
        {
            SetTexture [_MyGrabTexture] { combine one-texture }
        }
    }
}
重新计算TextureUV
由于GrabPass抓取的是整个屏幕所有的内容,那我们可以通过改变纹理的UV就可以实现将屏幕对应区域的内容进行显示。
UV的坐标系原点屏幕左下
在UGUI中,RectTransform.rect.center的值是当前rect中心的点的坐标,但是他的坐标系的原点RectTransform的Pivot
因此我们要得到纹理的正确UV还需要计算出正确的坐标。
[C#] 纯文本查看 复制代码
using UnityEngine;
using UnityEngine.UI;

[RequireComponent(typeof(RawImage))]
public class BlurTexture : MonoBehaviour {

        private RawImage texture;
        /// <summary>
        /// texture所在的Root Canvas
        /// </summary>
        public Canvas rootCanvas;

        private void Awake(){
                texture = GetComponent<RawImage>();                
        }

        private void Update()
        {
                var screenWidth = rootCanvas.pixelRect.xMax / rootCanvas.scaleFactor;
                var screenHeight = rootCanvas.pixelRect.yMax / rootCanvas.scaleFactor;

                //得到一个从屏幕中心点到texture左下角的点的向量
                var bottomLeft = texture.rectTransform.anchoredPosition + texture.rectTransform.rect.min;

                var normalWidth = texture.rectTransform.rect.width / screenWidth;
                var normalHeight = texture.rectTransform.rect.height  / screenHeight;

                //uv的xy起点为(0,0),我们在计算坐下角的点时是从屏幕中心点开始,因此要加上0.5
                texture.uvRect = new Rect(0.5f + bottomLeft.x / screenWidth, 0.5f + bottomLeft.y / screenHeight, normalWidth, normalHeight);
        }
}

简单模糊
这里我实现的是相对简单,但是效果欠佳的线性模糊

[AppleScript] 纯文本查看 复制代码
Shader "ShaderPlayground/BlurTexture" {
        Properties{
                _MainTex("Base (RGB)", 2D) = "white" {}
                _BlurRadius("Raius", Range(0, 10)) = 0
        }
        SubShader{
                //UGUI的RenderQueue在Transparent
                Tags{ "Queue" = "Transparent"}

                GrabPass{}

                Pass{
                        CGPROGRAM
                        #pragma vertex vert
                        #pragma fragment frag

                        #include "UnityCG.cginc"

                        sampler2D _GrabTexture;
                        float2 _GrabTexture_TexelSize;
                        float _BlurRadius;

                        struct appdata {
                                float4 pos:POSITION;
                                float2 uv:TEXCOORD0;
                                float4 color:COLOR;
                        };

                        struct v2f {
                                float4 pos:SV_POSITION;
                                float2 uv:TEXCOORD0;
                                float2 uv1:TEXCOORD1;
                                float2 uv2:TEXCOORD2;
                                float2 uv3:TEXCOORD3;
                                float2 uv4:TEXCOORD4;
                                float4 color:COLOR;
                        };

                        v2f vert(appdata i) {
                                v2f o;
                                o.pos = mul(UNITY_MATRIX_MVP, i.pos);
                                o.uv = i.uv.xy;
#if UNITY_UV_STARTS_AT_TOP
                                if (_GrabTexture_TexelSize.y < 0)
                                        o.uv.y = 1 - o.uv.y;
#endif
                                o.uv1 = o.uv.xy + _BlurRadius * _GrabTexture_TexelSize * float2(1, 1);
                                o.uv2 = o.uv.xy + _BlurRadius * _GrabTexture_TexelSize * float2(-1, 1);
                                o.uv3 = o.uv.xy + _BlurRadius * _GrabTexture_TexelSize * float2(-1, -1);
                                o.uv4 = o.uv.xy + _BlurRadius * _GrabTexture_TexelSize * float2(1, -1);
                                o.color = i.color;
                                return o;
                        }

                        fixed4 frag(v2f i) : SV_Target{
                                fixed4 color = fixed4(0, 0, 0, 0);
                                color += tex2D(_GrabTexture, i.uv);
                                color += tex2D(_GrabTexture, i.uv1);
                                color += tex2D(_GrabTexture, i.uv2);
                                color += tex2D(_GrabTexture, i.uv3);
                                color += tex2D(_GrabTexture, i.uv4);
                                return color * 0.2 ;
                        }
                        ENDCG
                }
        }
}



Bingo
这样我们就能得到一个随意移动缩放的马赛克了!
后面我还想实现高斯模糊,动态模糊效果,还有移动端优化,让手机也能看到马赛克。
这是demo工程的地址ForkMeInGithub(https://github.com/aaBaO/DemoRepository)
有不对的地方欢迎大家指正和探讨~~
原文博客(https://aabao.github.io/UnityUGUI-Blur-Texture/)也希望大家多多讨论





回复

使用道具 举报

7日久生情
3781/5000
排名
4225
昨日变化
20

5

主题

3129

帖子

3781

积分

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

UID
209186
好友
5
蛮牛币
4542
威望
0
注册时间
2017-3-1
在线时间
363 小时
最后登录
2018-1-23
发表于 2017-11-6 09:10:12 | 显示全部楼层
谢谢分享

回复

使用道具 举报

4四处流浪
361/500
排名
6572
昨日变化
60

0

主题

46

帖子

361

积分

Rank: 4

UID
148615
好友
0
蛮牛币
511
威望
0
注册时间
2016-5-15
在线时间
153 小时
最后登录
2018-1-23
发表于 2017-11-6 09:14:49 | 显示全部楼层
谢谢分享

回复

使用道具 举报

5熟悉之中
840/1000
排名
3775
昨日变化
18

1

主题

326

帖子

840

积分

Rank: 5Rank: 5

UID
122160
好友
0
蛮牛币
1453
威望
0
注册时间
2015-9-10
在线时间
196 小时
最后登录
2018-1-23
发表于 2017-11-6 09:21:01 | 显示全部楼层
感谢分享

回复

使用道具 举报

7日久生情
1623/5000
排名
1324
昨日变化
1

1

主题

498

帖子

1623

积分

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

UID
56496
好友
0
蛮牛币
4732
威望
0
注册时间
2014-11-19
在线时间
360 小时
最后登录
2018-1-23
发表于 2017-11-6 09:48:09 | 显示全部楼层
高斯模糊,动态模糊效果,还有移动端优化

回复 支持 反对

使用道具 举报

5熟悉之中
887/1000
排名
3252
昨日变化
19

0

主题

215

帖子

887

积分

Rank: 5Rank: 5

UID
168312
好友
0
蛮牛币
1548
威望
0
注册时间
2016-9-13
在线时间
300 小时
最后登录
2018-1-23
发表于 2017-11-6 12:17:34 | 显示全部楼层
路过学习
[发帖际遇]: 1169895688 捡了钱没交公 蛮牛币 降了 1 . 幸运榜 / 衰神榜

回复

使用道具 举报

3偶尔光临
212/300
排名
10066
昨日变化
143

0

主题

86

帖子

212

积分

Rank: 3Rank: 3Rank: 3

UID
252416
好友
0
蛮牛币
150
威望
0
注册时间
2017-11-3
在线时间
42 小时
最后登录
2018-1-23
发表于 2017-11-6 13:28:31 | 显示全部楼层
学习到了

回复

使用道具 举报

0

主题

26

帖子

35

积分

Rank: 1

UID
111878
好友
0
蛮牛币
15
威望
0
注册时间
2015-7-3
在线时间
9 小时
最后登录
2017-11-28
发表于 2017-11-6 15:00:15 | 显示全部楼层
Grab Pass的性能是不是还不如Render Texture啊?
[发帖际遇]: 斯巴达 在网吧通宵,花了 3 蛮牛币. 幸运榜 / 衰神榜

回复 支持 反对

使用道具 举报

排名
942
昨日变化
3

4

主题

71

帖子

1320

积分

Rank: 9Rank: 9Rank: 9

UID
3876
好友
0
蛮牛币
2785
威望
0
注册时间
2013-9-14
在线时间
293 小时
最后登录
2018-1-5

专栏作家

 楼主| 发表于 2017-11-6 16:29:41 | 显示全部楼层
斯巴达 发表于 2017-11-6 15:00
Grab Pass的性能是不是还不如Render Texture啊?

应该是比RenderTexture好的,要对比过才行。

回复 支持 反对

使用道具 举报

5熟悉之中
605/1000
排名
7008
昨日变化
3

1

主题

140

帖子

605

积分

Rank: 5Rank: 5

UID
56504
好友
0
蛮牛币
460
威望
0
注册时间
2014-11-19
在线时间
328 小时
最后登录
2018-1-22
发表于 2017-11-6 19:39:49 | 显示全部楼层
GrabPass性能应该不如RT吧。。  移动端基本上没法用这个玩意。。

回复 支持 反对

使用道具 举报

7日久生情
1845/5000
排名
1068
昨日变化
56

30

主题

295

帖子

1845

积分

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

UID
124569
好友
25
蛮牛币
8723
威望
0
注册时间
2015-10-4
在线时间
634 小时
最后登录
2018-1-23
发表于 2017-11-7 09:17:52 | 显示全部楼层
谢谢分享

回复

使用道具 举报

3偶尔光临
254/300
排名
12259
昨日变化
5

0

主题

122

帖子

254

积分

Rank: 3Rank: 3Rank: 3

UID
155121
好友
0
蛮牛币
126
威望
0
注册时间
2016-7-4
在线时间
74 小时
最后登录
2017-12-16
发表于 2017-11-8 18:51:35 | 显示全部楼层
{:86:}{:86:}

回复

使用道具 举报

4四处流浪
361/500
排名
6572
昨日变化
60

0

主题

46

帖子

361

积分

Rank: 4

UID
148615
好友
0
蛮牛币
511
威望
0
注册时间
2016-5-15
在线时间
153 小时
最后登录
2018-1-23
发表于 2017-11-13 12:24:40 | 显示全部楼层
谢谢分享

回复

使用道具 举报

5熟悉之中
550/1000
排名
7631
昨日变化
81

15

主题

333

帖子

550

积分

Rank: 5Rank: 5

UID
249218
好友
3
蛮牛币
1812
威望
0
注册时间
2017-10-17
在线时间
66 小时
最后登录
2018-1-22
发表于 2017-11-14 08:32:08 | 显示全部楼层
Shader Playground:Unity UGUI模糊贴图纹理效果实现

回复 支持 反对

使用道具 举报

3偶尔光临
166/300
排名
55379
昨日变化
26

0

主题

11

帖子

166

积分

Rank: 3Rank: 3Rank: 3

UID
64429
好友
0
蛮牛币
294
威望
0
注册时间
2014-12-29
在线时间
154 小时
最后登录
2018-1-18
发表于 2017-11-15 15:38:22 | 显示全部楼层
移动端基本不用考虑了,用GrabPass消耗太大。
比较经济实惠的方法是建立一个帧缓冲,用内存空间换时间,奇数帧将画面渲染到RenderTexture 1再blit到屏幕上偶数帧将画面渲染到RenderTexture 2上再blit到屏幕,利用上一帧渲染的结果(保存在了RenderTexture里面)来做模糊、扭曲效果。
[发帖际遇]: leosaac 发帖时在路边捡到 1 蛮牛币,偷偷放进了口袋. 幸运榜 / 衰神榜

回复 支持 1 反对 0

使用道具 举报

您需要登录后才可以回帖 登录 | 注册帐号

本版积分规则

关闭

站长推荐 上一条 /1 下一条

快速回复 返回顶部 返回列表