
在Urp12之后提供了新的接口SetupRenderPasses,对Pass的设置应当在SetupRenderPasses中进行
旧
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
{
// The target is used before allocation
m_CustomPass.Setup(renderer.cameraColorTarget);
// Letting the renderer know which passes are used before allocation
renderer.EnqueuePass(m_ScriptablePass);
}
新
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
{
// Letting the renderer know which passes are used before allocation
renderer.EnqueuePass(m_ScriptablePass);
}
public override void SetupRenderPasses(ScriptableRenderer renderer, in RenderingData renderingData)
{
// The target is used after allocation
m_CustomPass.Setup(renderer.cameraColorTarget);
}
注:此处调用的m_CustomPass.Setup方法为约定的初始化方法,可以自己定义(也可叫别的名字),一般用于将RenderTexture引用传入ScriptableRendererPass
1) 在ScriptableRendererPass中定义Dispose方法 并将未释放的RTHandle调用其方法
public void Dispose()
{
_customOpaqueTexture?.Release();
}
2) 在ScriptableRendererFeature中override Dispose方法 并调用Pass的Dispose方法
protected override void Dispose(bool disposing)
{
renderObjectsPass.Dispose();
}
3. 一些接口调整
public static readonly RenderTargetHandle CameraTarget不再存在 使用k_CameraTarget(在ScriptableRenderPass直接使用,或在外部使用ScriptableRenderPass.k_CameraTarget)替代
scriptableRenderer.cameraColorTarget现已废弃 使用scriptableRenderer.cameraColorTargetHandle替代
scriptableRenderer.cameraDepthTarget 现已废弃 使用 scriptableRenderer.cameraDepthTargetHandle代替
现在两者统一使用新接口 旧
private RenderTargetHandle _cameraOpaqueTexture;
新
private RTHandle _cameraOpaqueTexture;
2. Identifier - Color & Depth 拆分
示例: 旧
RenderTargetIdentifier m_Destination;
新
RTHandle m_DestinationColor;
RTHandle m_DestinationDepth;
3. 初始化RenderTexture
+ 一并替换为 或 如果为则使用
If the render target does not change within the lifetime of the application, use the method to allocate an RTHandle target. 文档链接
在中不需要设置分辨率,分辨率由统一自动控制,在申请时只需要传入格式的降采样参数即可,原始分辨率可传入
旧
private RenderTargetHandle _opaqueMap;
public override void OnCameraSetup( CommandBuffer cmd, ref RenderingData renderingData )
{
var cameraTextureDescriptor = renderingData.cameraData.cameraTargetDescriptor;
opaqueMap.Init( _textureName );
int width = DownSampleUtil.GetLength( cameraTextureDescriptor.width, downSample );
int height = DownSampleUtil.GetLength( cameraTextureDescriptor.height, downSample );
cmd.GetTemporaryRT( _opaqueMap.id, width, height, 0, FilterMode.Bilinear, RenderTextureFormat.ARGBHalf );
this.ConfigureTarget( _opaqueMap.Identifier() );
this.ConfigureClear( ClearFlag.All, Color.clear );
}
新
private RTHandle _opaqueMap;
public override void OnCameraSetup( CommandBuffer cmd, ref RenderingData renderingData )
{
var cameraTextureDescriptor = renderingData.cameraData.cameraTargetDescriptor;
cameraTextureDescriptor.colorFormat = RenderTextureFormat.ARGBHalf;
cameraTextureDescriptor.depthBufferBits = 0;
RenderingUtils.ReAllocateIfNeeded(
ref _opaqueMap,
Vector2.one * 0.5f,
cameraTextureDescriptor,
FilterMode.Bilinear,
TextureWrapMode.Clamp,
false,
1,
0f,
"_OpaqueMap"
);
this.ConfigureTarget( _opaqueMap );
this.ConfigureClear( ClearFlag.All, Color.clear );
}
注:和相比,RTHandle初始化时会在name(如)后追加描述字符串,所以无法再从全局中取到名为的纹理,如果需要将RTHandle生成的纹理全局使用(如交给Shader),可用下述写法
Shader.SetGlobalTexture("_OpaqueMap", _opaqueMap);
另外,如果需要将现有RenderTexture作为RTHandle的纹理,可用下述写法
_opaqueMap = RTHandles.Alloc(Shader.GetGlobalTexture("_OpaqueMap"));
4. 释放RenderTexture
如果该RTHandle由Feature传入,则只需在方法中将其置为即可
public override void OnCameraCleanup( CommandBuffer cmd )
{
_transparentObjectsTexture = null;
_transparentObjectsDepthAttachment = null;
}
如果该RTHandle由当前Pass初始化并不会被后续代码引用(如非全局Texture),则可在中Release掉
旧
public override void OnCameraCleanup( CommandBuffer cmd )
{
cmd.ReleaseTemporaryRT( _opaqueMap.id );
}
新
public override void OnCameraCleanup( CommandBuffer cmd )
{
_opaqueMap?.Release();
}
commandBuffer.Blit替换
官方不再推荐在URP管线中使用 commandBuffer.Blit(Blit) 进行渲染 现在使用Blitter类实现相应功能
不使用material全屏渲染
旧
cmd.Blit( _transparentObjectsTexture.Identifier(), _cameraOpaqueTexture.Identifier() );
新
Blitter.BlitCameraTexture2D(cmd,_transparentObjectsTexture, _cameraOpaqueTexture);
使用material全屏渲染
旧
Blit( cmd, tempTarget.Identifier(), target.Identifier(), _blurMaterial )
新
Blitter.BlitCameraTexture(cmd, tempTarget, target, _blurMaterial, 0);
Blitter使用Material时对应Shader修改
如果此前使用CG,需要改为HLSL
使用Blitter后,会将Source的纹理传递给名为的Texture(也可将RTHandle传递为GlobalTexture,进而在Shader中按新名称引用,需注意纹理回收),且在Shader中对其采样需要使用SAMPLE_TEXTURE2D方法
在Shader中需要引入以下两个HLSL文件(不能再引用UnityCG.cginc 请慎重)
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl" 注: _BlitTexture已在Blit.hlsl中定义,不需要重复定义
该示例以直接采样输出全屏图为例
struct Attributes
{
#if SHADER_API_GLES
float4 positionOS : POSITION;
float2 uv : TEXCOORD0;
#else
uint vertexID : SV_VertexID;
#endif
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct Varyings
{
float2 texcoord : TEXCOORD0;
// UNITY_FOG_COORDS(1) //目前没找到可以替代的
float4 positionCS : SV_POSITION;
UNITY_VERTEX_OUTPUT_STEREO
};
Varyings vert(Attributes v)
{
Varyings o;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
#if SHADER_API_GLES
float4 pos = v.positionOS;
float2 uv = v.uv;
#else
float4 pos = GetFullScreenTriangleVertexPosition(v.vertexID);
float2 uv = GetFullScreenTriangleTexCoord(v.vertexID);
#endif
o.positionCS = pos;
o.texcoord = uv * _BlitScaleBias.xy + _BlitScaleBias.zw;
return o;
}
Fragment修改
half4 frag(Varyings i) : SV_Target
{
half4 col = SAMPLE_TEXTURE2D(_BlitTexture, sampler_LinearRepeat, i.uv);
return col;
}
参考文献
https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@14.0/manual/upgrade-guide-2022-2.html
https://zenn.dev/sakutaro/articles/convert_blitter
https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@14.0/manual/renderer-features/how-to-fullscreen-blit.html
https://docs.unity3d.com/Packages/com.unity.render-pipelines.core@13.1/api/UnityEngine.Rendering.Blitter.html
https://forum.unity.com/threads/rendertargethandle-is-obsolete-deprecated-in-favor-of-rthandle.1211052/
https://teodutra.com/unity/shaders/urp/graphics/2020/05/18/From-Built-in-to-URP/