When you create a texture in the render graph system in a render pass, the render graph system handles the creation and disposal of the texture. This process means the texture might not exist in the next frame, and other 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 might not be able to use it.
To make sure a texture is available across frames and cameras, import it into the render graph system using the ImportTexture
API.
You can import a texture if you use a texture created outside the render graph system. For example, you can create a 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 that points to a texture in your project, such as a texture asset, and use it as the input to a render pass.
The render graph system doesn’t manage the lifetime of imported textures. As a result, the following applies:
For more information about the RTHandle
API, refer to Using the RTHandle system.
To import a texture, in the RecordRenderGraph
method of your ScriptableRenderPass
class, follow these steps:
Create a render texture handle using the RTHandle API.
For example:
private RTHandle renderTextureHandle;
Create a RenderTextureDescriptor object with the texture properties you need.
For example:
RenderTextureDescriptor textureProperties = new RenderTextureDescriptor(Screen.width, Screen.height, RenderTextureFormat.Default, 0);
Use the ReAllocateIfNeeded method to create a render texture and attach it to the render texture handle. This method creates a render texture only if the render texture handle is null, or the render texture has different properties to the render texture descriptor.
For example:
RenderingUtils.ReAllocateIfNeeded(ref renderTextureHandle, textureProperties, FilterMode.Bilinear, TextureWrapMode.Clamp, name: "My render texture" );
Import the texture, to convert the RTHandle
object to a TextureHandle
object the render graph system 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.
To import a texture from your project, such as an imported texture attached to a material, follow these steps:
Use the RTHandles.Alloc
API to create a render texture handle from the external texture.
For example:
RTHandle renderTexture = RTHandles.Alloc(texture);
Import the texture, to convert the RTHandle
object to a TextureHandle
object that the render graph system can use.
For example:
TextureHandle textureHandle = renderGraph.ImportTexture(renderTexture);
You can then use the TextureHandle
object to read from or write to the render texture.
You must free the memory a render texture uses at the end of a render pass, using the Dispose
method.
public void Dispose()
{
renderTexture.Release();
}
The following Scriptable Renderer Feature contains an example render pass that copies a texture asset to a temporary texture. To use this example, follow these steps:
using UnityEngine;
using UnityEngine.Rendering.Universal;
using UnityEngine.Rendering.RenderGraphModule;
using UnityEngine.Rendering;
public class BlitFromExternalTexture : ScriptableRendererFeature
{
// The texture to use as input
public Texture2D textureToUse;
BlitFromTexture customPass;
public override void Create()
{
// Create an instance of the render pass, and pass in the input texture
customPass = new BlitFromTexture(textureToUse);
customPass.renderPassEvent = RenderPassEvent.AfterRenderingPostProcessing;
}
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
{
renderer.EnqueuePass(customPass);
}
class BlitFromTexture : ScriptableRenderPass
{
class PassData
{
internal TextureHandle textureToRead;
}
private Texture2D texturePassedIn;
public BlitFromTexture(Texture2D textureIn)
{
// In the render pass's constructor, set the input texture
texturePassedIn = textureIn;
}
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameContext)
{
using (var builder = renderGraph.AddRasterRenderPass<PassData>("Copy texture", out var passData))
{
// Create a temporary texture and set it as the render target
RenderTextureDescriptor textureProperties = new RenderTextureDescriptor(Screen.width, Screen.height, RenderTextureFormat.Default, 0);
TextureHandle texture = UniversalRenderer.CreateRenderGraphTexture(renderGraph, textureProperties, "My texture", false);
builder.SetRenderAttachment(texture, 0, AccessFlags.Write);
// Create a render texture from the input texture
RTHandle rtHandle = RTHandles.Alloc(texturePassedIn);
// Create a texture handle that the shader graph system can use
TextureHandle textureToRead = renderGraph.ImportTexture(rtHandle);
// Add the texture to the pass data
passData.textureToRead = textureToRead;
// Set the texture as readable
builder.UseTexture(passData.textureToRead, AccessFlags.Read);
builder.AllowPassCulling(false);
builder.SetRenderFunc((PassData data, RasterGraphContext context) => ExecutePass(data, context));
}
}
static void ExecutePass(PassData data, RasterGraphContext context)
{
// Copy the imported texture to the render target
Blitter.BlitTexture(context.cmd, data.textureToRead, new Vector4(0.8f,0.6f,0,0), 0, false);
}
}
}