前言
再介绍一个简单的效果,贴图切换,根据目标距离远近切换贴图
贴图切换
先看效果
随着小黄鸭的移动,贴图以小黄鸭中心为半径变化。这个方法可以做出许多效果,如放大镜效果,画圆形遮罩等
原理分析
- 主要就是根据提供的目标点(也就是小黄鸭的中心点)和贴图的距离进行不同的采样
具体实现
Shader "Unlit/TextureSwitch"
{
Properties
{
_PlayerPos("Player position",vector) = (0.0,0.0,0.0,0.0)//玩家位置
_Dist("Distance",float)= 5.0//与玩家中心点的距离
_MainTex ("Texture", 2D) = "white" {}//第一张贴图
_SecondayTex("Secondary texture",2D) = "white"{}//第二张贴图
}
SubShader
{
Tags { "RenderType"="Opaque" }
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct v2f
{
float4 pos:SV_POSITION;//插值后的位置信息
float2 uv : TEXCOORD0;//插值后的uv坐标
float4 worldPos:TEXCOORD1;//插值后的世界坐标
};
float4 _PlayerPos;//玩家位置
sampler2D _MainTex;//第一张贴图
sampler2D _SecondayTex;//第二张贴图
float _Dist;//距离
v2f vert (appdata_base v)
{
v2f o;
o.worldPos = mul(unity_ObjectToWorld,v.vertex);//将顶点坐标转成世界坐标,unity_ObjectToWorld是UnityCG.cginc中内置的矩阵
o.pos = UnityObjectToClipPos(v.vertex);//裁剪,规范化坐标
o.uv = v.texcoord;//uv坐标
return o;
}
fixed4 frag (v2f i) : SV_Target
{
if(distance(_PlayerPos.xyz,i.worldPos.xyz)>_Dist){//当前片段位置与玩家位置的距离大于_Dist,采样第一张贴图
return tex2D(_MainTex,i.uv);
}else{//小于_Dist采样第二张贴图
return tex2D(_SecondayTex,i.uv);
}
}
ENDCG
}
}
}
为了便于观察,写一个脚本动态设置玩家位置
public class TextureSwitch : MonoBehaviour {
private Material Mat;
private GameObject Player;
public float Radius = 10;
void Start(){
Mat = GetComponent<Renderer>().material;
Player = GameObject.Find("Player");
}
private int direction = 1;//移动的方向,1向右,-1向左
private float speed = 0.5f;
void Update(){
var pos = Player.transform.position;
pos.x += direction*Time.deltaTime*speed;
if(pos.x>=1.5f){//当大于1.5f时改变移动方向
direction = -1;
}
if(pos.x<=-1.5f){//当小于-1.5f时改变移动方向
direction = 1;
}
Player.transform.position = pos;
Mat.SetVector("_PlayerPos",Player.transform.position);//设置玩家位置
Mat.SetFloat("_Dist",Radius);//设置距离
}
}
总结
这个shader虽然简单,但在做一些效果时还是可以有些启发,变通,如需配套代码,可以从作者github获取