unity摄像机的rt技术初探

2020.2.17——开工的第一天

闲话少说,今天来说下unity的中如何截取摄像机渲染那个图以及深度信息。
参考网址:
https://jiangxh1992.blog.csdn.net/article/details/100746757
https://zhuanlan.zhihu.com/p/84662573
https://zhuanlan.zhihu.com/p/61563576

rt的方法有两种:

  1. 使用SetTargetBuffers
  2. 使用command buffer

首先介绍第一个方法:
我们的目标是将摄像机绘制的颜色缓冲和深度缓冲显示在屏幕上:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SetTargetBuffers : MonoBehaviour
{
    public RenderTexture rt;
    public int width = 1334;
    public int height = 750;
    public int depth = 24;
    public RenderTextureFormat format = RenderTextureFormat.ARGB32;
    public Camera mainCamera;
    public Shader shader;
    public MeshRenderer meshRender;

    void Update()
    {
        if(Input.GetKeyDown(KeyCode.A))
        {
            Debug.LogError("创建rt");
            rt = new RenderTexture(width, height, depth, format);
        }
        
        if(Input.GetKeyDown(KeyCode.B))
        {
            Debug.LogError("渲染rt");
            mainCamera.SetTargetBuffers(rt.colorBuffer, rt.depthBuffer);
        }

        if(Input.GetKeyDown(KeyCode.C))
        {
            Debug.LogError("采样rt");
            Material mt = new Material(shader);
            meshRender.material = mt;
            meshRender.sharedMaterial.SetTexture("_MainTex", rt);
        }
    }
}

shader代码:

Shader "Unlit/SetRT"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        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;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = tex2D(_MainTex, i.uv);
                return col;
            }
            ENDCG
        }
    }
}

在这里插入图片描述

2.第二种方法commandbuffer

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

public class CommandBufferDemo : MonoBehaviour
{
    public Transform targetObj; // 要渲染的模型

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

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

Shader "Unlit/CommandBuffer"
{
	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
			)
			{
				float4 col = tex2D(_MainTex, i.uv);
				GRT0 = col;
				GRT1 = float4(0, 1, 0, 0);
				GRT2 = float4(1, 1, 0, 0);
				GRTDepth = 0.5;
			}
			ENDCG
		}
	}
}

实验结果:
在这里插入图片描述

在这里插入图片描述

发布了610 篇原创文章 · 获赞 96 · 访问量 33万+

猜你喜欢

转载自blog.csdn.net/wodownload2/article/details/104360166