トップ > 【Unity】ComputeShaderの使い方を紹介します!
更新日 2022/7/25

【Unity】ComputeShaderの使い方を紹介します!

ComputeShaderはGPGPU(General-Purpose computing on Graphics Processing Units)を実現するためのシェーダーです。 高負荷な物理演算やメッシュ変形などをGPUで並列計算することができます。 このページではUnityでのComputeShaderの実装方法をシンプルに解説します。


ComputeShaderの作成

プロジェクト上で右クリックから 作成 > シェーダー > コンピュートシェーダー でコンピュートシェーダーを作成します。

ComputeShader_Create

作成されたコンピュートシェーダーは以下の内容になります。

// Each #kernel tells which function to compile; you can have many kernels
#pragma kernel CSMain

// Create a RenderTexture with enableRandomWrite flag and set it
// with cs.SetTexture
RWTexture2D<float4> Result;

[numthreads(8,8,1)]
void CSMain (uint3 id : SV_DispatchThreadID)
{
// TODO: insert actual code here!

Result[id.xy] = float4(id.x & id.y, (id.x & 15)/15.0, (id.y & 15)/15.0, 0.0);
}

コードの解説をします。

#pragma kernel CSMain

CSMain関数をカーネル(エントリーポイント)として宣言します。
宣言されたカーネルはスクリプトから呼び出せるようになります。


RWTexture2D<float4> Result;

RWTexture2DはRead/Write可能な2Dテクスチャです。
float4なのでxyzwが各色成分rgbaになります。


[numthreads(8,8,1)]

1つのスレッドグループで実行されるスレッドの数を定義します。
今回のケースはX方向が8でY方向が8の8x8サイズが1つのスレッドグループです。


void CSMain (uint3 id : SV_DispatchThreadID)

SV_DispatchThreadIDセマンティクスで定義されたuint3 idは3D座標になります。
今回のシェーダーでは2Dテクスチャーを利用しているのでid.xyはテクスチャーのXY座標になります。


Result[id.xy] = float4(...);

Resultテクスチャーのxy座標に計算結果を代入します。


スクリプトの作成

先程のコンピュートシェーダーをそのまま使えるようにスクリプトを実装します。

using UnityEngine;

public class TestScript : MonoBehaviour
{
[SerializeField]
private ComputeShader computeShader;

private RenderTexture renderTexture;

public void Start()
{
renderTexture = new RenderTexture(64, 64, 0, RenderTextureFormat.ARGB32);
renderTexture.enableRandomWrite = true;

int kernel = computeShader.FindKernel("CSMain");
computeShader.SetTexture(kernel, "Result", renderTexture);
computeShader.Dispatch(kernel, 8, 8, 1);
}

void OnGUI()
{
GUI.DrawTexture(new Rect(0, 0, 64, 64), renderTexture, ScaleMode.ScaleToFit, false);
}
}

コードの解説をします。

[SerializeField]
private ComputeShader computeShader;

コンピュートシェーダーをUnityエディターで設定できるようにSerializeField属性を付加します。
インスペクター上でコンピュートシェーダーを設定して下さい。

ComputeShader

renderTexture = new RenderTexture(64, 64, 0, RenderTextureFormat.ARGB32);
renderTexture.enableRandomWrite = true;

レンダーテクスチャーを作成しコンピュートシェーダーからの書き込みを可能にするためにenableRandomWriteをtrueにして下さい。


int kernel = computeShader.FindKernel("CSMain");
computeShader.SetTexture(kernel, "Result", renderTexture);
computeShader.Dispatch(kernel, 8, 8, 1);

CSMain関数のカーネル番号を取得してSetTexture関数で出力先のレンダーテクスチャーを設定します。Dispatch関数で各方向のスレッドグループ数を指定してカーネルを呼び出します。今回は64x64のレンダーテクスチャーを[numthreads(8,8,1)]カーネルで使用するのでX方向のスレッドグループ数は8、Y方向のスレッドグループ数も8になります。

以下のようにスレッドグループ数を計算することもできます。

uint x, y, z;
computeShader.GetKernelThreadGroupSizes(kernel, out x, out y, out z);
computeShader.Dispatch(kernel, (int)(64 / x), (int)(64 / y), 1);

GUI.DrawTexture(new Rect(0, 0, 64, 64), renderTexture, ScaleMode.ScaleToFit, false);

OnGUI関数でレンダーテクスチャーを描画します。コンピュートシェーダーでアルファ値に0が代入されているのでアルファブレンドをオフにします。


実行して確認

実行してコンピュートシェーダーの計算結果が描画されることを確認します。

ComputeShader_Play

今回はテクスチャーを使用したコンピュートシェーダーの実装方法を紹介しました。
次回はテクスチャーより実装しやすいバッファーを使った方法を紹介したいと思います。

ComputeShaderの使い方 その2へ続きます。

関連ページ


Copyright ©2022 - 2024 うにぉらぼ