【从UnityURP开始探索游戏渲染】专栏-直达
自定义渲染通道是一种改变通用渲染管道(URP)如何渲染场景或场景中的对象的方法。自定义呈现通道(RenderPass)包含自己的Render代码,可以在注入点将其添加到RenderPass中。
添加自定义呈现通道(RenderPass):
- 使用Scriptable render pass API创建自定义render pass的代码。
- 将自定的render pass注入到URP管线中的指定注入点中,有两种方式:
- 用RenderPipelineManager API注入自定义渲染通道
- 或者通过创建一个可脚本化的RendererFeature添加到URP渲染器中。
使用Scriptable render pass API创建自定义render pass
-
Example custom render pass
csusing UnityEngine; using UnityEngine.Rendering; using UnityEngine.Rendering.Universal; internal class ColorBlitPass : ScriptableRenderPass { ProfilingSampler m_ProfilingSampler = new ProfilingSampler("ColorBlit"); Material m_Material; RTHandle m_CameraColorTarget; float m_Intensity; public ColorBlitPass(Material material) { m_Material = material; renderPassEvent = RenderPassEvent.BeforeRenderingPostProcessing; } public void SetTarget(RTHandle colorHandle, float intensity) { m_CameraColorTarget = colorHandle; m_Intensity = intensity; } public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData) { ConfigureTarget(m_CameraColorTarget); } public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) { var cameraData = renderingData.cameraData; if (cameraData.camera.cameraType != CameraType.Game) return; if (m_Material == null) return; CommandBuffer cmd = CommandBufferPool.Get(); using (new ProfilingScope(cmd, m_ProfilingSampler)) { m_Material.SetFloat("_Intensity", m_Intensity); Blitter.BlitCameraTexture(cmd, m_CameraColorTarget, m_CameraColorTarget, m_Material, 0); } context.ExecuteCommandBuffer(cmd); cmd.Clear(); CommandBufferPool.Release(cmd); } }
将自定的render pass注入到URP管线中的指定注入点中
用RenderPipelineManager API注入自定义渲染通道
-
通过RenderPipelineManager的注入点委托提供执行时机,加上Camera的EnqueuePass方法注入自定义RenderPass。
cspublic class EnqueuePass : MonoBehaviour { [SerializeField] private BlurSettings settings; private BlurRenderPass blurRenderPass; private void OnEnable() { ... blurRenderPass = new BlurRenderPass(settings); // Subscribe the OnBeginCamera method to the beginCameraRendering event. RenderPipelineManager.beginCameraRendering += OnBeginCamera; } private void OnDisable() { RenderPipelineManager.beginCameraRendering -= OnBeginCamera; blurRenderPass.Dispose(); ... } private void OnBeginCamera(ScriptableRenderContext context, Camera cam) { ... // Use the EnqueuePass method to inject a custom render pass cam.GetUniversalAdditionalCameraData() .scriptableRenderer.EnqueuePass(blurRenderPass); } }
创建一个可脚本化的RendererFeature
此示例执行将屏幕染成绿色的全屏blit。
-
要创建自定义渲染通道,创建一个名为ColorBlitPass.cs的新c#脚本,然后从示例自定义渲染通道部分粘贴代码。
- 注意:这个例子使用了Blitter API。不要使用CommandBuffer。URP中的Blit API。更多信息请参考Blit。
- 使用上面定义好的定制Render Pass
-
要创建Scriptable RendererFeature,将自定义渲染通道添加到渲染循环中,请创建一个名为ColorBlitRendererFeature.cs的新c#脚本,然后将示例Scriptable RendererFeature部分中的代码粘贴进来。
-
Example Scriptable Renderer Feature Scriptable Renderer Feature 添加 render pass 到渲染循环.
csusing UnityEngine; using UnityEngine.Rendering; using UnityEngine.Rendering.Universal; internal class ColorBlitRendererFeature : ScriptableRendererFeature { public Shader m_Shader; public float m_Intensity; Material m_Material; ColorBlitPass m_RenderPass = null; public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) { if (renderingData.cameraData.cameraType == CameraType.Game) renderer.EnqueuePass(m_RenderPass); } public override void SetupRenderPasses(ScriptableRenderer renderer, in RenderingData renderingData) { if (renderingData.cameraData.cameraType == CameraType.Game) { // Calling ConfigureInput with the ScriptableRenderPassInput.Color argument // ensures that the opaque texture is available to the Render Pass. m_RenderPass.ConfigureInput(ScriptableRenderPassInput.Color); m_RenderPass.SetTarget(renderer.cameraColorTargetHandle, m_Intensity); } } public override void Create() { m_Material = CoreUtils.CreateEngineMaterial(m_Shader); m_RenderPass = new ColorBlitPass(m_Material); } protected override void Dispose(bool disposing) { CoreUtils.Destroy(m_Material); } }
-
-
要创建将像素染成绿色的着色器代码,请创建一个着色器文件,然后从示例着色器部分粘贴代码。
-
Example shader
-
着色器执行渲染的GPU端。它从相机中采样颜色纹理,然后输出绿色值设置为所选强度的颜色。
注意:与Blitter API一起使用的着色器必须是手工编码的着色器。图形着色器与Blitter API不兼容。cppShader "ColorBlit" { SubShader { Tags { "RenderType"="Opaque" "RenderPipeline" = "UniversalPipeline"} LOD 100 ZWrite Off Cull Off Pass { Name "ColorBlitPass" HLSLPROGRAM #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" // The Blit.hlsl file provides the vertex shader (Vert), // the input structure (Attributes) and the output structure (Varyings) #include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl" #pragma vertex Vert #pragma fragment frag // Set the color texture from the camera as the input texture TEXTURE2D_X(_CameraOpaqueTexture); SAMPLER(sampler_CameraOpaqueTexture); // Set up an intensity parameter float _Intensity; half4 frag (Varyings input) : SV_Target { UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input); // Sample the color from the input texture float4 color = SAMPLE_TEXTURE2D_X(_CameraOpaqueTexture, sampler_CameraOpaqueTexture, input.texcoord); // Output the color from the texture, with the green value set to the chosen intensity return color * float4(0, _Intensity, 0, 1); } ENDHLSL } } }
-
-
将ColorBlitRendererFeature添加到当前URP Renderer资源中。有关更多信息,请参阅向URP渲染器添加渲染器功能。
-
要更改亮度,请调整Color Blit Renderer Feature组件中的Intensity属性。
注意:如果项目使用XR,为了使示例可视化,在项目中安装MockHMD XR插件包,然后将渲染模式属性设置为单通道实例化。
【从UnityURP开始探索游戏渲染】专栏-直达
(欢迎点赞留言探讨,更多人加入进来能更加完善这个探索的过程,🙏)