---
uid: urp-write-a-scriptable-render-pass
---
# Write a Scriptable Render Pass in Compatibility Mode
[!include[](../snippets/note-compatibility-mode.md)]
The following example is a `ScriptableRenderPass` instance that performs the following steps:
1. Creates a temporary render texture using the `RenderTextureDescriptor` API.
2. Applies two passes of the [custom shader](#example-shader) to the camera output using the `RTHandle` and the `Blit` API.
After you write a Scriptable Render Pass, you can inject the render pass using one of the following methods:
- [Use the `RenderPipelineManager` API](../customize/inject-render-pass-via-script.md)
- [Use a Scriptable Renderer Feature](scriptable-renderer-features/inject-a-pass-using-a-scriptable-renderer-feature.md)
## Create the scriptable Render Pass
This section demonstrates how to create a scriptable Render Pass.
1. Create a new C# script and name it `RedTintRenderPass.cs`.
2. In the script, remove the code that Unity inserted in the `RedTintRenderPass` class. Add the following `using` directive:
```C#
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
```
3. Create the `RedTintRenderPass` class that inherits from the **ScriptableRenderPass** class.
```C#
public class RedTintRenderPass : ScriptableRenderPass
```
4. Add the `Execute` method to the class. Unity calls this method every frame, once for each camera. This method lets you implement the rendering logic of the scriptable Render Pass.
```C#
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{ }
```
Below is the complete code for the RedTintRenderPass.cs file from this section.
```C#
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
public class RedTintRenderPass : ScriptableRenderPass
{
public override void Execute(ScriptableRenderContext context,
ref RenderingData renderingData)
{
}
}
```
## Implement the settings for the custom render pass
1. Add a field for the Material, and the constructor that uses the field.
```C#
private Material material;
public RedTintRenderPass(Material material)
{
this.material = material;
}
```
2. Add the `RenderTextureDescriptor` field and initialize it in the constructor:
```C#
using UnityEngine;
private RenderTextureDescriptor textureDescriptor;
public RedTintRenderPass(Material material)
{
this.material = material;
textureDescriptor = new RenderTextureDescriptor(Screen.width,
Screen.height, RenderTextureFormat.Default, 0);
}
```
3. Declare the `RTHandle` field to store the reference to the temporary red tint texture.
```C#
private RTHandle textureHandle;
```
4. Implement the `Configure` method. Unity calls this method before executing the render pass.
```C#
public override void Configure(CommandBuffer cmd,
RenderTextureDescriptor cameraTextureDescriptor)
{
//Set the red tint texture size to be the same as the camera target size.
textureDescriptor.width = cameraTextureDescriptor.width;
textureDescriptor.height = cameraTextureDescriptor.height;
//Check if the descriptor has changed, and reallocate the RTHandle if necessary.
RenderingUtils.ReAllocateIfNeeded(ref textureHandle, textureDescriptor);
}
```
5. Use the Blit method to apply the two render passes from the custom shader to the camera output.
```C#
public override void Execute(ScriptableRenderContext context,
ref RenderingData renderingData)
{
//Get a CommandBuffer from pool.
CommandBuffer cmd = CommandBufferPool.Get();
RTHandle cameraTargetHandle =
renderingData.cameraData.renderer.cameraColorTargetHandle;
// Blit from the camera target to the temporary render texture,
// using the first shader pass.
Blit(cmd, cameraTargetHandle, textureHandle, material, 0);
// Blit from the temporary render texture to the camera target,
// using the second shader pass.
Blit(cmd, textureHandle, cameraTargetHandle, material, 1);
//Execute the command buffer and release it back to the pool.
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
}
```
6. Implement the `Dispose` method that destroys the Material and the temporary render texture after the render pass execution.
```C#
public void Dispose()
{
#if UNITY_EDITOR
if (EditorApplication.isPlaying)
{
Object.Destroy(material);
}
else
{
Object.DestroyImmediate(material);
}
#else
Object.Destroy(material);
#endif
if (textureHandle != null) textureHandle.Release();
}
```
### Custom render pass code
Below is the complete code for the custom Render Pass script.
```C#
using UnityEditor;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
public class RedTintRenderPass : ScriptableRenderPass
{
private Material material;
private RenderTextureDescriptor textureDescriptor;
private RTHandle textureHandle;
public RedTintRenderPass(Material material)
{
this.material = material;
textureDescriptor = new RenderTextureDescriptor(Screen.width,
Screen.height, RenderTextureFormat.Default, 0);
}
public override void Configure(CommandBuffer cmd,
RenderTextureDescriptor cameraTextureDescriptor)
{
// Set the texture size to be the same as the camera target size.
textureDescriptor.width = cameraTextureDescriptor.width;
textureDescriptor.height = cameraTextureDescriptor.height;
// Check if the descriptor has changed, and reallocate the RTHandle if necessary
RenderingUtils.ReAllocateIfNeeded(ref textureHandle, textureDescriptor);
}
public override void Execute(ScriptableRenderContext context,
ref RenderingData renderingData)
{
//Get a CommandBuffer from pool.
CommandBuffer cmd = CommandBufferPool.Get();
RTHandle cameraTargetHandle =
renderingData.cameraData.renderer.cameraColorTargetHandle;
// Blit from the camera target to the temporary render texture,
// using the first shader pass.
Blit(cmd, cameraTargetHandle, textureHandle, material, 0);
// Blit from the temporary render texture to the camera target,
// using the second shader pass.
Blit(cmd, textureHandle, cameraTargetHandle, material, 1);
//Execute the command buffer and release it back to the pool.
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
}
public void Dispose()
{
#if UNITY_EDITOR
if (EditorApplication.isPlaying)
{
Object.Destroy(material);
}
else
{
Object.DestroyImmediate(material);
}
#else
Object.Destroy(material);
#endif
if (textureHandle != null) textureHandle.Release();
}
}
```
## The custom shader for the red tint effect
This section contains the code for the custom shader that implements the red tint effect.
```c++
Shader "CustomEffects/RedTint"
{
HLSLINCLUDE
#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"
float4 RedTint (Varyings input) : SV_Target
{
float3 color = SAMPLE_TEXTURE2D(_BlitTexture, sampler_LinearClamp, input.texcoord).rgb;
return float4(1, color.gb, 1);
}
float4 SimpleBlit (Varyings input) : SV_Target
{
float3 color = SAMPLE_TEXTURE2D(_BlitTexture, sampler_LinearClamp, input.texcoord).rgb;
return float4(color.rgb, 1);
}
ENDHLSL
SubShader
{
Tags { "RenderType"="Opaque" "RenderPipeline" = "UniversalPipeline"}
LOD 100
ZTest Always ZWrite Off Cull Off
Pass
{
Name "RedTint"
HLSLPROGRAM
#pragma vertex Vert
#pragma fragment RedTint
ENDHLSL
}
Pass
{
Name "SimpleBlit"
HLSLPROGRAM
#pragma vertex Vert
#pragma fragment SimpleBlit
ENDHLSL
}
}
}
```