程序化遮罩效果的实现

美术上有这样一个效果,需要文字一行一行或者一列一列的出现,可以自定义(从左向右、从右向左)或者(从上到下、从下到上)四种淡入方式。以下展示两种实现方式。
一、通过限制采样图片的UV坐标来修改被采样像素的Alpha值,不过在过渡中加入了插值,效果比较柔和
  • 优点:效果不错,过渡柔和
  • 缺点:消耗相对较大

如图:


在这里插入图片描述

函数解析
CG函数名称CG函数解析
lerplerp(a,b,f) 在下限a和b之间插值,f作为权值 公式:P=P_0+t(P_1-P_0),0<=t<=1
stepstep(a,x) 如果a<x,返回0,否者返回1
saturatesaturate(x) 限制X的值为0-1之间
Shader "Unlit/ImageAlpha"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}

        _AlphaLeftX("RangeAlphaLeftX",Range(-5,5)) = 1
        _AlphaRightX("RangeAlphaRightX",Range(-5,5)) = 1

        _AlphaTopY("RangeAlphaTopY",Range(-5,5)) = 1
        _AlphaBottomY("RangeAlphaBottomY",Range(-5,5)) = 0

        _MaskTop("MaskTop",Range(0,1)) = 0
        _MaskBottom("MaskBottom",Range(0,1)) = 0

        _AlphaPower("Power",Float) = 0 //透明度变化范围
    }
    SubShader
    {
        Tags { "RenderType"="Transparent"  }
        Blend SrcAlpha OneMinusSrcAlpha
        Cull back
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            
            #include "UnityCG.cginc"
            
            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };
            
            struct v2f
            {
                // float4 worldpos : SV_POSITION;

                float2 uv : TEXCOORD1;
                float4 vertex : SV_POSITION;
            };
            
            sampler2D _MainTex;
            float4 _MainTex_ST;

            float _AlphaPower;
            sampler2D _AlphaTex;


            float _AlphaLeftX;
            float _AlphaRightX;

            float _AlphaTopY;
            float _AlphaBottomY;

            float _MaskTop;
            float _MaskBottom;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                return o;
            }
            //此方法取自Unity默认Sprite的Shader
            fixed4 SampleSpriteTexture (float2 uv)
            {
                fixed4 color = tex2D (_MainTex, uv);
                
                #if ETC1_EXTERNAL_ALPHA
                    // get the color from an external texture (usecase: Alpha support for ETC1 on android)
                    color.a = tex2D (_AlphaTex, uv).r;
                #endif //ETC1_EXTERNAL_ALPHA
                
                return color;
            }
            
            fixed4 frag (v2f i) : SV_Target
            {

                fixed4 col = SampleSpriteTexture(i.uv);

                //四个方向只是对坐标的取值和正反方向不同,原理一致
                fixed alphaleftx = col.a * lerp(1,_AlphaPower,(_AlphaLeftX-i.uv.x));
                col.a = saturate(lerp(alphaleftx,col.a,step(_AlphaLeftX,i.uv.x)));
                
                fixed alpharightx = col.a * lerp(1,_AlphaPower,(i.uv.x-_AlphaRightX));
                col.a = saturate(lerp(col.a,alpharightx,step(_AlphaRightX,i.uv.x)));
                
                fixed alphabottomy = col.a * lerp(1,_AlphaPower,(_AlphaBottomY-i.uv.y));
                col.a = saturate(lerp(alphabottomy,col.a,step(_AlphaBottomY,i.uv.y)));
                
                fixed alphatopy = col.a * lerp(1,_AlphaPower,(i.uv.y-_AlphaTopY));
                col.a = saturate(lerp(col.a,alphatopy,step(_AlphaTopY,i.uv.y)));

                if(i.uv.y>_MaskTop )
                col.a=0;
                if(i.uv.y<_MaskBottom )
                col.a=0;


                return col;
            }
            ENDCG
        }
    }
}
二、通过限制采样图片的UV坐标来修改被采样像素的Alpha值
  • 优点:不那么消耗计算量,简单
  • 缺点:过渡的时候效果比较生硬

如图:


在这里插入图片描述

我们可以把要展示的文字制作成一张图片,通过限制采样图片的UV坐标来达到遮罩的效果,实现代码很简单。着色器代码如下:

Shader "Unlit/UVTest"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}

        _UVXMaskLeft("UVXMask_Left",Range(0,1))=0
        _UVXMaskRight("UVXMask_Right",Range(0,1))=0

        _UVYMaskTop("UVYMask_Top",Range(0,1))=0
        _UVYMaskBottom("UVYMask_Bottom",Range(0,1))=0
    }
    SubShader
    {
        Tags { "RenderType"="Transparent" }
        Blend SrcAlpha OneMinusSrcAlpha
        Cull back

        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;
            float4 _MainTex_ST;

            float _UVXMask;
            float _UVXMaskRight;

            float _UVYMaskTop;
            float _UVYMaskBottom;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);

                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                // sample the texture
                fixed4 col = tex2D(_MainTex, i.uv);

                if (i.uv.x<_UVXMask||i.uv.x>_UVXMaskRight)
                    col.a=0;
                if (i.uv.y>_UVYMaskTop||i.uv.y<_UVYMaskBottom)
                    col.a=0;   
                return col;
            }
            ENDCG
        }
    }
}

控制脚本如下,当然你可以使用Unity的Animation录制工具对Material的参数进行更改。

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

public class ShaderMask : MonoBehaviour
{
    [Range(0, 1)]
    public float uvmask_left=0;
    [Range(0, 1)]
    public float uvmask_right=1;
    [Range(0, 1)]
    public float uvmask_top=1;
    [Range(0, 1)]
    public float uvmask_bottom=0;

    public Material material;

    void Update()
    {
        material.SetFloat("_UVXMaskLeft", uvmask_left);

        material.SetFloat("_UVXMaskRight", uvmask_right);

        material.SetFloat("_UVYMaskTop", uvmask_top);

        material.SetFloat("_UVYMaskBottom", uvmask_bottom);
    }
}

完。
更多内容,欢迎关注:


在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值