コンピュートシェーダーは、通常のレンダリングパイプラインと異なって、グラフィックスカード上で動作するプログラムです。これは超並列 GPGPU アルゴリズム、またはゲームレンダリングの一部を加速させるために使用できます。効果的に使用するためには、しばしば GPU アーキテクチャおよび並列アルゴリズム、さらには DirectCompute、OpenCL、または CUDA に関する深い知識が必要です。
Unity のコンピュートシェーダーは DirectX 11 の DirectCompute テクノロジに非常に近いものです。コンピュートシェーダーを実行できるプラットホームは以下のとおりです。
シェーダーアセット と似て、コンピュートシェーダーはプロジェクト上で *.compute
拡張子のついたアセットファイルです。DirectX 11 スタイルの HLSL 言語で記述されていて、最小限の #pragma
コンパイルディレクティブ用いてどの関数がコンピュートシェーダーカーネルを用いるか指定します。
コンピュートシェーダーを使用するための最低限のサンプルです。
// test.compute
#pragma kernel FillWithRed
RWTexture2D<float4> res;
[numthreads(1,1,1)]
void FillWithRed (uint3 dtid : SV_DispatchThreadID)
{
res[dtid.xy] = float4(1,0,0,1);
}
上記のサンプルでは際立って面白いことはやっておらず、ただ出力テクスチャを赤で埋めます。
言語は標準的な DirectX 11 HLSL であり、例外として #pragma kernel FillWithRed
ディレクティブを使用しています。ひとつのコンピュートシェーダーアセットは最低限ひとつの実行可能な “コンピュートカーネル” を含む必要があり、その関数は e #pragma ディレクティブにより指定します。ファイルの中に複数のカーネルを含むことが可能であり、複数の #pragma kernel
行を追加するのみです。
コメント行に #pragma kernel
を複数記入していると、実際に #pragma kernel
を使用したときにコンパイルエラーになってしまうので注意してください。
#pragma kernel
行はオプションとして、カーネルをコンパイルしている間に複数のプリプロセッサーマクロを後に続けて定義することが可能です。サンプルとしては、
#pragma kernel KernelOne SOME_DEFINE DEFINE_WITH_VALUE=1337
#pragma kernel KernelTwo OTHER_DEFINE
// ...
スクリプトの中で、ComputeShader
型の変数を定義して、アセットに対する参照を割り当てて、その後は ComputeShader.Dispatch 関数を用いて実行することができます。詳細についてはスクリプトリファレンスの ComputeShader を参照してください。
コンピュートシェーダーと密接に関連しているのが ComputeBuffer クラスであり、任意のデータバッファを定義します( DirectX 11 用語では “structured buffer”)。Render Texture も、“random access” フラグ (DirecX 11 用語では “unordered access view”) が設定されていれば、またコンピュートシェーダーから書き込むことができます。RenderTexture.enableRandomWrite を参照してください。
テクスチャおよびサンプラは Unity で別オブジェクトではないため、コンピュートシェーダーで使用するためには Unity 特有のルールに従う必要があります。
Texture2D MyTex の場合、SamplerState samplerMyTex
) のいずれかにします。"SamplerState MyLinearClampSampler"
- これによりフィルターとして Linear、かつ、Wrap モードとして Clamp が使用されます。標準シェーダーのように、Unity は、HLSL から GLSL に コンピュートシェーダーを変換できます。したがって、最も簡単なクロスプラットフォームの構築については、HLSL でコンピュートシェーダーを記述することを推奨します。
複数の異なるシェーダーをプラットフォーム上で動作させるために考慮すべき制限事項は以下のとおりです。
一般的に、コンピュートシェーダーのファイルは HLSL で記述され、必要なプラットホームすべてに自動的にコンパイルまたは変換されます。ですが、GLSLプラットホームを省く(つまり、HLSLプラットホームだけを残す)か、GLSLのコードを手動で書くために、変換を制限することができます。
CGPROGRAM
と ENDCG
のキーワードに囲まれたコンピュートシェーダーソースは、OpenGL/GLSL プラットフォーム用には処理されません。GLSLPROGRAM
と ENDGLSL
のキーワードに囲まれたコンピュートシェーダーソースは、GLSL ソースとして扱われ、出力されます。これは、OpenGL/GLSL プラットフォームをターゲットとしているときのみ有効です。注意: クロスプラットフォームビルドには、上記のいずれも適していません。なぜなら、それらは、プラットフォームから実行するコンピュートシェーダーソースにかなり密接に結びついているからです。