47.滚动的背景

47.动态效果-纹理动画-滚动的背景


47.1 知识点

知识补充:内置函数 frac

frac 是一个内置函数,用于计算数值的小数部分,其公式为:

frac(x) = x - floor(x)

特性及应用

  • 主要作用是保留数值的小数部分。
  • 对于正数,直接取小数部分:
    • frac(2.5) = 2.5 - 2 = 0.5
    • frac(3.75) = 3.75 - 3 = 0.75
  • 对于负数,小数部分重新从 0 开始计数:
    • frac(-0.25) = -0.25 - (-1) = 0.75
    • frac(-3.75) = -3.75 - (-4) = 0.25

UV 坐标中的应用

  • 保证 UV 坐标始终在 [0, 1] 范围内。
  • 对 UV 值进行循环处理:
    • 大于 1 的 UV 值从 0 开始重新取值。
    • 小于 0 的 UV 值从 1 开始反向取值。

准备工作

  1. 导入滚动背景的美术资源。
  2. 准备测试场景,确保资源图片首尾循环连接。

利用纹理坐标实现滚动背景的原理

注意点

  • 滚动背景的图片通常首尾循环相连,保证视觉上的无缝过渡。

基本原理

  • 利用时间变量动态偏移 UV 坐标。
  • UV 坐标超过 1 时,自动从 0 重新采样。
  • UV 坐标小于 0 时,自动从 1 反向采样。

Shader 实现滚动背景

新建Shader,删除无用代码,保留骨架

Shader "Unlit/Lesson47_ScrollingBackground"
{
    Properties
    {
    
    }
    SubShader
    {

        Pass
        {
        
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            

            #include "UnityCG.cginc"

    
            ENDCG
        }
    }
}

声明属性和属性映射,包括主纹理、U轴速度、V轴速度(两个速度的原因是因为图片可能竖直或水平滚动)

Properties
{
    // 主纹理
    _MainTex ("Texture", 2D) = "white" {}
    // 水平滚动速度
    _ScrollSpeedU ("ScrollSpeedU", float) = 0.5
    // 竖直滚动速度
    _ScrollSpeedV ("ScrollSpeedV", float) = 0.5
}
sampler2D _MainTex; // 主纹理采样器
float _ScrollSpeedU; // 水平滚动速度
float _ScrollSpeedV; // 竖直滚动速度

设置为透明Shader,修改渲染标签、关闭深度写入、进行透明混合,因为往往这种滚动背景图片都会有透明区域

Tags
{
    // 渲染类型为透明
    "RenderType"="Transparent"
    // 渲染队列设置为透明队列
    "Queue"="Transparent"
    // 忽略投影器
    "IgnoreProjector"="True"
}

Pass
{
    // 关闭深度写入
    ZWrite Off
    // 设置混合模式为源颜色的透明度与目标颜色的反透明度进行混合
    Blend SrcAlpha OneMinusSrcAlpha
    
    //...
}

声明结构体,包括顶点和纹理坐标

struct v2f
{
    // UV 坐标,用于纹理采样
    float2 uv : TEXCOORD0;
    // 顶点在裁剪空间中的位置
    float4 vertex : SV_POSITION;
};

顶点函数把顶点坐标转换成裁剪空间,纹理uv坐标直接赋值

// 顶点着色器函数
v2f vert(appdata_base appdata_base)
{
    // 创建结构体变量
    v2f v2f;
    // 将顶点从模型空间转换到裁剪空间
    v2f.vertex = UnityObjectToClipPos(appdata_base.vertex);
    // 获取顶点的原始 UV 坐标
    v2f.uv = appdata_base.texcoord;
    // 返回结构体变量
    return v2f;
}

片元函数利用时间和速度对uv坐标进行偏移计算偏移后的uv坐标并进行采样

// 片元着色器函数
fixed4 frag(v2f v2f) : SV_Target
{
    // 根据时间和滚动速度计算 UV 坐标的偏移量
    // frac 函数用于获取小数部分,使得 UV 坐标在 0 到 1 之间循环变化
    float2 scrollUV = frac(v2f.uv + float2(_Time.y * _ScrollSpeedU, _Time.y * _ScrollSpeedV));
    // 使用计算后的 UV 坐标进行纹理采样并返回颜色值
    return tex2D(_MainTex, scrollUV);
}

创建4个贴图的对应shader,调整v轴速度为0,可以看到滚动效果

总结

  1. 图片资源规范:滚动背景的资源必须首尾无缝衔接。
  2. 核心实现:使用 frac 函数将 UV 坐标限制在 [0, 1] 范围内,实现循环滚动。
  3. 灵活调整:通过修改滚动速度控制背景滚动的方向和速度。

47.2 知识点代码

Lesson47_动态效果_纹理动画_滚动的背景.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Lesson47_动态效果_纹理动画_滚动的背景 : MonoBehaviour
{
    void Start()
    {
        #region 知识补充 内置函数frac

        //内置函数 frac(参数)
        //该函数的内部计算规则为:
        //frac(x) = x - floor(x)
        //一般用于保留数值的小数部分,但是负数时要注意
        //比如:
        //frac(2.5) = 2.5 - 2 = 0.5
        //frac(3.75) = 3.75 - 3 = 0.75
        //frac(-0.25) = -0.25 - (-1) = 0.75
        //frac(-3.75) = -3.75 - (-4) = 0.25

        //它的主要作用是可以帮助我们保证 uv坐标 范围在0~1之间
        //相当于
        //大于1的uv值重新从0开始向1方向取值
        //小于0的uv值重新从1开始向0方向取值

        #endregion

        #region 准备工作

        //导入测试用资源

        #endregion

        #region 知识点一 分析利用纹理坐标制作滚动的背景的原理

        //注意点:
        //滚动的背景使用的美术资源图片,往往是首尾循环相连的

        //基本原理:
        //不停地利用时间变量对uv坐标进行偏移运算
        //超过1的部分从0开始采样
        //小于0的部分从1开始采样

        #endregion

        #region 知识点二 用Shader实现滚动的背景

        //1.新建Shader,删除无用代码
        //2.声明属性,属性映射
        //  主纹理、U轴速度、V轴速度(两个速度的原因是因为图片可能竖直或水平滚动)
        //3.透明Shader
        //  往往这种滚动背景图片都会有透明区域
        //  渲染标签修改、关闭深度写入、进行透明混合
        //4.结构体
        //  顶点和纹理坐标
        //5.顶点着色器 
        //  顶点坐标转换,纹理坐标直接赋值
        //6.片元着色器
        //  利用时间和速度对uv坐标进行偏移计算
        //  利用偏移后的uv坐标进行采样

        #endregion

        #region 总结

        //Shader实现滚动的背景的关键点
        //1.纹理图片必须按规范制作,“首尾相连”
        //2.利用内置时间变量对纹理坐标进行偏移计算

        #endregion
    }
}

Lesson47_ScrollingBackground.shader

Shader "Unlit/Lesson47_ScrollingBackground"
{
    Properties
    {
        // 主纹理属性
        _MainTex ("Texture", 2D) = "white" {}
        // 水平滚动速度属性
        _ScrollSpeedU("ScrollSpeedU", float) = 0.5
        // 竖直滚动速度属性
        _ScrollSpeedV("ScrollSpeedV", float) = 0.5
    }

    SubShader
    {
        Tags
        {
            // 渲染类型为透明
            "RenderType"="Transparent"
            // 渲染队列设置为透明队列
            "Queue"="Transparent"
            // 忽略投影器
            "IgnoreProjector"="True"
        }
        
        Pass
        {
            // 关闭深度写入
            ZWrite Off
            // 设置混合模式为源颜色的透明度与目标颜色的反透明度进行混合
            Blend SrcAlpha OneMinusSrcAlpha
            
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            
            #include "UnityCG.cginc"

            // 主纹理采样器
            sampler2D _MainTex;
            // 水平滚动速度
            float _ScrollSpeedU;
            // 竖直滚动速度
            float _ScrollSpeedV;
            
            struct v2f
            {
                // UV 坐标,用于纹理采样
                float2 uv : TEXCOORD0;
                // 顶点在裁剪空间中的位置
                float4 vertex : SV_POSITION;
            };

            // 顶点着色器函数
            v2f vert(appdata_base appdata_base)
            {
                // 创建结构体变量
                v2f v2f;
                // 将顶点从模型空间转换到裁剪空间
                v2f.vertex = UnityObjectToClipPos(appdata_base.vertex);
                // 获取顶点的原始 UV 坐标
                v2f.uv = appdata_base.texcoord;
                // 返回结构体变量
                return v2f;
            }

            // 片元着色器函数
            fixed4 frag(v2f v2f) : SV_Target
            {
                // 根据时间和滚动速度计算 UV 坐标的偏移量
                // frac 函数用于获取小数部分,使得 UV 坐标在 0 到 1 之间循环变化
                float2 scrollUV = frac(v2f.uv + float2(_Time.y * _ScrollSpeedU, _Time.y * _ScrollSpeedV));
                // 使用计算后的 UV 坐标进行纹理采样并返回颜色值
                return tex2D(_MainTex, scrollUV);
            }
            ENDCG
        }
    }
}


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏