unity shader 案例uv流动+遮罩 Shader代码+ASE实现

本文介绍如何使用UnityShader中的UnlitShader实现UV流动和遮罩效果,通过a通道混合两张图片,同时提供遮罩控制图片亮度的方法,适合学习和实践基础shader技术。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

大家好,本期给大家展示shader实现的一些有趣的效果,寓教于乐
在这里插入图片描述
效果是由uv流动+遮罩实现,具体来说就是,

  • 将第二张图片与第一张图片利用a通道进行混合
  • a通道的区域由一个黑白图片决定,遮罩的r值决定利用哪个图片的像素
  • mask.r=0,像素由第一个图片决定,mask.r=1,像素由第二个图片决定

资源

在这里插入图片描述
遮罩图片,可以利用ps制作

  • 使用钢笔工具
  • 选择形状
  • 关闭填充,打开描边,调整描边大小
  • 加模糊,顶部菜单栏->滤镜/模糊/高斯模糊或者表面模糊

Shader代码

  1. 创建Shader,创建->Shader->Unlit Shader,命名为MaskUVFlow

在这里插入图片描述
2.声明Properties

Properties
{
    _MainTex ("Texture", 2D) = "white" {}//主贴图,在下面的贴图
    _FlowTexture("FLowTexture",2D)="white" {}//副贴图,在上面流动的贴图
    _MaskVTex("MaskSin Texture",2D)="white" {}//V形遮罩贴图
    _FlowSpeed("FlowSpeed",Float)=1//uv流动的速度
    _Drakness("Drakness",Range(0,1))=1//主贴图的暗度
    _Brightness("Brightness",Range(1,5))=1//副贴图的亮度
}
  1. 定义
//顶点着色器,接收的结构体
struct appdata
{
    float4 vertex : POSITION;
    float2 uv : TEXCOORD0;
};
//片元着色器,接收的结构体,由顶点着色器传入
struct v2f
{
    float2 uv : TEXCOORD0;//主贴图变换后的uv
    float2 uv1:TEXCOORD1;//副贴图变换后的uv
    float2 uv2:TEXCOORD2;//遮罩贴图变换后的uv
    float4 vertex : SV_POSITION;
};
  1. 顶点着色器
sampler2D _MainTex;
float4 _MainTex_ST;
sampler2D _FlowTexture;
sampler2D _MaskVTex;
float4 _FlowTexture_ST;
float4 _MaskVTex_ST;
float _FlowSpeed;
float _Drakness;
float _Brightness;
v2f vert (appdata v)
{
    v2f o;
    o.vertex = UnityObjectToClipPos(v.vertex);//将模型空间->裁剪空间
    o.uv = TRANSFORM_TEX(v.uv, _MainTex);//变换主贴图的uv
    //o.uv=v.uv*_MainTex_ST.xy+_MainTex_ST.zw;
    //使用一个float4对原来的uv进行缩放和偏移
    o.uv1 = TRANSFORM_TEX(v.uv,_FlowTexture);//变换副贴图的uv
    o.uv2 = TRANSFORM_TEX(v.uv, _MaskVTex);//变换遮罩贴图的uv
    o.uv2=float2(o.uv2.x+_Time.y*_FlowSpeed,o.uv2.y);
    //_Time.y单位s,游戏运行的秒数
    //利用对遮罩贴图的uv的x进行偏移
    return o;
}
  1. 片元着色器
fixed4 frag (v2f i) : SV_Target
{
    fixed4 col = tex2D(_MainTex, i.uv);
    //利用uv对_MainTex进行采样
    //如(0.1,0.2),图片大小1920*1080=>采样(192,216)
    fixed4 col2=tex2D(_FlowTexture,i.uv1);
    float mask=tex2D(_MaskVTex,i.uv2).r;//获取遮罩图片的r通道
    _Drakness=0.5-_Time.y%10/20;//每十秒暗度从0.5变化到0
    _Brightness=_Time.y%10/5+1;//每十秒亮度从1变化到3
    col*=_Drakness;   //使用暗度乘以主贴图的rgba
    col2*=_Brightness;//使用亮度乘以副贴图的rgba
    fixed4 final=lerp(col,col2,mask);
    //线性插值,lerp(a,b,t),a + (b - a) * t
    //利用mask.r混合图片1和2,mask黑色的区域显示为图片1,mask白色的区域显示为图片2
    return final;
}

完整Shader代码

Shader "Unlit/FlowSin"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}//主贴图,在下面的贴图
        _FlowTexture("FLowTexture",2D)="white" {}//副贴图,在上面流动的贴图
        _MaskVTex("MaskSin Texture",2D)="white" {}//V形遮罩贴图
        _FlowSpeed("FlowSpeed",Float)=1//uv流动的速度
        _Drakness("Drakness",Range(0,1))=1//主贴图的暗度
        _Brightness("Brightness",Range(1,5))=1//副贴图的亮度
    }
    SubShader
    {
        Tags
        Tags { "RenderType" = "Opaque" "Queue" = "Transparent" }
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            //顶点着色器,接收的结构体
            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            //片元着色器,接收的结构体,由顶点着色器传入
            struct v2f
            {
                float2 uv : TEXCOORD0; //主贴图变换后的uv
                float2 uv1:TEXCOORD1; //副贴图变换后的uv
                float2 uv2:TEXCOORD2; //遮罩贴图变换后的uv
                float4 vertex : SV_POSITION;//变换到裁剪空间的位置
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            sampler2D _FlowTexture;
            sampler2D _MaskVTex;
            float4 _FlowTexture_ST;
            float4 _MaskVTex_ST;
            float _FlowSpeed;
            float _Drakness;
            float _Brightness;

            v2f vert(appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex); //将模型空间->裁剪空间
                o.uv = TRANSFORM_TEX(v.uv, _MainTex); //变换主贴图的uv
                //o.uv=v.uv*_MainTex_ST.xy+_MainTex_ST.zw;
                //使用一个float4对原来的uv进行缩放和偏移
                o.uv1 = TRANSFORM_TEX(v.uv, _FlowTexture); //变换副贴图的uv
                o.uv2 = TRANSFORM_TEX(v.uv, _MaskVTex); //变换遮罩贴图的uv
                o.uv2 = float2(o.uv2.x + _Time.y * _FlowSpeed, o.uv2.y);
                //_Time.y单位s,游戏运行的秒数
                //利用对遮罩贴图的uv的x进行偏移
                return o;
            }

            fixed4 frag(v2f i) : SV_Target
            {
                fixed4 col = tex2D(_MainTex, i.uv);
                //利用uv对_MainTex进行采样
                //如(0.1,0.2),图片大小1920*1080=>采样(192,216)
                fixed4 col2 = tex2D(_FlowTexture, i.uv1);
                float mask = tex2D(_MaskVTex, i.uv2).r; //获取遮罩图片的r通道
                _Drakness = 0.5 - _Time.y % 10 / 20; //每十秒暗度从0.5变化到0
                _Brightness = _Time.y % 10 / 5 + 1; //每十秒亮度从1变化到3
                col *= _Drakness; //使用暗度乘以主贴图的rgba
                col2 *= _Brightness; //使用亮度乘以副贴图的rgba
                fixed4 final = lerp(col, col2, mask);
                //线性插值,lerp(a,b,t),a + (b - a) * t
                //利用mask.r混合图片1和2,mask黑色的区域显示为图片1,mask白色的区域显示为图片2
                return final;
            }
            ENDCG
        }
    }
}

ASE实现

  1. uv流动,遮罩
    在这里插入图片描述
  2. 控制图片亮度
    在这里插入图片描述

结束语

本文章只是用Shader实现有趣的效果,寓教于乐
如果有不懂的地方或者建议,欢迎在评论区交流
制作不易,希望大家支持一下,谢谢~~😊

遮罩图片可以换成正弦波
可以根据自己的喜好更换

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值