Unity的延迟渲染(一)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity的延迟渲染(一)相关的知识,希望对你有一定的参考价值。
参考技术A 本文不是延迟渲染原理的陈述,阅读本文之前,建议先了解了延迟渲染的底层实现原理:替换帧缓冲,绑定缓冲附件之类。哪怕你对OpenGL的延迟渲染已经很了解了,你对Unity中如何使用延迟渲染可能也是一脸懵逼,下面直接正文
Unity中使用延迟渲染需要了解一些Unity ShaderLab的内置变量。这里只说延迟渲染相关的比较重要的几个:
在Unity中
的Pass,在Unity的RenderPath设定为Deferred时,或者在摄像机的RenderPath设定为Deferred时,Unity会自动将该Pass渲染输出到缓冲附件中。而输出语义设定为SV_TARGET0, SV_TARGET1, SV_TARGET2...(或者COLOR0, COLOR1, COLOR2)
因为不同的输出信息实际上需要不同的精度,而Unity这几个输出语义似乎并没有给出具体的精度信息(我确实没找到,如果有请指出),但是Unity有给出几个建议的用法,陈列如下:
例如:
至此,缓冲附件渲染完毕,接下来就是缓冲附件的应用,计算光照
Unity的延迟渲染通道的末尾就进入正向渲染通道,在正向渲染通道中使用缓冲附件来计算光照,在CGPROGRAM中声明:
_CameraGBufferTexture0对应SV_TARGET0
_CameraGBufferTexture1对应SV_TARGET1
以此类推...
而后就像采样普通纹理一样采样这几个纹理缓冲,得到像素信息,进行光照计算即可。
如有错误请指正,谢谢。
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已在内存中,可以保存图片到本地供后续使用。
以上是关于Unity的延迟渲染(一)的主要内容,如果未能解决你的问题,请参考以下文章
unity 中Deferred Lighting (延迟光照)