【Unity】RTHandleシステムの参照サイズとスケールを変更する

投稿者: | 2024-03-20

RTHandleシステムの参照サイズとスケール(rtHandleScale)を画面に表示してみました。

RTHandleSystemをインスタンス化して、スクリーンサイズを参照サイズとして設定します。ゲームビューのサイズを変更して値を見ます。

RTHandleSystemを使う

RTHandleSystemをインスタンス化して初期化します。RTHandleSystem.AllocメソッドでRTHandleを割り当てます。全画面のテクスチャと解像度が1/4のテクスチャを作っています。第一引数の値を使って、最大参照サイズに対する解像度を決定します。

   RTHandleSystem rtHandleSystem;
    RTHandle rtHandle1;
    RTHandle rtHandle2;

    // Start is called before the first frame update
    void Start()
    {
        // RTHandleSystemをインスタンス化
        rtHandleSystem = new RTHandleSystem();

        // 初期化する
        rtHandleSystem.Initialize(Screen.width, Screen.height);      
        rtHandleSystem.SetReferenceSize(Screen.width, Screen.height);

        // RTHandleの割り当て
        rtHandle1 = rtHandleSystem.Alloc(Vector2.one, depthBufferBits: DepthBits.Depth32, dimension: TextureDimension.Tex2D, name: "RTHandle1");
        rtHandle2 = rtHandleSystem.Alloc(Vector2.one * 0.5f, depthBufferBits: DepthBits.Depth32, dimension: TextureDimension.Tex2D, name: "RTHandle2");
    }

Updateメソッドで、参照サイズとして画面サイズを設定しています。ゲームビューの大きさが変わるとそれにあわせて参照サイズが変わります。

    void Update()
    {
        // 画面サイズを参照サイズとして設定
        rtHandleSystem.SetReferenceSize(Screen.width, Screen.height);

画面サイズを変更する

RTHandleSystem.rtHandlePropertiesの値を画面に表示してみます。この構造体にrtHandleScaleや参照サイズが定義されています。プレイボタンを押した直後のrtHandleScaleは1になっています。

Gameビューを大きくします。スケールは1のままcurrentViewportSizeとcurrentRenderTargetSizeの値が大きくなります。

前のフレームの値はpreviousViewportSizeとpreviousRenderTargetSizeに格納されています。

        if (rtHandleProperties.currentViewportSize.x != rtHandleProperties.previousViewportSize.x)
        {
            diffText = "";
            diffText += "\n\nrtHandleScale.zw : " + rtHandleProperties.rtHandleScale.z.ToString("F2") + " " + rtHandleProperties.rtHandleScale.w.ToString("F2");
            diffText += "\npreviousViewportSize : " + rtHandleProperties.previousViewportSize;
            diffText += "\npreviousRenderTargetSize: " + rtHandleProperties.previousRenderTargetSize;
        }

        text.text += diffText;

ゲームビューを小さくします。スケールとcurrentViewportSizeの値が下がり、currentRenderTargetSizeは変わりません。currentViewportSizeは現在の参照サイズ、currentRenderTargetSizeが最大の参照サイズです。

rtHandleScaleはcurrentViewportSizeをcurrentRenderTargetSizeで割った値になっています。

RTHandleSystem.ResetReferenceSizeメソッドで、参照サイズをスクリーンサイズにリセットします。スケールが1に、currentRenderTargetSizeがcurrentViewportSizeと同じ値になりました。

    public void ResetReferenceSize()
    {
        rtHandleSystem.ResetReferenceSize(Screen.width, Screen.height);
    }

RTHandles

静的なRTHandlesクラスから、RTHandleSystemのデフォルトのインスタンスが利用できます。別途インスタンス化する必要はありません。

        rtHandle1 = RTHandles.Alloc(Vector2.one, depthBufferBits: DepthBits.Depth32, dimension: TextureDimension.Tex2D, name: "RTHandle1");
        rtHandle2 = RTHandles.Alloc(Vector2.one * 0.5f, depthBufferBits: DepthBits.Depth32, dimension: TextureDimension.Tex2D, name: "RTHandle2");

         var rtHandleProperties = RTHandles.rtHandleProperties;

デフォルトのインスタンスは、HDRenderPipelineのコンストラクタで初期化されています。

            RTHandles.Initialize(Screen.width, Screen.height);

RenderメソッドやResetCameraSizeForAfterPostProcessメソッドのなかで、参照サイズが設定されています。

Vector2Int maxSize = new Vector2Int(1, 1);

for (int i = 0; i < renderRequestIndicesToRender.Count; ++i)
{
    var renderRequestIndex = renderRequestIndicesToRender[i];
    var renderRequest = renderRequests[renderRequestIndex];
    var hdCamera = renderRequest.hdCamera;

    maxSize.x = Math.Max((int)hdCamera.finalViewport.size.x, maxSize.x);
    maxSize.y = Math.Max((int)hdCamera.finalViewport.size.y, maxSize.y);
}

// Here we use the non scaled resolution for the RTHandleSystem ref size because we assume that at some point we will need full resolution anyway.
// This is necessary because we assume that after post processes, we have the full size render target for debug rendering
// The only point of calling this here is to grow the render targets. The call in BeginRender will setup the current RTHandle viewport size.
RTHandles.SetReferenceSize(maxSize.x, maxSize.y);

スクリプト

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Rendering;

public class RTHandleTest : MonoBehaviour
{

    [SerializeField] Text text;
    RTHandleSystem rtHandleSystem;
    RTHandle rtHandle1;
    RTHandle rtHandle2;

    // Start is called before the first frame update
    void Start()
    {
        // RTHandleSystemをインスタンス化
        rtHandleSystem = new RTHandleSystem();

        // 初期化する
        rtHandleSystem.Initialize(Screen.width, Screen.height);      
        rtHandleSystem.SetReferenceSize(Screen.width, Screen.height);

        // RTHandleの割り当て
        rtHandle1 = rtHandleSystem.Alloc(Vector2.one, depthBufferBits: DepthBits.Depth32, dimension: TextureDimension.Tex2D, name: "RTHandle1");
        rtHandle2 = rtHandleSystem.Alloc(Vector2.one * 0.5f, depthBufferBits: DepthBits.Depth32, dimension: TextureDimension.Tex2D, name: "RTHandle2");
    }

    string diffText;

    // Update is called once per frame
    void Update()
    {
        // 画面サイズを参照サイズとして設定
        rtHandleSystem.SetReferenceSize(Screen.width, Screen.height);

        // RTHandleシステムのプロパティ
        var rtHandleProperties = rtHandleSystem.rtHandleProperties;

        // スケールと現在の参照サイズを表示
        text.text = "rtHandleScale : " + rtHandleProperties.rtHandleScale + "\n" +
            "currentRenderTargetSize : " + rtHandleProperties.currentRenderTargetSize + "\n" +
            "currentViewportSize : " + rtHandleProperties.currentViewportSize;

        if (rtHandleProperties.currentRenderTargetSize.x != 0 && rtHandleProperties.currentRenderTargetSize.y != 0)
        {
            text.text += "\nViewport / RenderTexture x : " + (rtHandleProperties.currentViewportSize.x / (float)rtHandleProperties.currentRenderTargetSize.x).ToString("F2");
            text.text += "\nViewport / RenderTexture y : " + (rtHandleProperties.currentViewportSize.y / (float)rtHandleProperties.currentRenderTargetSize.y).ToString("F2");
        }

        // 各RTHandleの情報を表示
        if (rtHandle1 != null && rtHandle2 != null)
        {
            text.text += "\n\nrtHandle1.scaleFactor : " + rtHandle1.scaleFactor;
            text.text += "\nrtHandle2.scaleFactor : " + rtHandle2.scaleFactor;

            text.text += "\n\nrtHandle1.referenceSize : " + rtHandle1.referenceSize;
            text.text += "\nrtHandle2.referenceSize : " + rtHandle2.referenceSize;

            text.text += "\n\nrtHandle1.rt : " + rtHandle1.rt.width + " " + rtHandle1.rt.height;
            text.text += "\nrtHandle2.rt : " + rtHandle2.rt.width + " " + rtHandle2.rt.height;
        }

        // 前のフレームのスケールと参照サイズを表示
        if (rtHandleProperties.currentViewportSize.x != rtHandleProperties.previousViewportSize.x)
        {
            diffText = "";
            diffText += "\n\nrtHandleScale.zw : " + rtHandleProperties.rtHandleScale.z.ToString("F2") + " " + rtHandleProperties.rtHandleScale.w.ToString("F2");
            diffText += "\npreviousViewportSize : " + rtHandleProperties.previousViewportSize;
            diffText += "\npreviousRenderTargetSize: " + rtHandleProperties.previousRenderTargetSize;
        }

        text.text += diffText;
    }

    private void OnDisable()
    {
        // RTHandleを解放
        rtHandle1.Release();
        rtHandle2.Release();
    }

    // 参照サイズをリセット
    public void ResetReferenceSize()
    {
        rtHandleSystem.ResetReferenceSize(Screen.width, Screen.height);
    }

}
参考:
https://docs.unity3d.com/ja/Packages/com.unity.render-pipelines.core@10.7/manual/rthandle-system-using.html
https://docs.unity3d.com/Packages/com.unity.render-pipelines.core@7.1/api/UnityEngine.Rendering.RTHandleSystem.html

コメントを残す

メールアドレスが公開されることはありません。