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的方法有两种:
- 使用SetTargetBuffers
- 使用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
}
}
}
实验结果: