
こんにちは、SGEコア技術本部(コアテク)のグラフィックスチームの清原です。 今回はUnity上で3DとUIのハイブリッド解像度を実現する「Reso Dynamix」をOSSとして公開したので、それについてご紹介します。
3DとUIの解像度を変えたい
Unityでゲームを開発しているときに、GPUのパフォーマンス的な問題で描画解像度を落としたい場合があります。しかし、全体の描画解像度を下げてしまうと、テキストの視認性が落ちてしまい、文字がつぶれて読めないといった問題が起きることがあります。
そこで、3Dの描画解像度のみを下げたいというケースがよくあります。
このような場合、UIのRender ModeがScreen Space Overlayであれば、URPAssetsのRender Scaleを変更するだけで3Dの描画解像度を下げることができます。

しかし、UI CanvasのRender ModeがScreen Space CameraやWorld SpaceになっているとUIの解像度まで下がってしまいます。

このような要望はゲームの開発ではよくあることなので、Screen Space Cameraが利用されているケースも多くあります。 しかしUnityにはカメラごとにRender Scaleを変更する機能がありません。そのため、Render Scaleを変更するとUIまで解像度が落ちてしまいます。
Reso Dynamixはこの問題を解決するOSSです。
Reso Dynamixの仕組みと機能の紹介
Reso Dynamixがやっていることは次のようになっていて、非常にシンプルな実装です。
- 3Dカメラ描画用の低解像度のRender Textureを作成して、3Dカメラの描画先に設定する
- 1のRender Textureを元々の描画先にBlit
- UIを普通に描画
このように、非常にシンプルな実装なのですが、URPのRender Scaleを利用せずに描画解像度を下げているため、いくつかの設定を正しく行わないと、Forward+ではライトカリングがうまく動かなくなり、 Reflection ProbeやAdditional Lightなどの当たり方に不具合が生じます。

Reso Dynamixではこのような問題も対応を入れています。
具体的には次のようにシェーダーのグローバルパラメーターの_ScaledScreenParamsに描画解像度に合わせた適切な値を設定しています。
var width = Screen.width * _resoDynamixController.BaseCameraRenderScale; var height = Screen.height * _resoDynamixController.BaseCameraRenderScale; cmd.SetGlobalVector(ScaledScreenParams, new Vector4(width, height, 1.0f + 1.0f / width, 1.0f + 1.0f / height));
それ以外にも、複数のベースカメラ+UIカメラで描画しているシーンであっても、個別でレンダリング解像度を設定できるようになっています。 これは、パフォーマンス的な問題が起きていたプロダクトでは、複数のカメラでレンダリングを行っており、カメラによっては解像度を落としたくない、という要望があったためです。

また、3Dだけではなく、UIの描画負荷が問題になっているプロジェクトもあり、最終出力先の描画解像度も変更することができるようになっています。

最後に
Reso Dynamixでは難しいことはやっていないのですが、UIの描画でScreen Space Cameraを使っている、多くのゲーム開発で課題になることを解決するOSSとなっています。 また、このOSSはプロジェクトの終盤に開発を行ったため、問題が顕在化しがちな開発終盤でも柔軟に導入できる設計になっています。
このOSSが皆様の開発の一助になると幸いです。