• Unity中Shader抓取屏幕并实现扭曲效果



    前言

    Unity中Shader抓取屏幕并实现扭曲效果实现


    一、屏幕抓取,在上一篇文章已经写了

    二、实现抓取后的屏幕扭曲

    实现思路:

    1、屏幕扭曲要借助传入 UV 贴图进行扭曲

    2、传入贴图后在顶点着色器的输入参数处,传入一个 float2 uv : TEXCOORD,用于之后对扭曲贴图进行采样

    3、最后在片元着色器阶段使用lerp(screenUV,distortTex,_Distort);进行线性插值对扭曲程度进行控制

    代码实现:

    Shader "MyShader/P0_10_4"
    {
        Properties
        {
            //实现扭曲,就需要传入贴图来实现扰度
            _DistortTex("DistortTex",2D) = "white"{}
            _Distort("Distort",Range(0,1)) = 0
        }
        SubShader
        {
            Tags{"Queue" = "Transparent"}
            //屏幕抓取需要单独使用一个Pass —— GrabPass{} 里面什么都不写,或者GrabPass{"_GrabTex"}
            GrabPass{"_GrabTex"}
            
            Pass
            {
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #include "UnityCG.cginc"
                
                struct v2f
                {
                    float2 uv : TEXCOORD0;
                };
    
                //在使用抓取的屏幕前,需要像使用属性一样定义一下,_GrabTexture这个名字是Unity定义好的
                sampler2D _GrabTex;
                sampler2D _DistortTex;float4 _DistortTex_ST;
                fixed _Distort;
                
                //在顶点着色器的输入处,不用appdata,直接使用用到的参数,防止 SV_POSITION 重复定义
                v2f vert (
                    float4 vertex : POSITION,
                    //从应用程序阶段的输入,多加一个uv,用于对扭曲纹理的采样
                    float2 uv : TEXCOORD,
                    out float4 pos : SV_POSITION
                )
                {
                    v2f o;
                    pos = UnityObjectToClipPos(vertex);
                    o.uv = uv;
                    return o;
                }
    
                fixed4 frag (v2f i,UNITY_VPOS_TYPE screenPos : VPOS) : SV_Target
                {
                    
                    fixed2 screenUV = screenPos.xy / _ScreenParams.xy;
    
                    fixed4 distortTex = tex2D(_DistortTex,i.uv);
    
                    //使用线性插值来控制UV的扭曲程度
                    float2 uv = lerp(screenUV,distortTex,_Distort);
                    //对抓取的屏幕进行采样
                    fixed4 grabTex = tex2D(_GrabTex,uv);
                    return grabTex;
                }
                ENDCG
            }
        }
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64

    三、在扭曲的效果上实现流动效果

    实现思路:

    在顶点着色器处,使用扭曲贴图的Tiling 及 offset 后与_Time相乘即可,流动速度,暴露两个float变量控制流速即可

    代码实现:

    Shader "MyShader/P0_10_4"
    {
        Properties
        {
            //实现扭曲,就需要传入贴图来实现扰度
            _DistortTex("DistortTex",2D) = "white"{}
            _Distort("Distort",Range(0,1)) = 0
            _SpeedX("SpeedX",float) = 0
            _SpeedY("SpeedY",float) = 0
        }
        SubShader
        {
            Tags{"Queue" = "Transparent"}
            //屏幕抓取需要单独使用一个Pass —— GrabPass{} 里面什么都不写,或者GrabPass{"_GrabTex"}
            GrabPass{"_GrabTex"}
            //使用Cull off 让两面都有扭曲
            Cull Off
            Pass
            {
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #include "UnityCG.cginc"
                
                struct v2f
                {
                    float2 uv : TEXCOORD0;
                };
    
                //在使用抓取的屏幕前,需要像使用属性一样定义一下,_GrabTexture这个名字是Unity定义好的
                sampler2D _GrabTex;
                sampler2D _DistortTex;float4 _DistortTex_ST;
                fixed _Distort;
                float _SpeedX,_SpeedY;
                
                //在顶点着色器的输入处,不用appdata,直接使用用到的参数,防止 SV_POSITION 重复定义
                v2f vert (
                    float4 vertex : POSITION,
                    //从应用程序阶段的输入,多加一个uv,用于对扭曲纹理的采样
                    float2 uv : TEXCOORD,
                    out float4 pos : SV_POSITION
                )
                {
                    v2f o;
                    pos = UnityObjectToClipPos(vertex);
                    o.uv = TRANSFORM_TEX(uv,_DistortTex) + float2(_SpeedX,_SpeedY) * _Time.y;
                    return o;
                }
    
                fixed4 frag (v2f i,UNITY_VPOS_TYPE screenPos : VPOS) : SV_Target
                {
                    
                    fixed2 screenUV = screenPos.xy / _ScreenParams.xy;
    
                    fixed4 distortTex = tex2D(_DistortTex,i.uv);
    
                    //使用线性插值来控制UV的扭曲程度
                    float2 uv = lerp(screenUV,distortTex,_Distort);
                    //对抓取的屏幕进行采样
                    fixed4 grabTex = tex2D(_GrabTex,uv);
                    return grabTex;
                }
                ENDCG
            }
        }
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68

    效果:
    请添加图片描述

    四、为了节省性能,把_Distort 、_SpeedX 和 _SpeedY三个变量用一个四维变量存储

    优化后:

    Shader "MyShader/P0_10_4"
    {
        Properties
        {
            //实现扭曲,就需要传入贴图来实现扰度
            _DistortTex("DistortTex",2D) = "white"{}
            
            _Distort("SpeedX(X) SpeedY(y) Distort(Z)",vector) = (0,0,0,0)
        }
        SubShader
        {
            Tags{"Queue" = "Transparent"}
            //屏幕抓取需要单独使用一个Pass —— GrabPass{} 里面什么都不写,或者GrabPass{"_GrabTex"}
            GrabPass{"_GrabTex"}
            //使用Cull off 让两面都有扭曲
            Cull Off
            Pass
            {
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #include "UnityCG.cginc"
                
                struct v2f
                {
                    float2 uv : TEXCOORD0;
                };
    
                //在使用抓取的屏幕前,需要像使用属性一样定义一下,_GrabTexture这个名字是Unity定义好的
                sampler2D _GrabTex;
                sampler2D _DistortTex;float4 _DistortTex_ST;
                float4 _Distort;
                
                
                //在顶点着色器的输入处,不用appdata,直接使用用到的参数,防止 SV_POSITION 重复定义
                v2f vert (
                    float4 vertex : POSITION,
                    //从应用程序阶段的输入,多加一个uv,用于对扭曲纹理的采样
                    float2 uv : TEXCOORD,
                    out float4 pos : SV_POSITION
                )
                {
                    v2f o;
                    pos = UnityObjectToClipPos(vertex);
                    o.uv = TRANSFORM_TEX(uv,_DistortTex) + _Distort.xy * _Time.y;
                    return o;
                }
    
                fixed4 frag (v2f i,UNITY_VPOS_TYPE screenPos : VPOS) : SV_Target
                {
                    
                    fixed2 screenUV = screenPos.xy / _ScreenParams.xy;
    
                    fixed4 distortTex = tex2D(_DistortTex,i.uv);
    
                    //使用线性插值来控制UV的扭曲程度
                    float2 uv = lerp(screenUV,distortTex,_Distort.z);
                    //对抓取的屏幕进行采样
                    fixed4 grabTex = tex2D(_GrabTex,uv);
                    return grabTex;
                }
                ENDCG
            }
        }
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
  • 相关阅读:
    2022-08-13周总结
    TinyKv介绍
    女性排卵期的七个表现,把握住提前当宝妈
    【Java八股文总结】之数据结构
    Java面试题大全(整理版)1000+面试题附答案详解最全面看完稳了
    SpringBoot解压zip包,读取每个文件内容
    达梦8全量备份和增量备份备份策略
    冒泡排序法解析
    英国滞胀或在四季度正式到来 英镑兑美元将处于不利处境?
    Three.js中加载和渲染3D Tiles
  • 原文地址:https://blog.csdn.net/qq_51603875/article/details/132784257