A render loop is the term for all of the rendering operations that take place in a single frame. This page contains information on creating a simple render loop in a custom render pipelineA series of operations that take the contents of a Scene, and displays them on a screen. Unity lets you choose from pre-built render pipelines, or write your own. More info
See in Glossary that is based on Unity’s Scriptable Render Pipeline.
The code examples on this page demonstrate the basic principles of using the Scriptable Render Pipeline. You can use this information to build your own custom Scriptable Render Pipeline, or to understand how Unity’s prebuilt Scriptable Render Pipelines work.
Before you begin writing the code for your render loop, you must prepare your project.
The steps are as follows:
In the Scriptable Render Pipeline, you use the LightMode
Pass tag to determine how to draw geometry. For more information on Pass tags, see ShaderLab: assigning tags to a Pass.
This task shows you how to create a very simple unlit Shader objectAn instance of the Shader class, a Shader object is container for shader programs and GPU instructions, and information that tells Unity how to use them. Use them with materials to determine the appearance of your scene. More info
See in Glossary with a LightMode Pass tag value of ExampleLightModeTag
.
// This defines a simple unlit Shader object that is compatible with a custom Scriptable Render Pipeline.
// It applies a hardcoded color, and demonstrates the use of the LightMode Pass tag.
// It is not compatible with SRP Batcher.
Shader "Examples/SimpleUnlitColor"
{
SubShader
{
Pass
{
// The value of the LightMode Pass tag must match the ShaderTagId in ScriptableRenderContext.DrawRenderers
Tags { "LightMode" = "ExampleLightModeTag"}
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
float4x4 unity_MatrixVP;
float4x4 unity_ObjectToWorld;
struct Attributes
{
float4 positionOS : POSITION;
};
struct Varyings
{
float4 positionCS : SV_POSITION;
};
Varyings vert (Attributes IN)
{
Varyings OUT;
float4 worldPos = mul(unity_ObjectToWorld, IN.positionOS);
OUT.positionCS = mul(unity_MatrixVP, worldPos);
return OUT;
}
float4 frag (Varyings IN) : SV_TARGET
{
return float4(0.5,1,0.5,1);
}
ENDHLSL
}
}
}
To test that your render loop works, you must create something to render. This task shows you how to put GameObjectsThe fundamental object in Unity scenes, which can represent characters, props, scenery, cameras, waypoints, and more. A GameObject’s functionality is defined by the Components attached to it. More info
See in Glossary in your sceneA Scene contains the environments and menus of your game. Think of each unique Scene file as a unique level. In each Scene, you place your environments, obstacles, and decorations, essentially designing and building your game in pieces. More info
See in Glossary that use the SRP-compatible shader that you created in the previous task.
The final stage of preparation is to create the basic source files needed for your custom SRP, and tell Unity to begin rendering using the custom SRP.
RenderPipeline
and a compatible Render Pipeline Asset, following the instructions in Creating a Render Pipeline Instance and Render Pipeline Asset
In a simple render loop, the basic operations are:
Clearing means removing the things that were drawn during the last frame. The render target is usually the screen; however, you can also render to textures to create a “picture in picture” effect. These examples demonstrate how to render to the screen, which is Unity’s default behavior.
To clear the render target in the Scriptable Render Pipeline, you do the following:
CommandBuffer
with a Clear
command.CommandBuffer
to the queue of commands on the ScriptableRenderContext
; to do this, call ScriptableRenderContext.ExecuteCommandBuffer.ScriptableRenderContext
; to do this, call ScriptableRenderContext.Submit.As with all Scriptable Render Pipeline operations, you use the RenderPipeline.Render method as the entry point for this code. This example code demonstrates how to do this:
/*
This is a simplified example of a custom Scriptable Render Pipeline.
It demonstrates how a basic render loop works.
It shows the clearest workflow, rather than the most efficient runtime performance.
*/
using UnityEngine;
using UnityEngine.Rendering;
public class ExampleRenderPipeline : RenderPipeline {
public ExampleRenderPipeline() {
}
protected override void Render (ScriptableRenderContext context, Camera[] cameras) {
// Create and schedule a command to clear the current render target
var cmd = new CommandBuffer();
cmd.ClearRenderTarget(true, true, Color.black);
context.ExecuteCommandBuffer(cmd);
cmd.Release();
// Instruct the graphics API to perform all scheduled commands
context.Submit();
}
}
Culling is the process of filtering out geometry that is not visible to a Camera.
To cull in the Scriptable Render Pipeline, you do the following:
ScriptableCullingParameters
struct.CullingResults
struct.This example code extends the example above, and demonstrates how to clear the render target and then perform a culling operation:
/*
This is a simplified example of a custom Scriptable Render Pipeline.
It demonstrates how a basic render loop works.
It shows the clearest workflow, rather than the most efficient runtime performance.
*/
using UnityEngine;
using UnityEngine.Rendering;
public class ExampleRenderPipeline : RenderPipeline {
public ExampleRenderPipeline() {
}
protected override void Render (ScriptableRenderContext context, Camera[] cameras) {
// Create and schedule a command to clear the current render target
var cmd = new CommandBuffer();
cmd.ClearRenderTarget(true, true, Color.black);
context.ExecuteCommandBuffer(cmd);
cmd.Release();
// Iterate over all Cameras
foreach (Camera camera in cameras)
{
// Get the culling parameters from the current Camera
camera.TryGetCullingParameters(out var cullingParameters);
// Use the culling parameters to perform a cull operation, and store the results
var cullingResults = context.Cull(ref cullingParameters);
}
// Instruct the graphics API to perform all scheduled commands
context.Submit();
}
}
Drawing is the process of instructing the graphics API to draw a given set of geometry with given settings.
To draw in SRP, you do the following:
CullingResults
struct.This example code builds on the examples above, and demonstrates how to clear the render target, perform a culling operation, and draw the resulting geometry:
/*
This is a simplified example of a custom Scriptable Render Pipeline.
It demonstrates how a basic render loop works.
It shows the clearest workflow, rather than the most efficient runtime performance.
*/
using UnityEngine;
using UnityEngine.Rendering;
public class ExampleRenderPipeline : RenderPipeline {
public ExampleRenderPipeline() {
}
protected override void Render (ScriptableRenderContext context, Camera[] cameras) {
// Create and schedule a command to clear the current render target
var cmd = new CommandBuffer();
cmd.ClearRenderTarget(true, true, Color.black);
context.ExecuteCommandBuffer(cmd);
cmd.Release();
// Iterate over all Cameras
foreach (Camera camera in cameras)
{
// Get the culling parameters from the current Camera
camera.TryGetCullingParameters(out var cullingParameters);
// Use the culling parameters to perform a cull operation, and store the results
var cullingResults = context.Cull(ref cullingParameters);
// Update the value of built-in shader variables, based on the current Camera
context.SetupCameraProperties(camera);
// Tell Unity which geometry to draw, based on its LightMode Pass tag value
ShaderTagId shaderTagId = new ShaderTagId("ExampleLightModeTag");
// Tell Unity how to sort the geometry, based on the current Camera
var sortingSettings = new SortingSettings(camera);
// Create a DrawingSettings struct that describes which geometry to draw and how to draw it
DrawingSettings drawingSettings = new DrawingSettings(shaderTagId, sortingSettings);
// Tell Unity how to filter the culling results, to further specify which geometry to draw
// Use FilteringSettings.defaultValue to specify no filtering
FilteringSettings filteringSettings = FilteringSettings.defaultValue;
// Schedule a command to draw the geometry, based on the settings you have defined
context.DrawRenderers(cullingResults, ref drawingSettings, ref filteringSettings);
// Schedule a command to draw the Skybox if required
if (camera.clearFlags == CameraClearFlags.Skybox && RenderSettings.skybox != null)
{
context.DrawSkybox(camera);
}
// Instruct the graphics API to perform all scheduled commands
context.Submit();
}
}
}
When you visit any website, it may store or retrieve information on your browser, mostly in the form of cookies. This information might be about you, your preferences or your device and is mostly used to make the site work as you expect it to. The information does not usually directly identify you, but it can give you a more personalized web experience. Because we respect your right to privacy, you can choose not to allow some types of cookies. Click on the different category headings to find out more and change our default settings. However, blocking some types of cookies may impact your experience of the site and the services we are able to offer.
More information
These cookies enable the website to provide enhanced functionality and personalisation. They may be set by us or by third party providers whose services we have added to our pages. If you do not allow these cookies then some or all of these services may not function properly.
These cookies allow us to count visits and traffic sources so we can measure and improve the performance of our site. They help us to know which pages are the most and least popular and see how visitors move around the site. All information these cookies collect is aggregated and therefore anonymous. If you do not allow these cookies we will not know when you have visited our site, and will not be able to monitor its performance.
These cookies may be set through our site by our advertising partners. They may be used by those companies to build a profile of your interests and show you relevant adverts on other sites. They do not store directly personal information, but are based on uniquely identifying your browser and internet device. If you do not allow these cookies, you will experience less targeted advertising. Some 3rd party video providers do not allow video views without targeting cookies. If you are experiencing difficulty viewing a video, you will need to set your cookie preferences for targeting to yes if you wish to view videos from these providers. Unity does not control this.
These cookies are necessary for the website to function and cannot be switched off in our systems. They are usually only set in response to actions made by you which amount to a request for services, such as setting your privacy preferences, logging in or filling in forms. You can set your browser to block or alert you about these cookies, but some parts of the site will not then work. These cookies do not store any personally identifiable information.