トップ > 【Unity】コンピュートシェーダーでメッシュを変形させる方法を紹介します!
更新日 2022/7/28

【Unity】コンピュートシェーダーでメッシュを変形させる方法を紹介します!

コンピュートシェーダーでメッシュを変形させる方法を紹介します。
ちょうどウニの3Dアバターが欲しいと思っていたのでスフィアを元に作っていきます。


実行時にメッシュのコピーを作る

スフィアを元形状として使いますが直接頂点を変形してしまうと他にも影響が出てしまいますので、
Instantiateメソッドでメッシュのコピーを作りそれをメッシュフィルターに設定します。

MeshFilter meshFileter = GetComponent<MeshFilter>();
Mesh mesh = Instantiate(meshFileter.sharedMesh);
meshFileter.sharedMesh = mesh;

MeshFilterにはSphereが設定されています。

ComputeMeshFilter

実行するとSphere(Clone)になりコピーされたメッシュが設定されていることが確認できます。

ComputeMeshFilterRunning

メッシュを変形させるコンピュートシェーダーを作る

頂点にスケールをかけるだけの簡単なコンピュートシェーダーを作ります。

SphereShader.compute

#pragma kernel CSMain

StructuredBuffer<float3> Vertices;
RWStructuredBuffer<float3> Result;
float Scale;

[numthreads(8,1,1)]
void CSMain (uint3 id : SV_DispatchThreadID)
{
Result[id.x] = Scale * Vertices[id.x];
}

Verticesはメッシュの頂点バッファーでResultは出力先バッファーです。
Scaleはスケール値をパラメーターとして受け取ります。
スレッド数の設定[numthreads(8,1,1)]はスクリプトで意識しなければならない項目です。


メッシュを変形させるスクリプトを作る

メッシュを変形させるスクリプトを作ります。
気を付けないといけないのはカーネルに設定したスレッド数[numthreads(8,1,1)]です。
スレッド数の倍数の要素の頂点バッファを用意しなければなりません。
例えば頂点が15個の場合、コンピュートシェーダーで使うバッファーサイズは8の倍数の16にします。
16個目の頂点は使用されませんがコンピュートシェーダー内では処理されます。
このルールを守らないとエラーが出力されますのでスレッド数には気を付けましょう。

GraphicsBufferのコンストラクタの第3引数の12はVector3のバイト数です。
sizeof(float)*3でもいいですし、
System.Runtime.InteropServices.Marshal.SizeOf<Vector3>()でも良いです。

GraphicsBufferは明示的に開放する必要があります。
OnDestroyの実装を参照して下さい。

SphereTest.cs

using UnityEngine;

public class SphereTest : MonoBehaviour
{
[SerializeField]
private ComputeShader shader;

[SerializeField, Range(0.01f, 2)]
private float scale = 1;

private GraphicsBuffer buffer;
private GraphicsBuffer vertexBuffer;

private int groupCount;

private Vector3[] vertices;
private Mesh mesh;

void Start()
{
MeshFilter meshFileter = GetComponent&lt;MeshFilter&gt;();
mesh = Instantiate(meshFileter.sharedMesh);
meshFileter.sharedMesh = mesh;

groupCount = (mesh.vertices.Length + 7) / 8;
int count = 8 * groupCount;
vertices = new Vector3[count];

buffer = new GraphicsBuffer(GraphicsBuffer.Target.Structured, count, 12);
vertexBuffer = new GraphicsBuffer(GraphicsBuffer.Target.Structured, count, 12);
vertexBuffer.SetData(mesh.vertices);
}

void OnDestroy()
{
buffer.Release();
vertexBuffer.Release();
}

void Update()
{
shader.SetFloat("Scale", scale);

int kernel = shader.FindKernel("CSMain");
shader.SetBuffer(kernel, "Vertices", vertexBuffer);
shader.SetBuffer(kernel, "Result", buffer);
shader.Dispatch(kernel, groupCount, 1, 1);

buffer.GetData(vertices);
mesh.vertices = vertices;
}
}
ComputeMeshScript

スケールパラメーターでスフィアの大きさを変更できるようになります。

ComputeMesh

コンピュートシェーダーでメッシュを変形する方法を紹介しました。
次回は頂点ごとにスケール値を持たせてスフィアをトゲトゲさせてみます。


関連ページ


Copyright ©2022 - 2024 うにぉらぼ