Unity CommandBuffer渲染MTR到自定义的RenderTexture

目标:

延迟渲染技术下,有时我们要先把模型的Diffuse、Normal、Depth、Roughness等数据先渲到自定义的RenderTexture中(CPU中,以几张贴图的形式保存到Disk),然后进行后面的延迟光照等计算。

思路:

  • 方法一
    可以用Camera直接渲,只要将自定义的RT设置为相机的target即可(MRT要使用Camera的SetTargetBuffers (RenderBuffer[] colorBuffer, RenderBuffer depthBuffer)方法设置渲染目标);
  • 方法二
    即使用CommandBuffer自定义渲染指令来渲,这样可以针对某个模型来渲贴图,获取模型的Render对象,调用CommandBuffer的DrawRenderer(render,material)方法并在合适的时机执行CommandBufferGPU指令。

CommandBuffer方法实现

先自定义几张RT并初始化用来缓冲渲染结果,自定义一个新的CommandBuffer设置渲染目标和绘制指令,然后在合适的时机执行CommandBuffer即可:

    public Transform targetObj; // 要渲染的模型

    RenderTexture[] rtGBuffers = new RenderTexture[3]; // 自定义RT
    RenderTexture depthBuffer = null; // 深度RT
    public Material GBufferMaterial; // 渲染MRT的材质,自定义shader
    Renderer targetRender; // 模型的Render对象

    void Start()
    	{
        targetRender = targetObj.GetComponent<MeshRenderer>();
        CommandBuffer cmd = new CommandBuffer();
        cmd.name = "TestGBufferCMD";
        RenderTargetIdentifier[] rtGBuffersID = new RenderTargetIdentifier[rtGBuffers.Length];
        for (int i = 0; i < rtGBuffers.Length; ++i)
        {
            rtGBuffers[i] = RenderTexture.GetTemporary(Screen.width, Screen.height, 0);
            rtGBuffersID[i] = rtGBuffers[i];
        }
        depthBuffer = RenderTexture.GetTemporary(Screen.width, Screen.height, 0);

        cmd.SetRenderTarget(rtGBuffersID, depthBuffer); // 设置渲染目标
        cmd.ClearRenderTarget(true, true, Color.clear, 1);
        cmd.DrawRenderer(targetRender, GBufferMaterial); // 绘制指令
        
        // 这里可以在相机的渲染事件中自动执行CommandBuffer
        Camera.main.AddCommandBuffer(CameraEvent.BeforeForwardOpaque,cmd);
        }

另外也可以在合适的位置手动执行CommandBuffer:
Graphics.ExecuteCommandBuffer(cmd);

自定义的MRT shader示例:

Shader "Unlit/GBuffer"
{
	Properties
	{
		_MainTex ("MainTex", 2D) = "white" {}
	}
	SubShader
	{
		Tags { "RenderType"="Opaque" }
		LOD 100
        Cull Back

		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			
			#include "UnityCG.cginc"

			struct appdata
			{
				float4 vertex : POSITION;
                float3 normal : NORMAL;
				float2 uv : TEXCOORD0;
			};

			struct v2f
			{
				float2 uv : TEXCOORD0;
                float4 normal : TEXCOORD1;
				float4 vertex : SV_POSITION;
			};

			sampler2D _MainTex;
			float4 _MainTex_ST;
			
			v2f vert (appdata v)
			{
				v2f o;
				o.vertex = UnityObjectToClipPos(v.vertex);
				o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                o.normal = float4(v.normal,0);
				return o;
			}
			
			void frag (v2f i,
            out half4 GRT0:SV_Target0,
            out half4 GRT1:SV_Target1,
            out half4 GRT2:SV_Target2,
            out float GRTDepth:SV_Depth
            )
			{                
				// sample the texture
				float4 col = tex2D(_MainTex, i.uv);
                GRT0 = col;
                GRT1 = i.normal;
                GRT2 = float4(0,0,1,0);
                GRTDepth = 0.5;
			}
			ENDCG
		}
	}
}

查看结果

运行Unity,打开Frame Debuger截一帧,找到我们的CommandBuffer那条指令,然后可以看到有我们的三个RT,选择不同RT查看贴图结果。自定义RT已在内存中,可以保存图片到本地供后续使用。

在这里插入图片描述

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mr_厚厚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值