Column

プログラミング
[Unityメモ2] 3DのRenderTextureを定義する方法
2023.06.09

3Dの医療画像処理において、GPUでデータを処理する場合3次元のボクセルデータを3次元テクスチャとして扱うのが定石かと思います。

単に画像として読み込むだけであればTexture3Dを利用すればよいのですが、ComputeShaderを使ってGPU上で画像の編集を行う場合はさらにRenderTextureが必要です。

3DのRenderTextureを作るにはRenderTextureDescriptorを使う必要があります。コードは以下の通り。

//空のRenderTextureを定義する関数。
//引数として画像の幅と高さ、奥行き(DICOMで言うところのColumns, Rows, Slice数に該当)
private static RenderTexture CreateRT3(int width, int height, int depth)
{
        var rd = new RenderTextureDescriptor(width, height);
        rd.dimension = UnityEngine.Rendering.TextureDimension.Tex3D;
        rd.volumeDepth = depth;
        rd.colorFormat = RenderTextureFormat.RFloat;
        rd.enableRandomWrite = true;

        var tex = new RenderTexture(rd);
        tex.Create();
        return tex;
}

Texture3Dとは異なり、RenderTextureは直接CPUのメモリからデータの転送は出来ません。Texture3Dのデータから処理した結果を書き込む先として使うのが良いと思います。

※Render Textureは明示的にReleaseする必要があります。3Dで大きなデータを作りまくるとWindowsごとフリーズするので気を付けてください。

colorFormatはその名の通り、1ピクセルあたりのデータ内容をGPUに伝えるものです。
例えばARGB32であれば、A(透明度) R(赤)G(緑)B(青)がそれぞれ8bitずつ順番に並び、合計32bit (4byte)で1ピクセルを表すことを表します。この場合はARGBのそれぞれは0~255の値に納まります。
CTやMRIの12ビットの白黒画像を扱う場合、複数チャンネルは不要なのでRFloatを用います。この場合はRedのチャンネルとしてFloatが入ります。(メモリ節約するためにint16などを使っても良いと思います。)シェーダからピクセルの値にアクセスする場合は Texture[id].rのように最後に.rをつけてアクセスできます。

[参考] UnityのRenderTextureFormat

https://docs.unity3d.com/ja/2019.4/ScriptReference/RenderTextureFormat.html