简单Shader实现刮刮乐效果

Unity Shader的测试题,类似刮刮乐那种。

下面是实现的一个效果(随便找的图片),是在一个plane中根据按钮来滑动鼠标来进行刮刮乐的操作,即plane上的一张图片上显示不同图片的某区域的颜色值。

首先是Shader部分,我们就根据纹理的a值来判断区域内该显示哪个图片的颜色值。

Shader "Unlit/changeC"
{
    Properties
    {
        _ColorTex("Color Texture", 2D) = "white"{}

        //三张图片的纹理
        _FirstTex("First Texture", 2D) = "white"{}
        _SecondTex("Second Texture", 2D) = "white"{}
        _ThirdTex("Third Texture", 2D) = "white"{}
    }
    SubShader
    {


        Pass
        {
            CGPROGRAM
            #pragma vertex vert_img
            #pragma fragment frag
            #include "UnityCG.cginc"

            sampler2D _ColorTex;
            sampler2D _FirstTex;
            sampler2D _SecondTex;
            sampler2D _ThirdTex;

            fixed4 frag(v2f_img i):SV_Target
            {
                //根据纹理的a值来判断显示哪个图片的纹理
                float r = tex2D(_ColorTex, i.uv).a;
                if(r > 0.66) {
                    return tex2D(_FirstTex, i.uv);
                }
                if (r > 0.33) {
                    return tex2D(_SecondTex, i.uv);
                }
                return tex2D(_ThirdTex, i.uv);
            }
            ENDCG
        }
    }
        FallBack "Diffuse"
}

在Unity场景中,创建一个plane(3D中的,因为要定位鼠标的位置,就直接用3D中的碰撞来检测),为其增加一个Tag

 下面是c#代码,挂在创建的plane上

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

public class changeC : MonoBehaviour
{
    //擦除的像素半径
    public int radius = 20;
    //控制显示效果的纹理
    Texture2D colorTint;
    //像素高度
    public int picWidth, picHeight;
    //显示的图片
    float picIndex;

    void Start()
    {
        picIndex = 0f;

        colorTint = new Texture2D(picWidth, picHeight, TextureFormat.Alpha8, false);

        for(int i = 0; i < picWidth; i++)
        {
            for(int j=0;j<picHeight;j++)
            {
                colorTint.SetPixel(i, j, new Color(0, 0, 0, 1));
            }
        }

        colorTint.Apply();
        GetComponent<MeshRenderer>().material.SetTexture("_ColorTex", colorTint);

    }

    private void Update()
    {
        if(Input.GetMouseButton(0))
        {
            //print("a");
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;
            if(Physics.Raycast(ray,out hit))
            {
                if(hit.collider.tag == "TintTex")
                {
                    print("b");
                    changeColor(hit.textureCoord);
                }
            }
        }
    }

    void changeColor(Vector2 uv)
    {
        Vector2Int o = new Vector2Int((int)(colorTint.width * uv.x), (int)(colorTint.height * uv.y));
        print("color");
        for (int x = -radius; x < radius; x++)
        {
            for (int y = -radius; y < radius; y++)
            {
                if (x * x + y * y < radius * radius)
                {
                    colorTint.SetPixel(o.x + x, o.y + y, new Color(0,0,0,1)*picIndex);
                }
            }

        }
        colorTint.Apply();
        GetComponent<MeshRenderer>().material.SetTexture("_ColorTex", colorTint);
    }

    public void SetPicIndex(float i)
    {
        picIndex = i;
    }
}

再创建三个button,为其绑定事件(每个button直接调用c#代码中的setPicIndex,传入不同参数即可),把plane拖入其中就大功告成了。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class test3 : MonoBehaviour
{
    public GameObject plane;
    

    private void Start()
    {
        Button btn = this.GetComponent<Button>();
        btn.onClick.AddListener(OnClick);
    }
    void OnClick()
    {
        plane.GetComponent<changeC>().SetPicIndex(0);
    }
}
原文地址:https://www.cnblogs.com/sjp737420/p/13996731.html