首页 > 解决方案 > 关于 Unity 上多个渲染目标的渲染行为的问题。还是Shader的问题?

问题描述

我尝试在 Unity 中使用多个渲染目标来获取通用渲染图像、深度图像和 Id(为每种材质预先分配)图像。

首先,看这张图。

RenderTexture多个渲染目标的输出分配在三个垂直堆叠的框中。从下方,分配了渲染图像、深度图像和 Id 图像。

我希望深度和 id 图像只在盒子所在的地方着色。但是,我遇到了前一帧的颜色仍然存在的问题。我认为这是 z 缓冲区的问题,但我无法解决。

这是github 上的示例存储库。

着色器代码

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# 代码

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();
    }
}

标签: c#unity3dshader

解决方案


推荐阅读