ikoan unity 開発メモ

Unityに関するアレコレを日々つづっていこうと思います

RenderTextureのアルファ

環境

Unity2018.2.14f1

概要

Cameraで撮ったRenderTextureを表示する際にRenderTextureのアルファ成分についてわかりづらく、よく忘れるのでまとめました。

問題

CameraAの表示内容をRenderTextureに焼き込み、それをUnlitなどで他のmeshに描画すると、CameraAのClean Colorが表示されてしまいます。これはRenderTextureの特性ともいえるでしょう。
多くの場合、このCameraAのCleanColorは透過されてほしいはずです。
これをshaderを自作することで、解決したいと思います。

解決策の概念

shaderのBlendがキモとなります。
Blend colorA colorB
もしくは
Blend colorA colorB , alphaA alphaB
のような記述になります。
どちらもAの方が該当シェーダで表現される色情報、Bがすでにフレームバッファに書き込まれている色情報と考えていいと思います。
詳しくは
Unity - マニュアル: ShaderLab構文:Blending
をご覧ください。
正直よくわからないと思います。(私もまだ感覚でしかつかめていません汗)

上記のBlendを元に整理していきます。
やりたいことは
1)「RenderTexture」のRGB値はCameraAで表示される「α(透過)も反映させた色値」、A値は「フレームバッファに書き込まれている色情報にかかるべきα情報」と保存する
2)「RenderTexture」を書き込む時に、RGBはそのまま上書きする、AはRenderTextureのA値を有効に活用する、やり方になります。

実装方法

CameraAのCleanColorは0x000000FFにします。
また、CameraAで描画するオブジェクトに使用するシェーダーのBlend部分は
Blend SrcAlpha OneMinusSrcAlpha, Zero OneMinusSrcAlpha
とします。
CleanColorを0x000000にする理由は、RenderTextureに描き込み時のBlendする際に0だったらアルファがいくつであろうとブレンドされたところで影響がないためです。
また、Blend構文を上記にすることで、RGBにはアルファが考慮された数値が入力され、AにはRenderTextureにオブジェクトが描画される際に背景にかかるα値が保存されることとなります。
つまり描画されるオブジェクトでアルファが1の部分にはA=0が保存され、アルファが0の部分にはA=1が保存されます。オブジェクトが描画されない場所もCleanColorのアルファが1のため、A=1となっています。
まとめると、RenderTextureの色値情報として
RGBはCameraAが描画する内容として、オブジェクトのアルファも考慮された内容。
Aはオブジェクトが描画される場所はオブジェクトのアルファの逆値、その他は1が入っている状態となっています。

そうした上で、RenderTextureを描画する際のshaderのblend構文を
Blend One SrcAlpha
都することで、RenderTextureの表示内容はそのまま表示しつつ、背景色にも適切にアルファが計算されてブレンドされることとなります。