The jonki

呼ばれて飛び出てじょじょじょじょーんき

【Unity】オリジナルMeshの作成とVertex ColoredなShader

頂点4つ(三角形2つ)のシンプルなMeshを作成し、その各頂点に色情報を与えてきれいなグラデーションをやってみました。OpenGL初めてやると大体こういうのやりますよね。Unityに最初からあるPlaneのMeshは頂点数が多いですが、今回作った左のSimplePlaneはスクショから確認できるようにかなりシンプルになっているのがわかります。


参考にさせていただいたサイト

今回はMesh作成と色情報を同じスクリプトで行ってますが、よく使うMeshは下記サイトを参考して、AssetDatabase.SaveAssets()しといた方が便利だと思います。

Shader側

今回シェーダー側では特に何もせず、Vertexの色情報を使うような設定を書いておくだけです。このCustom ShaderをセットしたMaterialを作成し、今回のSimplePlaneを作成するGameObjectのMeshRendererにセットしておきましょう。ここは今回マニュアルで準備しておきます。どのようなものがGameObjectにアタッチされてるかは最初のスクショを参考にしてください。
ShaderLab syntax: Color, Material, Lighting

Shader "Custom/VertexColored" {
Properties {
}
    SubShader {
            Pass {
                    ColorMaterial AmbientAndDiffuse
            }
    } 
}

C#

開始時にMeshを作り、次に色情報を各頂点に適用します。この辺りはOpenGLとか得意な人は特に違和感なく書けそうですね。三角形2つで四角を作り、それに対応するuv座標も入れておきます。

using UnityEngine;
using System.Collections;

public class CreateColoredMesh : MonoBehaviour {
	void Start () {
		var meshFilter = gameObject.AddComponent<MeshFilter>();
		if (meshFilter == null) return;
		Mesh mesh = CreateSimplePlane();
		meshFilter.mesh = mesh;

		ChangeSimplePlaneMeshColor();
	}

	private Mesh CreateSimplePlane() {

		Mesh mesh = new Mesh();
		mesh.name = "SimplePlane";
		Vector3[] vertices = new Vector3[] {
			new Vector3( 0.5f,  0.5f, 0.0f),
			new Vector3(-0.5f, -0.5f, 0.0f),
			new Vector3(-0.5f,  0.5f, 0.0f),
			new Vector3( 0.5f, -0.5f, 0.0f)
		};
		int[] triangles = new int[] {
			0, 1, 2,
			3, 1, 0
		};
		Vector2[] uv = new Vector2[] {
			new Vector2(1.0f, 1.0f),
			new Vector2(0.0f, 0.0f),
			new Vector2(0.0f, 1.0f),
			new Vector2(1.0f, 0.0f)
		};

		mesh.vertices = vertices;
		mesh.triangles = triangles;
		mesh.uv = uv;
		mesh.RecalculateNormals();
		mesh.RecalculateBounds();

		return mesh;
	}

	private void ChangeSimplePlaneMeshColor() {
		Mesh mesh = GetComponent<MeshFilter>().mesh;
		Vector3[] vertices = mesh.vertices;
		Color[] colors = new Color[vertices.Length];
		colors[0] = Color.red;
		colors[1] = Color.blue;
		colors[2] = Color.yellow;
		colors[3] = Color.green;

		mesh.colors = colors;
	}
}

最後に

動的に色情報などをグリングリンさせたければShader側に処理を持っていった方が良いと思いますが、今回のように静的なグラデーションを用意したければ今回のような方法がかなり便利になりそうですね。