5.9 KiB
Write a render pass using the render graph system in SRP Core
Write a render pass using the render graph system, after you use the BeginRecording API to start recording render graph commands.
Note: This section is about creating a custom render pipeline. To use the render graph system in a prebuilt Unity pipeline, refer to either Render graph system in URP or Render graph system in HDRP.
Prerequisites
To add a render pass, you must first create a render graph instance and start recording. For more information, refer to Write a render pipeline with render graph.
Write a render pass
-
Create a class or struct that declares the resources the render pass uses. For example:
class PassData { public TextureHandle cameraTarget; public TextureHandle sourceTexture; }Ensure that you declare only the variables that the render pass uses. Adding unnecessary variables can reduce performance.
-
Declare the render pass, for example using the
AddRasterRenderPassmethod.using (var builder = myRenderGraph.AddRasterRenderPass<PassData>("Example render pass", out var passData)) { }The
buildervariable is an instance of theIRasterRenderGraphBuilderinterface. This variable is the entry point for configuring the information related to the render pass. -
Set the resources that the render pass uses. For example:
using (var builder = myRenderGraph.AddRasterRenderPass<PassData>("Example render pass", out var passData)) { ... // Set the source texture as the camera target. passData.cameraTarget = myRenderGraph.ImportBackbuffer(BuiltinRenderTextureType.CameraTarget, cameraTargetProperties); // Set the destination texture as a temporary texture. passData.sourceTexture = myRenderGraph.CreateTexture(textureProperties); }For more information, refer to Resources in the render graph system.
-
Declare the inputs of the render pass using the
UseTextureAPI, but don't add commands to command buffers. This is the recording stage.builder.UseTexture(passData.cameraTarget, AccessFlags.Read); -
Declare the output of the render pass using the
SetRenderAttachmentAPI. For example:builder.SetRenderAttachment(passData.sourceTexture, 0, AccessFlags.Write); -
To add commands, declare a rendering function using the
SetRenderFuncAPI. Use a static method or a static lambda method. This is the execution stage. For example:builder.SetRenderFunc(static (PassData passData, RasterGraphContext context) => { context.cmd.ClearRenderTarget(true, true, Color.blue); });
Example
The following example sets a temporary texture as the input and the camera target as the output, then clears the camera target to blue. To use the example, add it to a custom render pipeline after the BeginRecording API. For more information, refer to Write a render pipeline with render graph.
This code example is simplified. It demonstrates the clearest workflow, rather than the most efficient runtime performance.
using (var builder = myRenderGraph.AddRasterRenderPass<PassData>("Example render pass", out var passData))
{
RenderTargetInfo cameraTargetProperties = new RenderTargetInfo
{
width = cameraToRender.pixelWidth,
height = cameraToRender.pixelHeight,
volumeDepth = 1,
msaaSamples = 1,
format = GraphicsFormat.R8G8B8A8_UNorm
};
passData.cameraTarget = myRenderGraph.ImportBackbuffer(BuiltinRenderTextureType.CameraTarget, cameraTargetProperties);
var textureProperties = new TextureDesc(Vector2.one)
{
colorFormat = GraphicsFormat.R8G8B8A8_UNorm,
width = cameraTargetProperties.width,
height = cameraTargetProperties.height,
clearBuffer = true,
clearColor = Color.red,
name = "My temporary texture"
};
passData.sourceTexture = myRenderGraph.CreateTexture(textureProperties);
passData.material = new Material(Shader.Find("Unlit/Texture"));
builder.UseTexture(passData.sourceTexture, AccessFlags.Read);
builder.SetRenderAttachment(passData.cameraTarget, 0, AccessFlags.Write);
// Make sure the render graph system keeps the render pass, even if it's not used in the final frame.
// Don't use this in production code, because it prevents the render graph system from removing the render pass if it's not needed.
builder.AllowPassCulling(false);
builder.SetRenderFunc(static (PassData passData, RasterGraphContext context) =>
{
// Create a quad mesh
Mesh mesh = new Mesh();
Vector3[] vertices = new Vector3[4]
{
new Vector3(0, 0, 0),
new Vector3(1f, 0, 0),
new Vector3(0, 1f, 0),
new Vector3(1f, 1f, 0)
};
mesh.vertices = vertices;
int[] triangles = new int[6]
{
0, 2, 1,
2, 3, 1
};
mesh.triangles = triangles;
context.cmd.ClearRenderTarget(true, true, Color.blue);
// Pass the source texture to the shader
passData.material.SetTexture("_MainTex", passData.sourceTexture);
// Create a transformation matrix for the quad
Matrix4x4 trs = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0, 0, 0), Vector3.one);
// Draw the quad onto the camera target, using the shader and the source texture
context.cmd.DrawMesh(mesh, trs, passData.material, 0);
});
}