Koo叔说Shader-贴图切换

前言

再介绍一个简单的效果,贴图切换,根据目标距离远近切换贴图

贴图切换

先看效果

随着小黄鸭的移动,贴图以小黄鸭中心为半径变化。这个方法可以做出许多效果,如放大镜效果,画圆形遮罩等

原理分析

  • 主要就是根据提供的目标点(也就是小黄鸭的中心点)和贴图的距离进行不同的采样

具体实现

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获取

猜你喜欢

转载自blog.csdn.net/qq_31967569/article/details/81109023