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

函数解析
CG函数名称 | CG函数解析 |
---|---|
lerp | lerp(a,b,f) 在下限a和b之间插值,f作为权值 公式:P=P_0+t(P_1-P_0),0<=t<=1 |
step | step(a,x) 如果a<x,返回0,否者返回1 |
saturate | saturate(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);
}
}
完。
更多内容,欢迎关注:
