unity Shader 扭曲效果

原理

所谓扭曲就是扰动一个物体的uv坐标,表现出来就是一个扰动效果,如火焰扭曲空气,和水波对水底的影响。
1. 在shader 中我们需要一张当前渲染的纹理
2. 给一个物体渲染并使用当前纹理,用屏幕坐标作为uv坐标加上一个扰动值

unity

1.
unity提供了抓取的pass: GrabPass unity官网介绍

//每次遇到这个pass就去抓取一次提供了了一个默认名称_GrabTexture 不推荐使用
GrabPass
{ 
}
//第一次遇到去抓取一次每帧只会抓取一次,名称由你自己定义
 GrabPass
 {
     "_BackgroundTexture"
 }

2.
获取物体的屏幕坐标,unity也给出了内置函数

//官网代码
 v2f vert(appdata_base v) {
      v2f o;
       // use UnityObjectToClipPos from UnityCG.cginc to calculate 
       // the clip-space of the vertex
       o.pos = UnityObjectToClipPos(v.vertex);
       // use ComputeGrabScreenPos function from UnityCG.cginc
       // to get the correct texture coordinate
       o.grabPos = ComputeGrabScreenPos(o.pos);
       return o;
}

ComputeGrabScreenPos 函数就是得到屏幕坐标,下面是UnityCG.cginc里面的函数源码

inline float4 ComputeGrabScreenPos (float4 pos) {
    #if UNITY_UV_STARTS_AT_TOP
    float scale = -1.0;
    #else
    float scale = 1.0;
    #endif
    float4 o = pos * 0.5f;
    o.xy = float2(o.x, o.y*scale) + o.w;
    #ifdef UNITY_SINGLE_PASS_STEREO
        o.xy = TransformStereoScreenSpaceTex(o.xy, pos.w);
    #endif
        o.zw = pos.zw;
        return o;
}

UNITY_UV_STARTS_AT_TOP 和设备的纹理坐标有关如图
这里写图片描述

pos传进来的坐标是齐次裁剪坐标x,y都在[-w,w]之间,不在这个范围的会在光栅化之前(之后执行片段着色器)裁剪掉。转换如图 A->B 就是o.xy = float2(o.x, o.y*scale) + o.w;
最后还要归一化得到最终纹理坐标是除o.w实现的这个在tex2Dproj 纹理采样中内置函数中实现的(纹理坐标在[0,1])
这里写图片描述

UV 扰动

UV扰动是对一张噪声纹理采用加上偏移值,同时让噪声纹理做uv移动,达到每次采用不同来实现一个动态的效果

关键代码

fixed4 frag (v2f i) : SV_Target
{
    //让噪声纹理的uv移动
    fixed4 col = tex2D(_Noise, i.uv+=_Time.xy*_distortFactorTime);
    // 加上一个偏移值
    i.grabPos.xy +=col.xy*_distortFactor;
     half4 bgcolor = tex2Dproj(_BackgroundTexture, i.grabPos);
    return bgcolor;
}

效果图

这里写图片描述

完整代码

Shader "Custom/Distort"
{
    Properties
    {
        _Noise ("Noise", 2D) = "white" {}
        _distortFactorTime("FactorTime",Range(0,5)) = 0.5
        _distortFactor("factor",Range(0.04,1)) = 0
    }
    SubShader
    {
        Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "PreviewType"="Plane" }
        LOD 100
        Cull Off Lighting Off ZWrite Off
         GrabPass
        {
            "_BackgroundTexture"
        }
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;

            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
                float4 grabPos:TEXCOORD1;
            };

            sampler2D _Noise;
            float4 _Noise_ST;
            fixed _distortFactorTime;
            fixed _distortFactor;
            sampler2D _BackgroundTexture;
            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _Noise);
                o.grabPos = ComputeGrabScreenPos(o.vertex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                // sample the texture
                fixed4 col = tex2D(_Noise, i.uv+=_Time.xy*_distortFactorTime);

                i.grabPos.xy +=col.xy*_distortFactor;
                 half4 bgcolor = tex2Dproj(_BackgroundTexture, i.grabPos);
                return bgcolor;
            }
            ENDCG
        }
    }
}
  • 2
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
要实现图像扭曲过场效果,可以使用Unity3D中的Shader。具体实现步骤如下: 1. 创建一个新的Shader,并将其属性设置为Unlit/Texture。 2. 在Shader中添加一个名为“Distortion”的属性,类型为2D纹理,用于存储扭曲图像。 3. 在Shader中添加一个名为“DistortionStrength”的属性,类型为Range,用于控制扭曲强度。 4. 在Shader的片段着色器中,使用tex2D函数获取原始纹理的颜色,并使用uv坐标对扭曲图像进行采样。 5. 将扭曲图像的采样值与“DistortionStrength”属性相乘,并将结果添加到原始颜色中。 6. 最后,将新的颜色值输出到屏幕。 下面是一个简单的Shader示例: ``` Shader "Custom/DistortionTransition" { Properties { _MainTex ("Texture", 2D) = "white" {} _Distortion ("Distortion", 2D) = "white" {} _DistortionStrength ("Distortion Strength", Range(0.0, 1.0)) = 0.5 } SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; }; sampler2D _MainTex; sampler2D _Distortion; float _DistortionStrength; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = v.uv; return o; } fixed4 frag (v2f i) : SV_Target { // Get the original color fixed4 texColor = tex2D(_MainTex, i.uv); // Get the distortion value float4 distortion = tex2D(_Distortion, i.uv); // Calculate the distortion offset float2 offset = (distortion.rg * 2.0 - 1.0) * _DistortionStrength; // Apply the distortion to the UV coordinates float2 distortedUV = i.uv + offset; // Get the color from the distorted UV coordinates fixed4 distortedColor = tex2D(_MainTex, distortedUV); // Add the distortion to the original color return texColor + (distortedColor - texColor); } ENDCG } } FallBack "Diffuse" } ``` 在使用这个Shader时,可以将原始纹理作为“_MainTex”属性的值,将扭曲图像作为“_Distortion”属性的值,然后通过修改“_DistortionStrength”属性的值来控制扭曲强度。 希望这个示例能够帮助你实现所需的效果

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值