class in UnityEngine.Experimental.Rendering
/
Implemented in:UnityEngine.CoreModule
Thank you for helping us improve the quality of Unity Documentation. Although we cannot accept all submissions, we do read each suggested change from our users and will make updates where applicable.
CloseFor some reason your suggested change could not be submitted. Please <a>try again</a> in a few minutes. And thank you for taking the time to help us improve the quality of Unity Documentation.
CloseObject encapsulating the duration of a single renderpass that contains one or more subpasses.
The RenderPass object provides a new way to switch rendertargets in the context of a Scriptable Rendering Pipeline. As opposed to the SetRenderTargets function, the RenderPass object specifies a clear beginning and an end for the rendering, alongside explicit load/store actions on the rendering surfaces.
The RenderPass object also allows running multiple subpasses within the same renderpass, where the pixel shaders have a read access to the current pixel value within the renderpass. This allows for efficient implementation of various rendering methods on tile-based GPUs, such as deferred rendering.
RenderPasses are natively implemented on Metal (iOS) and Vulkan, but the API is fully functional on all rendering backends via emulation (using legacy SetRenderTargets calls and reading the current pixel values via texel fetches).
A quick example on how to use the RenderPass API within the Scriptable Render Pipeline to implement deferred rendering:
The RenderPass mechanism has the following limitations:
- All attachments must have the same resolution and MSAA sample count
- The rendering results of previous subpasses are only available within the same screen-space pixel
coordinate via the UNITY_READ_FRAMEBUFFER_INPUT(x) macro in the shader; the attachments cannot be bound
as textures or otherwise accessed until the renderpass has ended
- iOS Metal does not allow reading from the Z-Buffer, so an additional render target is needed to work around that
- The maximum amount of attachments allowed per RenderPass is currently 8 + depth, but note that various GPUs may
have stricter limits.
using UnityEngine; using UnityEngine.Experimental.Rendering;
public class DeferredRenderer { private RenderPassAttachment m_Albedo; private RenderPassAttachment m_SpecRough; private RenderPassAttachment m_Normal; private RenderPassAttachment m_Emission; private RenderPassAttachment m_Depth;
public DeferredRenderer() { // Create the attachment objects. If these attachments are not specifically bound to any RenderTexture using the BindSurface calls, // these are treated as temporary surfaces that are discarded at the end of the renderpass // NOTE: DO NOT ALLOCATE NEW RENDERPASSATTACHMENTS EVERY FRAME! // These objects only get garbage collected when a scene is unloaded, so you'll leak a lot of objects. m_Albedo = new RenderPassAttachment(RenderTextureFormat.ARGB32); m_SpecRough = new RenderPassAttachment(RenderTextureFormat.ARGB32); m_Normal = new RenderPassAttachment(RenderTextureFormat.ARGB2101010); m_Emission = new RenderPassAttachment(RenderTextureFormat.ARGBHalf); m_Depth = new RenderPassAttachment(RenderTextureFormat.Depth);
// At the beginning of the render pass, clear the emission buffer to all black, and the depth buffer to 1.0f m_Emission.Clear(new Color(0.0f, 0.0f, 0.0f, 0.0f), 1.0f, 0); m_Depth.Clear(new Color(), 1.0f, 0); }
public void ExecuteRenderLoop(Camera camera, CullResults cullResults, ScriptableRenderContext scriptableRenderContext) { // Bind the albedo surface to the current camera target, so the final pass will render the scene to the screen backbuffer // The second argument specifies whether the existing contents of the surface need to be loaded as the initial values; // in our case we do not need that because we'll be clearing the attachment anyway. This saves a lot of memory // bandwidth on tiled GPUs. // The third argument specifies whether the rendering results need to be written out to memory at the end of // the renderpass. We need this as we'll be generating the final image there. // We could do this in the constructor already, but the camera target may change on the fly, esp. in the editor m_Albedo.BindSurface(BuiltinRenderTextureType.CameraTarget, false, true);
// All other attachments are transient surfaces that are not stored anywhere. If the renderer allows, // those surfaces do not even have a memory allocated for the pixel values, saving RAM usage.
// Start the renderpass using the given scriptable rendercontext, resolution, samplecount, array of attachments that will be used within the renderpass and the depth surface using (RenderPass rp = new RenderPass(scriptableRenderContext, camera.pixelWidth, camera.pixelHeight, 1, new[] { m_Albedo, m_SpecRough, m_Normal, m_Emission }, m_Depth)) { // Start the first subpass, GBuffer creation: render to albedo, specRough, normal and emission, no need to read any input attachments using (new RenderPass.SubPass(rp, new[] { m_Albedo, m_SpecRough, m_Normal, m_Emission }, null)) { // Render the deferred G-Buffer RenderGBuffer(cullResults, camera, scriptableRenderContext); } // Second subpass, lighting: Render to the emission buffer, read from albedo, specRough, normal and depth. // The last parameter indicates whether the depth buffer can be bound as read-only. // Note that some renderers (notably iOS Metal) won't allow reading from the depth buffer while it's bound as Z-buffer, // so those renderers should write the Z into an additional FP32 render target manually in the pixel shader and read from it instead using (new RenderPass.SubPass(rp, new[] { m_Emission }, new[] { m_Albedo, m_SpecRough, m_Normal, m_Depth }, true)) { PushGlobalShadowParams(scriptableRenderContext);
RenderLighting(camera, cullResults, scriptableRenderContext);
scriptableRenderContext.DrawSkybox(camera); } // Third subpass, tonemapping: Render to albedo (which is bound to the camera target), read from emission. using (new RenderPass.SubPass(rp, new[] { m_Albedo }, new[] { m_Emission }, true)) { // present frame buffer. FinalPass(scriptableRenderContext); } } } }
colorAttachments | Read only: array of RenderPassAttachment objects currently bound into this RenderPass. |
context | Read only: The ScriptableRenderContext object this RenderPass was created for. |
depthAttachment | Read only: The depth/stencil attachment used in this RenderPass, or null if none. |
height | Read only: The height of the RenderPass surfaces in pixels. |
sampleCount | Read only: MSAA sample count for this RenderPass. |
width | Read only: The width of the RenderPass surfaces in pixels. |
RenderPass | Create a RenderPass and start it within the ScriptableRenderContext. |
Dispose | End the RenderPass. |
Did you find this page useful? Please give it a rating:
Thanks for rating this page!
What kind of problem would you like to report?
Thanks for letting us know! This page has been marked for review based on your feedback.
If you have time, you can provide more information to help us fix the problem faster.
Provide more information
You've told us this page needs code samples. If you'd like to help us further, you could provide a code sample, or tell us about what kind of code sample you'd like to see:
You've told us there are code samples on this page which don't work. If you know how to fix it, or have something better we could use instead, please let us know:
You've told us there is information missing from this page. Please tell us more about what's missing:
You've told us there is incorrect information on this page. If you know what we should change to make it correct, please tell us:
You've told us this page has unclear or confusing information. Please tell us more about what you found unclear or confusing, or let us know how we could make it clearer:
You've told us there is a spelling or grammar error on this page. Please tell us what's wrong:
You've told us this page has a problem. Please tell us more about what's wrong:
Thanks for helping to make the Unity documentation better!