Shader dans Unity saisit l'écran et obtient un effet de distorsion


Préface

Shader dans Unity saisit l'écran et réalise l'effet de distorsion


1. La capture d'écran a été écrite dans l'article précédent.

2. Réalisez la distorsion de l'écran après la saisie

Idées de mise en œuvre :

1. La distorsion de l’écran nécessite l’utilisation de cartes UV entrantes.

2. Après avoir passé la texture, transmettez un float2 uv: TEXCOORD au paramètre d'entrée du vertex shader, qui sera utilisé pour échantillonner la carte de distorsion plus tard.

3. Enfin, utilisez lerp(screenUV,distortTex,_Distort) dans l'étape du fragment shader et effectuez une interpolation linéaire pour contrôler le degré de distorsion.

Code:

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. Obtenez des effets de flux sur des effets déformés

Idées de mise en œuvre :

Au vertex shader, utilisez le Tiling et le décalage de la carte de distorsion et multipliez-le par _Time. Pour la vitesse d'écoulement, exposez simplement deux variables float pour contrôler la vitesse d'écoulement.

Code:

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


Effet:
Veuillez ajouter une description de l'image

4. Afin d'économiser les performances, stockez les trois variables _Distort, _SpeedX et _SpeedY dans une variable à quatre dimensions

Optimisé :

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


Je suppose que tu aimes

Origine blog.csdn.net/qq_51603875/article/details/132784257
conseillé
Classement