To make a texture available across frames and camerasA component which creates an image of a particular viewpoint in your scene. The output is either drawn to the screen or captured as a texture. More info
See in Glossary, create it outside the render graph system, then point a render graph to it using the ImportTexture API.
The render graph system doesn’t manage the lifetime of imported textures, so it can’t optimize using the texture, and there might be memory leaks. Where possible, Create a temporary texture for a single frame instead, so the render graph system manages its lifetime.
To fetch textures created by URP instead of your own code, for example the camera color and depth textures, refer to Frame data in the render graph system.
To create a texture once but use it across multiple frames, create it before you call AddRasterRenderPass. For example:
Declare the texture using the RTHandle API.
For example:
public RTHandle renderTextureHandle;
Create a TextureDesc object with the texture properties you need.
Allocate the render textureA special type of Texture that is created and updated at runtime. To use them, first create a new Render Texture and designate one of your Cameras to render into it. Then you can use the Render Texture in a Material just like a regular Texture. More info
See in Glossary using the ReAllocateHandleIfNeeded API. This method checks if the render texture already exists, so it only creates the render texture once.
For example:
RenderingUtils.ReAllocateHandleIfNeeded(ref renderTextureHandle, textureDesc, name: "My render texture");
To use the texture after you call AddRasterRenderPass, use the ImportTexture API to get a handle to the render texture that render graph can use. For example:
TextureHandle texture = renderGraph.ImportTexture(renderTextureHandle);
You can then use the TextureHandle object to read from or write to the render texture, and the texture won’t be disposed of at the end of the render pass.
At the end of rendering, you must free the memory a render texture uses at the end of a render pass.
For example, you can create the following Dispose method in your ScriptableRendererFeature class.
public void Dispose()
{
renderTexture.Release();
}
The following Scriptable Renderer Feature creates a texture outside the render graph system, then uses it in a render pass to draw a random triangle each frame. To see the texture, open the Frame Debugger and select the Test render pass item.
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.RenderGraphModule;
using UnityEngine.Rendering.RenderGraphModule.Util;
using UnityEngine.Rendering.Universal;
using UnityEngine.Experimental.Rendering;
public class RandomTriangles : ScriptableRendererFeature
{
class DrawRandomTriangles : ScriptableRenderPass
{
RTHandle destinationTexture;
class PassData
{
public TextureHandle destination;
public Material material;
}
public DrawRandomTriangles(RTHandle externalTexture)
{
destinationTexture = externalTexture;
}
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameContext)
{
using (var builder = renderGraph.AddRasterRenderPass<PassData>("Test render pass", out var passData))
{
// 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);
// Create a material for drawing a mesh.
passData.material = new Material(Shader.Find("Unlit/Texture"));
// Point the render graph to the external texture.
passData.destination = renderGraph.ImportTexture(destinationTexture);
builder.SetRenderAttachment(passData.destination, 0, AccessFlags.Write);
builder.SetRenderFunc(static (PassData data, RasterGraphContext context) =>
{
// Create a triangle mesh.
Mesh mesh = new Mesh();
Vector3[] vertices = new Vector3[3]
{
new Vector3(0, 0, 0),
new Vector3(1f, 0, 0),
new Vector3(0, 1f, 0),
};
int[] triangles = new int[3]
{
0, 2, 1,
};
mesh.vertices = vertices;
mesh.triangles = triangles;
// Draw the triangle mesh at a random position.
Vector3 randomPos = new Vector3(Random.Range(-10, 10), Random.Range(-10, 10), 0);
Matrix4x4 trs = Matrix4x4.TRS(randomPos, Quaternion.Euler(0, 0, 0), Vector3.one);
context.cmd.DrawMesh(mesh, trs, data.material, 0);
});
}
}
}
DrawRandomTriangles renderPass;
public RTHandle myRenderTexture;
public override void Create()
{
// Allocate a render texture outside the shader graph
TextureDesc textureDesc = new TextureDesc(Vector2.one)
{
colorFormat = GraphicsFormat.R8G8B8A8_UNorm,
width = 256,
height = 256,
clearBuffer = true,
clearColor = Color.red,
name = "My temporary texture"
};
RenderingUtils.ReAllocateHandleIfNeeded(ref myRenderTexture, textureDesc, name: "My render texture");
// Create the render pass and pass in the render texture
renderPass = new DrawRandomTriangles(myRenderTexture);
renderPass.renderPassEvent = RenderPassEvent.AfterRenderingPostProcessing;
}
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
{
renderer.EnqueuePass(renderPass);
}
public new void Dispose()
{
myRenderTexture.Release();
}
}