Shader en Unity toma la pantalla y logra un efecto de distorsión


Prefacio

Shader en Unity toma la pantalla y realiza el efecto de distorsión


1. La captura de pantalla se escribió en el artículo anterior.

2. Date cuenta de la distorsión de la pantalla después de agarrar

Ideas de implementación:

1. La distorsión de la pantalla requiere el uso de mapas UV entrantes.

2. Después de pasar la textura, pase un float2 uv: TEXCOORD en el parámetro de entrada del sombreador de vértices, que se utilizará para muestrear el mapa de distorsión más adelante.

3. Finalmente, use lerp(screenUV,distortTex,_Distort) en la etapa de sombreado de fragmentos y realice una interpolación lineal para controlar el grado de distorsión.

Código:

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
        }
    }
}


3. Lograr efectos de flujo sobre efectos distorsionados.

Ideas de implementación:

En el sombreador de vértices, use el mosaico y el desplazamiento del mapa de distorsión y multiplíquelo con _Time. Para la velocidad del flujo, simplemente exponga dos variables flotantes para controlar la velocidad del flujo.

Código:

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
        }
    }
}


Efecto:
Por favor agregue la descripción de la imagen.

4. Para ahorrar rendimiento, almacene las tres variables _Distort, _SpeedX y _SpeedY en una variable de cuatro dimensiones

Optimizado:

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
        }
    }
}


Supongo que te gusta

Origin blog.csdn.net/qq_51603875/article/details/132784257
Recomendado
Clasificación