Koo叔说Shader-贴图切换

本文介绍了如何使用Shader实现根据目标距离远近切换贴图的效果,通过小黄鸭移动展示效果,可用于创建放大镜或圆形遮罩等。核心原理是依据目标点与贴图之间的距离进行采样,具体实现包括动态设置玩家位置的脚本配合。

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

前言

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

贴图切换

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

原理分析

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

具体实现

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值