Unity hand-painted Mesh realizes color gradient

 The requirements I received are as follows:

Please see the final renderings

Let's start 

Simplifying the requirement is to create a Mesh with a width*2 and a color gradient based on 2 points.

Creating a square Mesh requires four points, and what I need here is only two, so I regard the two points as the center points and use a Width to get the four points, which is here.

                Vector3 pos1 = nextDrawnMesh.transform.position + new Vector3(-width, 0, 0);
                Vector3 pos2 = nextDrawnMesh.transform.position + new Vector3(width, 0, 0);
                Vector3 pos3 = currentDrawnMesh.transform.position + new Vector3(width, 0, 0);
                Vector3 pos4 = currentDrawnMesh.transform.position + new Vector3(-width, 0, 0);

You can see that it is a Vector3, so this value will have different directions when attached to different positions. You can test it yourself to get the desired effect.

Or you can define four points by yourself and assign values ​​by yourself without the calculation here.

So there is a method addpos, which is used to add all points. Addpos corresponds to adding points. name corresponds to adding color addcolor.

                currentDrawnMesh.SetShaderColor("_ColorTop", color);
                currentDrawnMesh.SetShaderColor("_ColorMid", color);
                nextDrawnMesh.SetShaderColor("_ColorBot", color);

You don’t need to understand that these three things are the attributes of the Shader. The Shader fields come here, which is a trap. This attribute name is not the name of the attribute in the Shader code. To set the attributes in the Shader, you must carefully look at the Shader. Correspond to each attribute name under the panel. I got it wrong at the beginning. I can’t modify the name in the code when I go to the Shader!

public class ProtractMeshController : MonoBehaviour
{
    public static ProtractMeshController interest;
    public float width = 0.002f;
    public GameObject MeshPosObj;
    public Color color;
    private void Awake()
    {
        interest = this;
        InitProtractMeshPos();
        widthRecording = width;
    }

    float widthRecording ;

    public void Update()
    {
        if(widthRecording!= width)
        {
            widthRecording = width;
            InitProtractMeshPos();
        }
    }

    public void AddPos(List<GameObject> pos){
 
        for(int  i=0;i< pos.Count; i++)
        {
            GameObject go = GameObject.Instantiate(MeshPosObj, pos[i].transform.position,Quaternion.identity);
            go.transform.parent = this.transform;
        }

        InitProtractMeshPos();
    }

    public void AddColor(List<Color32> colors)
    {
        if (this.transform.childCount <= 0) return;

        for (int i = 0; i < colors.Count; i++)
        {
            if (i + 1 < colors.Count)
            {
                DrawnMesh currentDrawnMesh = transform.GetChild(i).GetComponent<DrawnMesh>();
                DrawnMesh nextDrawnMesh = transform.GetChild(i + 1).GetComponent<DrawnMesh>();
                currentDrawnMesh.SetShaderColor("_ColorTop", colors[i + 1]);
                currentDrawnMesh.SetShaderColor("_ColorMid", colors[i + 1]);
                currentDrawnMesh.SetShaderColor("_ColorBot", colors[i]);
            }
        }
    }

    /// <summary>
    /// 初始化mesh点位
    /// </summary>
    public void InitProtractMeshPos()
    {
        for (int i = 0; i < transform.childCount; i++)
        {
            if (i + 1 < transform.childCount)
            {
                DrawnMesh currentDrawnMesh = transform.GetChild(i).GetComponent<DrawnMesh>();
                DrawnMesh nextDrawnMesh = transform.GetChild(i + 1).GetComponent<DrawnMesh>();
                Vector3 pos1 = nextDrawnMesh.transform.position + new Vector3(-width, 0, 0);
                Vector3 pos2 = nextDrawnMesh.transform.position + new Vector3(width, 0, 0);
                Vector3 pos3 = currentDrawnMesh.transform.position + new Vector3(width, 0, 0);
                Vector3 pos4 = currentDrawnMesh.transform.position + new Vector3(-width, 0, 0);
                currentDrawnMesh.posList = new List<Vector3>() { pos4, pos3, pos2, pos1 };
                currentDrawnMesh.SetMesh();
                currentDrawnMesh.SetShaderColor("_ColorTop", color);
                currentDrawnMesh.SetShaderColor("_ColorMid", color);
                nextDrawnMesh.SetShaderColor("_ColorBot", color);
            }
        }
    }

    public void Clean()
    {
        for(int i = transform.childCount; i> 0; i--)
        {
            GameObject.Destroy(transform.GetChild(i - 1).gameObject);
        }
    }
}

 This is drawing Mesh! Be careful to add UVs to the mesh you draw, otherwise the material will look wrong!

public class DrawnMesh : MonoBehaviour
{
    public float proportion = 1f;
    public List<Vector3> posList = new List<Vector3>();//赋值顺序为顺时针或者逆时针(为世界坐标位置)
    public MeshRenderer meshRenderer;


    public GameObject ga;
    void Awake()
    {
        meshRenderer = GetComponent<MeshRenderer>();
    }

    /// <summary>
    /// 设置shader的颜色属性
    /// </summary>
    /// <param name="attributeName"> 三种 "_ColorTop","_ColorMid","_ColorBot" </param>
    /// <param name="color"></param>
    public void SetShaderColor(string attributeName, Color color)
    {
        meshRenderer.materials[0].SetColor(attributeName, color);
    }

    public void SetMiddle(float value)
    {
        meshRenderer.materials[0].SetFloat("_Middle", value);
    }

    public void SetMesh()
    {
        List<Vector3> vertices = new List<Vector3>();
        for (int i = 0; i < posList.Count; i++)
        {
            Vector3 pos = (posList[i] - transform.position) * proportion;
            vertices.Add(pos);
        }

        DrawPentagon(vertices);
    }

    void DrawPentagon(List<Vector3> vertices)
    {
        Mesh mesh = new Mesh();
        mesh.name = gameObject.name;
        int triangleAmount = vertices.Count - 2;
        int[] triangles = new int[3 * triangleAmount];

        //根据三角形的个数,来计算绘制三角形的顶点顺序(索引)  
        //顺序必须为顺时针或者逆时针  
        for (int i = 0; i < triangleAmount; i++)
        {
            triangles[3 * i] = 0;
            triangles[3 * i + 1] = i + 1;
            triangles[3 * i + 2] = i + 2;
        }

        Vector2[] baseUVs = new Vector2[] { new Vector2(0, 0), new Vector2(1, 0), new Vector2(1, 1), new Vector2(0, 1), };

        mesh.vertices = vertices.ToArray();
        mesh.uv = baseUVs;
        mesh.triangles = triangles;

        GetComponent<MeshFilter>().mesh = mesh;
    }
}

 This is the shader for color collision.

Shader "Unlit/Gradient"
{
	Properties
	{
		[PerRendererData] _MainTex("Sprite Texture", 2D) = "white" {}
		_ColorTop("Top Color", Color) = (1, 1, 1, 1)
		_ColorMid("Mid Color", Color) = (1, 1, 1, 1)
		_ColorBot("Bot Color", Color) = (1, 1, 1, 1)
		_Middle("Middle", Range(0.001, 0.999)) = 1
		_test("Test", Range(0.001, 0.999)) = 1
	}
		SubShader
		{
		Tags {"Queue" = "Background"  "IgnoreProjector" = "True"}
		LOD 100
		ZWrite On
		Pass
		{
		CGPROGRAM
#pragma vertex vert  
#pragma fragment frag
#include "UnityCG.cginc"
		fixed4 _ColorTop;
	fixed4 _ColorMid;
	fixed4 _ColorBot;
	float  _Middle;
	float _test;
	struct v2f
	{
		float4 pos : SV_POSITION;
		float4 texcoord : TEXCOORD0;
	};
	v2f vert(appdata_full v)
	{
		v2f o;
		if (v.vertex.y > _test)
		{
			v.vertex.y = _test;
	}
		o.pos = UnityObjectToClipPos(v.vertex);
	o.texcoord = v.texcoord;
	return o;
	}
		fixed4 frag(v2f i) : COLOR
	{
		fixed4 c = lerp(_ColorBot, _ColorMid, i.texcoord.y / _Middle) * step(i.texcoord.y, _Middle);
	c += lerp(_ColorMid, _ColorTop, (i.texcoord.y - _Middle) / (1 - _Middle)) * step(_Middle, i.texcoord.y);
	c.a = 1;
	return c;
	}
		ENDCG
		}
		}
}

Guess you like

Origin blog.csdn.net/weixin_52599679/article/details/134304174