🐡
UnityでShader始めてみた No.2 四角形・多角形
前置き
前回は動的に三角形を生成し、シェーダーを適用してみました。
今回は四角形を作成し、汎用性を高めるためにN角形でも適用できるようにしてみます。
シェーダーと言うよりC#プログラムメインですね。
四角形
動的に四角形のメッシュを生成しています。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(MeshRenderer))]
[RequireComponent(typeof(MeshFilter))]
public class DynamicCreateSquare : MonoBehaviour
{
private void Start()
{
var mesh = new Mesh();
// 頂点座標の配列
mesh.vertices = new Vector3[]
{
new Vector3(-1f, 1f, 0),
new Vector3( 1f, 1f, 0),
new Vector3( 1f, -1f, 0),
new Vector3(-1f, -1f, 0),
};
// インデックス配列
mesh.triangles = new int[]
{
0, 1, 2,
0, 2, 3
};
// 頂点に色情報を割り当てる
mesh.SetColors(new Color[] { Color.red, Color.green, Color.blue, Color.cyan });
// メッシュをセット
var filter = GetComponent<MeshFilter>();
filter.sharedMesh = mesh;
// シェーダーセット
var renderer = GetComponent<MeshRenderer>();
renderer.material = new Material(Shader.Find("Unlit/Color"));
}
}
頂点座標の配列
四角形の頂点は4つなので、それぞれの座標を指定します。
インデックス配列
四角形を作っていますが、メッシュは三角形が2個の組み合わせでできています。
そのため、インデックス配列では2つの三角形を作る頂点を指定します。
つまり0, 1, 2 と 0, 2, 3 です。
時計回りに指定しないと、表側と認識されずに表示されないので注意です。
シェーダーを適用して実行した画面がこちら。
頂点の色の境目で三角形が2個あるのが見えますね。
多角形
このまま正五角形、正六角形...と座標を指定しても良いのですが、プログラムで賢く実装してみます。
必要な値は、頂点座標とインデックス配列の2つです。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(MeshRenderer))]
[RequireComponent(typeof(MeshFilter))]
public class DynamicCreatePolygon : MonoBehaviour
{
[Header("頂点の数")]
public int vertexNum = 5;
Color[] colors = { Color.red, Color.blue, Color.green, Color.yellow, Color.cyan, Color.magenta };
private void Start()
{
Vector3[] vertexPosition = new Vector3[vertexNum + 1]; // 頂点座標の配列
int[] indexArray = new int[3 * vertexNum]; // インデックス配列
Color[] vertexColor = new Color[vertexNum + 1]; // 頂点色配列
float rotationAngle = 2 * Mathf.PI / vertexNum; // 回転角
var mesh = new Mesh();
// 頂点座標
for (int i = 0; i < vertexNum; i++)
{
vertexPosition[i + 1] = new Vector3(Mathf.Sin(i * rotationAngle), Mathf.Cos(i * rotationAngle), 0);
}
// インデックス配列
for (int i = 0; i < vertexNum; i++)
{
indexArray[3 * i] = 0;
indexArray[3 * i + 1] = i + 1;
if (i+2 != vertexNum+1)
{
indexArray[3 * i + 2] = i + 2;
}
else
{
indexArray[3 * i + 2] = 1;
}
}
// 頂点の色を決める
for (int i = 0; i < vertexColor.Length; i++)
{
vertexColor[i] = colors[Random.Range(0, colors.Length)];
}
mesh.vertices = vertexPosition;
mesh.triangles = indexArray;
mesh.colors = vertexColor;
var filter = GetComponent<MeshFilter>();
filter.sharedMesh = mesh;
var renderer = GetComponent<MeshRenderer>();
renderer.material = new Material(Shader.Find("Unlit/Color"));
}
}
頂点座標の配列
三角形のとき、頂点から頂点へは120度回転しています。
四角形のときは90度、五角形のときは72度です。
つまり、ラジアンに直すと
ずつ回転していることになります。
これをあらかじめ計算しておきます。
インデックス配列
正五角形のとき頂点は5個ありますが、三角形で構成するには6個必要です。
指定する3つの頂点のうち、最初は必ず0番目となります。
- 0, 1, 2
- 0, 2, 3
- 0, 3, 4
- 0, 4, 5
- 0, 5, 1
の5つを指定すれば良さそうです。
これをプログラムに書きますが、0, 5, 1のときだけ、if文で場合分けして実装しました。
シェーダーをつけて実行します。
右から順に正五角形, 正六角形, 正十角形です。
良い感じに表示できました!
参考リンク
【Unity】四角形のポリゴンを作ってテクスチャを貼る
Unityでプロシージャルモデリング (三角形・四角形・正多角形)
Discussion