I tried to get a general render image, depth image and Id (pre-assigned for each material) image using multiple render target in Unity.
First, look at this image.
RenderTexture output by multiple rendering targets is assigned in the three vertically stacked boxes. From below, the rendered image, depth image, and Id image are assigned.
I expected the depth and id images to be colored only where the box is. However, I ran into an issue where the color of the previous frame remained. I thought it was a problem around z buffer, but I couldn't solve it.
this is sample repository on github.
shader code
Shader "Custom/MRT"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Id ("Id", float) = 0.5
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
float depth : TEXCOORD1;
};
struct buffer {
float4 buf1 : SV_Target0;
float4 buf2 : SV_Target1;
float4 buf3 : SV_Target2;
};
sampler2D _MainTex;
float4 _MainTex_ST;
float _Id;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
COMPUTE_EYEDEPTH(o.depth.x);
o.depth *= _ProjectionParams.w;
//for debug visualizing
o.depth *= -1;
o.depth += 1;
//end debug
return o;
}
buffer frag (v2f i)
{
buffer o;
// sample the texture
fixed4 col = tex2D(_MainTex, i.uv);
o.buf1 = col;
o.buf2 = float4(i.depth.x, 0, 0, 1);
o.buf3 = float4(0, _Id, 0, 1);
return o;
}
ENDCG
}
}
}
C# code
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
public class MRTCamera : MonoBehaviour
{
public GameObject Template;
public Material StandardMaterial;
public Shader MrtShader;
private Camera _camera;
private RenderTexture[] _renderTextureArray;
private RenderBuffer[] _colorBuffers;
private RenderTexture _depthBuffer;
void Start()
{
_camera = GetComponent<Camera>();
_camera.enabled = false;
_renderTextureArray = new RenderTexture[3]
{
new RenderTexture(640,480, 0, RenderTextureFormat.Default),
new RenderTexture(640,480, 0, RenderTextureFormat.Default),
new RenderTexture(640,480, 0, RenderTextureFormat.Default),
};
_renderTextureArray[0].Create();
_renderTextureArray[1].Create();
_renderTextureArray[2].Create();
_colorBuffers = new RenderBuffer[]{ _renderTextureArray[0].colorBuffer, _renderTextureArray[1].colorBuffer, _renderTextureArray[2].colorBuffer };
_depthBuffer = new RenderTexture(640, 480, 24, RenderTextureFormat.Depth);
_depthBuffer.Create();
var o1 = Instantiate(Template, new Vector3(0, 2, 0), Quaternion.identity);
o1.GetComponent<Renderer>().material = new Material(StandardMaterial) { mainTexture = _renderTextureArray[0] };
var o2 = Instantiate(Template, new Vector3(0, 3, 0), Quaternion.identity);
o2.GetComponent<Renderer>().material = new Material(StandardMaterial) { mainTexture = _renderTextureArray[1] };
var o3 = Instantiate(Template, new Vector3(0, 4, 0), Quaternion.identity);
o3.GetComponent<Renderer>().material = new Material(StandardMaterial) { mainTexture = _renderTextureArray[2] };
}
void Update()
{
_camera.SetTargetBuffers(this._colorBuffers, this._depthBuffer.depthBuffer);
_camera.RenderWithShader(MrtShader, "");
}
void OnDestroy()
{
_renderTextureArray[0].Release();
_renderTextureArray[1].Release();
_renderTextureArray[2].Release();
_depthBuffer.Release();
}
}
