在URP中实现MRT

最后实现的结果

img

核心代码

  1. 在配置RT的时候将MRT绑定至当前RT
1
2
3
4
5
6
7
8
9
10
11
12
case GoRenderObjectsFeature.ECameraType.MRT:
RenderTargetIdentifier[] renderTargetIdentifiers = new RenderTargetIdentifier[4];
for (int i = 0; i < m_MRTDestinations.Length; i++)
{
//cameraTextureDescriptor.memoryless = RenderTextureMemoryless.Color;
cameraTextureDescriptor.depthBufferBits = 0;
cameraTextureDescriptor.colorFormat = RenderTextureFormat.ARGB32;
cmd.GetTemporaryRT(m_MRTDestinations[i].id, cameraTextureDescriptor);
renderTargetIdentifiers[i] = m_MRTDestinations[i].Identifier();
}
ConfigureClear(ClearFlag.Depth, m_ClearColor);
ConfigureTarget(renderTargetIdentifiers, mCameraDepthTarget);
  1. 给shader添加MRTPass,并在ForwardLit.hlsl中实现相应Frag
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Pass
{
Name "GoMRT"
Tags{"LightMode" = "GoMRT"}

Blend[_SrcBlend][_DstBlend]
ZWrite[_ZWrite]
Cull[_Cull]

HLSLPROGRAM
// ... URP的各种宏等

#pragma vertex LitPassVertex
#pragma fragment LitPassFragmentMRT

#include "LitInput.hlsl"
#include "LitForwardPass.hlsl"
ENDHLSL
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void LitPassFragmentMRT(Varyings input, out half4 buf0 : SV_Target0, out half4 buf1 : SV_Target1, out half4 buf2 : SV_Target2, out half4 buf3 : SV_Target3)
{
SurfaceData surfaceData;
InitializeStandardLitSurfaceData(input.uv, surfaceData);
InputData inputData;
InitializeInputData(input, surfaceData.normalTS, inputData);

buf0.rgb = surfaceData.albedo;
buf0.a = surfaceData.metallic;
buf1.rgb = inputData.normalWS;
buf1.a = surfaceData.smoothness;
buf2.rgb = inputData.bakedGI;
buf2.a = 0;
buf3.rgb = surfaceData.emission;
buf3.a = 0;
}
  1. 将绘制好的GBuffer绑定至GlobalTexture
1
2
3
4
for (int i = 0; i < m_MRTDestinations.Length; i++)
{
cmd.SetGlobalTexture("_GBuffer" + i, m_MRTDestinations[i].Identifier());
}
  1. 剩下就可以写一个全屏的Pass,拿到GBuffer玩耍啦