最近のCGだとあまり使用する機会がない気がする頂点カラーですが、たまにどんな感じの色付けになっているのか確認したいケースがあります。ただ、Unityではデフォルトの機能で確認する方法がないので、頂点カラーを表示するためのシェーダーを書く必要があります。
今回は、Unityで頂点カラーを表示する簡単なシェーダーの作り方を紹介します。
Contents
頂点カラーを持つモデルを用意する
まず初めに、今回のシェーダーは頂点カラーを持つモデルでないと効果がありません。頂点カラーを持つモデルはBlenderなどのDCCで作成するか、以下のコードをオブジェクトにアタッチして作成してください。
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(MeshFilter))]
[RequireComponent(typeof(MeshRenderer))]
[ExecuteInEditMode]
public class MeshGeneratorWithColor : MonoBehaviour
{
void Start()
{
CubeWithColor();
}
private void OnValidate()
{
CubeWithColor();
}
void CubeWithColor()
{
List<Vector3> vertices = new List<Vector3>() {
// 0
new Vector3(0.0f, 0.0f, 0.0f), // 正面
new Vector3(1.0f, 0.0f, 0.0f),
new Vector3(1.0f, 1.0f, 0.0f),
new Vector3(0.0f, 1.0f, 0.0f),
// 4
new Vector3(1.0f, 1.0f, 0.0f), // 上面
new Vector3(0.0f, 1.0f, 0.0f),
new Vector3(0.0f, 1.0f, 1.0f),
new Vector3(1.0f, 1.0f, 1.0f),
// 8
new Vector3(1.0f, 0.0f, 0.0f), // 右面
new Vector3(1.0f, 1.0f, 0.0f),
new Vector3(1.0f, 1.0f, 1.0f),
new Vector3(1.0f, 0.0f, 1.0f),
// 12
new Vector3(0.0f, 0.0f, 0.0f), // 左面
new Vector3(0.0f, 1.0f, 0.0f),
new Vector3(0.0f, 1.0f, 1.0f),
new Vector3(0.0f, 0.0f, 1.0f),
// 16
new Vector3(0.0f, 1.0f, 1.0f), // 背面
new Vector3(1.0f, 1.0f, 1.0f),
new Vector3(1.0f, 0.0f, 1.0f),
new Vector3(0.0f, 0.0f, 1.0f),
// 20
new Vector3(0.0f, 0.0f, 0.0f), // 下面
new Vector3(1.0f, 0.0f, 0.0f),
new Vector3(1.0f, 0.0f, 1.0f),
new Vector3(0.0f, 0.0f, 1.0f),
};
List<int> triangles = new List<int> {
0, 3, 2, 0, 2, 1, //前面 ( 0 - 3)
5, 6, 7, 5, 7, 4, //上面 ( 4 - 7)
8, 9,10, 8,10,11, //右面 ( 8 - 11)
15,14,13, 15,13,12, //左面 (12 - 15)
16,18,17, 16,19,18, //奥面 (16 - 19)
23,20,21, 23,21,22, //下面 (20 - 23)
};
List<Color> colors = new List<Color>
{
Color.blue,
Color.cyan,
Color.gray,
Color.green,
Color.grey,
Color.magenta,
Color.red,
Color.yellow,
Color.blue,
Color.cyan,
Color.gray,
Color.green,
Color.grey,
Color.magenta,
Color.red,
Color.yellow,
Color.blue,
Color.cyan,
Color.gray,
Color.green,
Color.grey,
Color.magenta,
Color.red,
Color.yellow,
};
Mesh mesh = new Mesh(); // メッシュを作成
mesh.Clear(); // メッシュ初期化
mesh.SetVertices(vertices); // メッシュに頂点を登録する
mesh.SetColors(colors); // 頂点カラーを登録
mesh.SetTriangles(triangles, 0); // メッシュにインデックスリストを登録する
mesh.RecalculateNormals(); // 法線の再計算
// 作成したメッシュをメッシュフィルターに設定する
MeshFilter meshFilter = GetComponent<MeshFilter>();
meshFilter.mesh = mesh;
}
}
なお、動的にメッシュを作成するコードでは、以下の部分でメッシュにカラー情報を渡しているので注意してください。
Mesh mesh = new Mesh();
mesh.SetColors(colors);
カラー情報をシェーダー内で受け渡す
メッシュから渡ってきたカラー情報を、最終的にはフラグメントシェーダーに渡していきます。
struct appdata //メッシュデータが持つ情報
{
float4 vertex : POSITION;
float4 color : COLOR;
};
struct v2f //ラスタライズ後に格納される
{
float4 vertex : SV_POSITION;
float4 color : COLOR;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex); //メッシュの頂点情報をMVP変換
o.color = v.color; //メッシュのカラー情報を代入
return o;
}
fixed4 frag (v2f i) : SV_Target
{
return i.color; //渡ってきたカラー情報を表示
}
シェーダー全体
シェーダーの全容は以下のとおりです。
Shader "CAGraphicsAcademy/VertexColor"
{
Properties
{
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float4 color : COLOR;
};
struct v2f
{
float4 vertex : SV_POSITION;
float4 color : COLOR;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.color = v.color;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
return i.color;
}
ENDCG
}
}
}
まとめ
頂点カラーを単純に表示するシェーダーの紹介でしたが、頂点カラーはそんなに使われないので、使いどころは限られるかもしれません。分かりきっていることかもしれませんが、メッシュに色を表示するならテクスチャを作ってください。