大元の画像はこちら。
3D描画に、PostProcessingStackV2でBloomとDoFがかかっています。
白い部分が滲んでいる(Bloom)&遠景近景がぼやけている(DoF)ことが確認できます
この画像に、
【Unity】カメラ1つでUI解像度を維持し、3D解像度だけを下げる方法
を試してみた所、何やら違和感が。※解像度は半分で、低解像度を強調するためにFilterMode.Point。
予定通り解像度は半分になった! ・・・けど、
あれ、PostProcessingStackV2の効果が消えてしまっている?
何故か?ということで、FrameDebuggerを確認した所、
モデルの描画については、指定したとおり、自分で用意したDisplayBufferに描画されている。
モデルの描画は意図通りされている様子。
ただ、PostProcessingStackを行っている部分を確認すると…
PostProcessingStackの最初の元画像を取得する部分がUnityWhiteテクスチャになってしまっている…!?
元画像が上手く取得できていないみたい。
いわゆるシェーダの
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
の"white"を引っ張ってしまっている様子。
普段のPostProcessingStackなら、
TempBuffer を _TargetPool0 にコピーしているはずなのに…。
…ということで色々確認した所、下記のことがわかってきた。
ここからは低解像度描画をするために別途用意したRenderTextureを低解像度描画用RTと記載する
描画の仕方 | モデルなどの描画 | PostProcessの元画像取得 |
---|---|---|
camera.SetTargetBuffers(低解像度描画用RT) | 低解像度描画用RTに描画される | UnityWhiteテクスチャを引っ張ってしまう |
PostProcessingStackV2 | TempBufferに描画される | TempBufferを引っ張る |
つまり、やりたい事を達成するためには下記のどれかを達成する必要がある |
- PPSV2を有効にした上でTempBufferのサイズを自由に変更することができれば、3Dのみ低解像度描画が達成できる
- 低解像度描画用RTの画像をTempBufferにコピーする事ができれば、PostProcessに画像を伝える事ができる
- PostProcessがTempBufferではなく低解像度描画用RTを拾う事ができれば、低解像度画像にPostEffectをかけることが出来る
結局色々試した所、1つのカメラではどれも達成できませんでした。
1週間近く、試しては消し、試しては消しで途方に暮れてしまった。。
ので、いっそ方針を変更して、2つカメラを用意してPostProcessingStack用にカメラを分けてみることにしました。
順番としては下記の順序となります。
- メイン描画用カメラ
2. SetTargetBuffers()で低解像度描画用RTに書き込むように設定
4. AfterEverythingタイミングでCommandBufferでSetRenderTarget(-1)で描画先をフレームバッファにする
5. AfterEverythingタイミングで低解像度描画用RTをCameraTargetにコピーする - PPSV2用のカメラ
7. メインカメラ描画の直後に描画するようにdepthを設定
8. 念の為、位置や姿勢など、メイン描画カメラと全く同じ表示となるようにしておく
9. CullingはPostProcessレイヤのみ表示するようにし、ClearFlagはDon't Clearにしてメイン描画をそのまま使う
9. PostProcessLayerを付けておいてポストプロセスをかける
という事で「メイン描画は低解像度描画用RTにモデルなどを描画し、PPSV2用はTempBufferが用意されるだろう」という目論見で試してみた結果がこれ。
DoFが効いていない…??
FlameDebuggerを確認すると、カメラを切り替えたタイミングでUpdateDepthTextureが走って、深度テクスチャが無効になっていることがわかる。
PPSV2用カメラはDon't Clearにしてるのに…。何で深度をクリアしてしまうのか…。
まぁそれでも、カメラを2つにすることでカラー情報をTempBufferに渡すことができた。
という事は、後は深度バッファをPostProcessにわたすことができれば目的が達成できそう…!
なので、先程の処理に深度バッファの取得&コピーを追加してみる
- メイン描画用カメラ
2. SetTargetBuffers()で低解像度描画用RTに書き込むように設定
3. CommandBufferでAfterDepthTextureのタイミングで深度バッファをキャプチャしておく
4. AfterEverythingタイミングでCommandBufferでSetRenderTarget(-1)で描画先をフレームバッファにする
5. AfterEverythingタイミングで低解像度描画用RTをCameraTargetにコピーする - PPSV2用のカメラ
7. メインカメラ描画の直後に描画するようにdepthを設定
8. 念の為、位置や姿勢など、メイン描画カメラと全く同じ表示となるようにしておく
9. CullingはPostProcessレイヤのみ表示するようにし、ClearFlagはDon't Clearにしてメイン描画をそのまま使う
10. AfterDepthTextureタイミングで、キャプチャ済み深度バッファをBuiltinRenderTextureType.Depthにコピーする
11. PostProcessLayerを付けておいてポストプロセスをかける
できた画像がこちら。※わかりやすくするために、3D側解像度は半分にしています。
ちゃんと3D解像度は半分になりつつ、PostProcessingStackV2の効果もかかっていることが確認できます。
FrameDebuggerも確認。
PPSV2用カメラのUpdateDepthTextureの後処理で深度バッファをコピーできていることが見えます。
という事で、カメラ1つで何とかしようとしすぎた事で時間がかかってしまいましたが、なんとか目的達成できました。
同じ苦労をする人が少しでも減ると良いですね。。