Unity中Shader序列图动画(UV流动的通用起始点)

文章目录

  • 前言
  • 一、一般序列帧动画是按照序列图如下顺序读取的
  • 二、在Shader找到UV流动的起始点
    • 1、先实现纹理采样
    • 2、得到 uv 走格的单位格子大小
    • 3、定位到左上角为起始单位格
  • 三、使UV流动的起始点通用化
    • 1、在属性面板接收 行 和 列的属性
    • 2、看图片可以总结出第一个单元格的公式
    • 3、我们选几个不同的序列图看看效果
  • 四、测试代码


前言

我们在Shader中实现序列帧动画。可以实现一些简单特效或动画节省性能用。

我们在这篇文章中,实现一下UV流动的通用起始点。


一、一般序列帧动画是按照序列图如下顺序读取的

  • 先左到右,再从上到下
    Unity中Shader序列图动画(UV流动的通用起始点)_第1张图片

二、在Shader找到UV流动的起始点

1、先实现纹理采样

  • Unity中 URP Shader 的纹理与采样器的分离定义

  • 属性面板

_MainTex(“MainTex”,2D) = “white”{}

  • 定义纹理

TEXTURE2D(_MainTex);

  • 定义采样器

SAMPLER(sampler_MainTex);

  • 在片元着色器进行纹理采样

float4 mainTex = SAMPLE_TEXTURE2D(_MainTex,sampler_MainTex,i.uv);

2、得到 uv 走格的单位格子大小

  • m ∗ n m * n mn 的序列帧图,就对UV除以多少,来得到一个格子的图像
    u m 和 v n \frac{u}{m} 和 \frac{v}{n} munv
  • 比如说,我们使用如下 4 x 4 的序列帧来测试
    Unity中Shader序列图动画(UV流动的通用起始点)_第2张图片
    就对 uv 分别除以4得到一个序列图的大小

o.uv = float2(v.uv.x/4,v.uv.y/4);

Unity中Shader序列图动画(UV流动的通用起始点)_第3张图片

3、定位到左上角为起始单位格

  • 可以看出,我们的 u 方向以及在起始位置了,但是 v 方向却在最后一列
  • 所以,我们需要加上 n - 1 个单位格大小,使 v 方向上达到第一行

o.uv = float2(v.uv.x/4,v.uv.y/4 + 0.75);

Unity中Shader序列图动画(UV流动的通用起始点)_第4张图片


三、使UV流动的起始点通用化

1、在属性面板接收 行 和 列的属性

_Sequence(“Row(X) Column(Y)”,Vector) = (1,1,1,1)

2、看图片可以总结出第一个单元格的公式

  • u v . x = u v . x C o l u m n uv.x = \frac{uv.x}{Column} uv.x=Columnuv.x
  • u v . y = u v . y R o w + R o w − 1 R o w uv.y = \frac{uv.y}{Row}+\frac{Row-1}{Row} uv.y=Rowuv.y+RowRow1

o.uv = float2(v.uv.x/_Sequence.y,v.uv.y/_Sequence.x + (_Sequence.x - 1)/_Sequence.x);

3、我们选几个不同的序列图看看效果

  • 4x3
    Unity中Shader序列图动画(UV流动的通用起始点)_第5张图片

  • 4x4
    Unity中Shader序列图动画(UV流动的通用起始点)_第6张图片


四、测试代码

Shader "MyShader/URP/P3_9"
{
    Properties
    {
        _Color("Color",Color) = (1,1,1,1)
        _MainTex("MainTex",2D) = "white"{}
        _Sequence("Row(X) Column(Y)",Vector) = (1,1,1,1)
    }
    SubShader
    {
        Tags
        {
            //告诉引擎,该Shader只用于 URP 渲染管线
            "RenderPipeline"="UniversalPipeline"
            //渲染类型
            "RenderType"="Transparent"
            //渲染队列
            "Queue"="Transparent"
        }
        Blend SrcAlpha OneMinusSrcAlpha Zwrite On
        Pass
        {
            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_fog
            #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"

            struct Attribute
            {
                float3 vertexOS : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct Varying
            {
                float4 vertexCS : SV_POSITION;
                float2 uv : TEXCOORD1;
                float fogCoord : TEXCOORD2;
            };

            CBUFFER_START(UnityPerMaterial)
                float4 _Color;
                float4 _MainTex_ST;
                half4 _Sequence;
            CBUFFER_END
            TEXTURE2D(_MainTex);
            SAMPLER(sampler_MainTex);

            Varying vert(Attribute v)
            {
                Varying o;
                o.vertexCS = TransformObjectToHClip(v.vertexOS);
                o.uv = float2(v.uv.x/_Sequence.y,v.uv.y/_Sequence.x + (_Sequence.x - 1)/_Sequence.x);
                //o.uv = float2(v.uv.x/4,v.uv.y/4);
                //o.uv = TRANSFORM_TEX(v.uv,_MainTex);
                o.fogCoord = ComputeFogFactor(o.vertexCS.z);
                return o;
            }

            half4 frag(Varying i) : SV_Target
            {
                float4 mainTex = SAMPLE_TEXTURE2D(_MainTex,sampler_MainTex,i.uv);
                float4 col = mainTex * _Color;
                col.rgb = MixFog(col,i.fogCoord);
                return col;
            }
            ENDHLSL
        }
    }
    
}

你可能感兴趣的:(Unity,unity,uv,游戏引擎)