本日はコンピュートシェーダー枠です。
現在はコンピュートシェーダーの概要を学びながらある条件の頂点座標数を抽出する処理を実装しています。
〇環境
・Windows11PC
・Unity6000.0.2f1
〇コンピュートシェーダーとは?
コンピュートシェーダー(Compute Shader)はGPU上で実行されるプログラムで、GPGPU=GPUでの汎用的計算=シェーダーとして以外のGPUの利用用途として用いられています。
GPUでは一般的に描画のプロセスが行われていますが、近年のAIなどにみられるように物理シミュレーション、画像処理、機械学習などグラフィックの描画以外の計算をCPUではなくGPUの膨大な並列演算機能を用いて行うというものがGPGPUであり、この処理プログラムがコンピュートシェーダーです。
また、この時GPUのメモリであるVRAMを使用することができ、データの読み書きが可能です。
近年ジオメトリシェーダーステージで従来行っていた処理を、コンピュートシェーダーで置き換え、ジオメトリシェーダーステージを使用しないという実装が増えています。
またDirectX以外のグラフィックスAPIではMetalなどジオメトリシェーダーをそもそもサポートしない場合も増えています。
この理由は汎用性の向上、パフォーマンスの向上、メモリ管理に加えコンピュートシェーダーがレンダリングパイプラインの外で実行されるという点があります。
ジオメトリシェーダーの特徴であった頂点の増減などもコンピュートシェーダーを使用することで可能なため従来のジオメトリシェーダーに置き換えが始めっています。
〇C#でコンピュートシェーダーを呼び出す
Unityではコンピュートシェーダーを使用するためにシーンからC#スクリプトを使用して呼び出します。
コンピュートシェーダーはComputeShaderクラスとして呼び出します。
public ComputeShader computeShader;
前回作成したコンピュートシェーダーを用いてY座標より下にある頂点の数を求める処理は以下のようになります。
using UnityEngine;
public class CountTrianglesBelowY0 : MonoBehaviour
{
public ComputeShader computeShader;
public MeshFilter meshFilter;
private ComputeBuffer vertexBuffer;
private ComputeBuffer indexBuffer;
private ComputeBuffer countBuffer;
void Start()
{
// メッシュを取得
Mesh mesh = meshFilter.mesh;
Vector3[] vertices = mesh.vertices;
int[] indices = mesh.triangles;
// ComputeBufferの準備
vertexBuffer = new ComputeBuffer(vertices.Length, sizeof(float) * 3);
indexBuffer = new ComputeBuffer(indices.Length, sizeof(int));
countBuffer = new ComputeBuffer(1, sizeof(int), ComputeBufferType.Raw);
// 頂点とインデックスのデータをバッファにセット
vertexBuffer.SetData(vertices);
indexBuffer.SetData(indices);
// カウント用バッファを初期化
int[] countData = new int[1] { 0 };
countBuffer.SetData(countData);
// シェーダーにバッファをセット
computeShader.SetBuffer(0, "vertexBuffer", vertexBuffer);
computeShader.SetBuffer(0, "indexBuffer", indexBuffer);
computeShader.SetBuffer(0, "countBuffer", countBuffer);
// シェーダーのディスパッチ
int triangleCount = indices.Length / 3;
computeShader.Dispatch(0, triangleCount, 1, 1);
// 結果の取得
countBuffer.GetData(countData);
int trianglesBelowY0 = countData[0];
// デバッグ出力
Debug.Log("Y=0以下にある面の数: " + trianglesBelowY0);
// バッファの解放
vertexBuffer.Release();
indexBuffer.Release();
countBuffer.Release();
}
}
これをゲームオブジェクトにアタッチし、コンピュートシェーダーとメッシュフィルターをアタッチします。

この状態で実行すると頂点の数をログとして出力しています。

コードの解説は次回行っていきます。
本日は以上です。