123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213 |
- using UnityEngine;
- using UnityEngine.Rendering.RenderGraphModule;
- using UnityEngine.Rendering;
- using UnityEngine.Rendering.Universal;
-
- // In this example we will create a texture reference ContextItem in frameData to hold a reference
- // used by furture passes. This is usefull to avoid additional blit operations copying back and forth
- // to the cameras color attachment. Instead of copying it back after the blit operation we can instead
- // update the reference to the blit destination and use that for future passes.
- public class TextureRefRendererFeature : ScriptableRendererFeature
- {
- // The ContextItem used to store the texture reference at.
- public class TexRefData : ContextItem
- {
- // The texture reference variable.
- public TextureHandle texture = TextureHandle.nullHandle;
-
- // Reset function required by ContextItem. It should reset all variables not carried
- // over to next frame.
- public override void Reset()
- {
- // We should always reset texture handles since they are only vaild for the current frame.
- texture = TextureHandle.nullHandle;
- }
- }
-
- // This pass updates the reference when making a blit operation using a material and the camera's color attachment.
- class UpdateRefPass : ScriptableRenderPass
- {
- // The data we want to transfer to the render function after recording.
- class PassData
- {
- // For the blit operation we will need the source and destination of the color attachments.
- public TextureHandle source;
- public TextureHandle destination;
- // We will also need a material to transform the color attachment when making a blit operation.
- public Material material;
- }
-
- // Scale bias is used to blit from source to distination given a 2d scale in the x and y parameters
- // and an offset in the z and w parameters.
- static Vector4 scaleBias = new Vector4(1f, 1f, 0f, 0f);
-
- // Material used in the blit operation.
- Material[] m_DisplayMaterials;
-
- // Function used to transfer the material from the renderer feature to the render pass.
- public void Setup(Material[] materials)
- {
- m_DisplayMaterials = materials;
- }
-
- // This function blits the whole screen for a given material.
- public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
- {
- foreach (var mat in m_DisplayMaterials)
- {
- // Skip material if it is null.
- if (mat == null)
- {
- Debug.LogWarning($"Skipping render pass for unassigned material.");
- continue;
- }
-
-
- // Starts the recording of the render graph pass given the name of the pass
- // and outputting the data used to pass data to the execution of the render function.
- using (var builder = renderGraph.AddRasterRenderPass<PassData>($"UpdateRefPass_{mat.name}", out var passData))
- {
- var texRefExist = frameData.Contains<TexRefData>();
- var texRef = frameData.GetOrCreate<TexRefData>();
-
- // First time running this pass. Fetch ref from active color buffer.
- if (!texRefExist)
- {
- var resourceData = frameData.Get<UniversalResourceData>();
- // For this first occurence we would like
- texRef.texture = resourceData.activeColorTexture;
- }
-
- // Setup the descriptor we use for BlitData. We should use the camera target's descriptor as a start.
- var cameraData = frameData.Get<UniversalCameraData>();
- var descriptor = cameraData.cameraTargetDescriptor;
- // We disable MSAA for the blit operations.
- descriptor.msaaSamples = 1;
- // We disable the depth buffer, since we are only makeing transformations to the color buffer.
- descriptor.depthBufferBits = 0;
-
- // Fill in the pass data using by the render function.
-
- // Use the old reference from TexRefData.
- passData.source = texRef.texture;
- // Create a new temporary texture to keep the blit result.
- passData.destination = UniversalRenderer.CreateRenderGraphTexture(renderGraph, descriptor, $"BlitMaterialRefTex_{mat.name}", false);
- // Material used in the blit operation.
- passData.material = mat;
-
- // Update the texture reference to the blit destination.
- texRef.texture = passData.destination;
-
- // Sets input attachment.
- builder.UseTexture(passData.source);
- // Sets color attachment 0.
- builder.SetRenderAttachment(passData.destination, 0);
-
- // Sets the render function.
- builder.SetRenderFunc((PassData data, RasterGraphContext rgContext) => ExecutePass(data, rgContext));
- }
- }
- }
-
- // ExecutePass is the render function for each of the blit render graph recordings.
- // This is good practice to avoid using variables outside of the lambda it is called from.
- // It is static to avoid using member variables which could cause unintended behaviour.
- static void ExecutePass(PassData data, RasterGraphContext rgContext)
- {
- Blitter.BlitTexture(rgContext.cmd, data.source, scaleBias, data.material, 0);
- }
- }
-
- // After updating the reference we will need to use the result copying it back to camera's
- // color attachment.
- class CopyBackRefPass : ScriptableRenderPass
- {
- // Scale bias is used to blit from source to distination given a 2d scale in the x and y parameters
- // and an offset in the z and w parameters.
- static Vector4 scaleBias = new Vector4(1f, 1f, 0f, 0f);
-
- // The data we want to transfer to the render function after recording.
- class PassData
- {
- // For the blit operation we will need the source and destination of the color attachments.
- // We don't need a material for the blit operation since we only want to copy it back
- // without any transformations to the color attachment.
- public TextureHandle source;
- public TextureHandle destination;
- }
-
- // This function blits the reference back to the camera's color attachment.
- public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
- {
- // Early exit if TexRefData doesn't exist within frameData since where is nothing to copy back.
- if (!frameData.Contains<TexRefData>()) return;
- // Starts the recording of the render graph pass given the name of the pass
- // and outputting the data used to pass data to the execution of the render function.
- using (var builder = renderGraph.AddRasterRenderPass<PassData>("Copy Back Pass", out var passData))
- {
- // Fetch UniversalResourceData to retrive the camera's active color texture.
- var resourceData = frameData.Get<UniversalResourceData>();
- // Fetch TexRefData to retrive the texture reference.
- var texRef = frameData.Get<TexRefData>();
-
- // Update the pass data.
- passData.source = texRef.texture;
- passData.destination = resourceData.activeColorTexture;
-
- // Sets input attachment.
- builder.UseTexture(passData.source);
- // Sets color attachment 0.
- builder.SetRenderAttachment(passData.destination, 0);
-
- // Sets the render function.
- builder.SetRenderFunc((PassData data, RasterGraphContext rgContext) => ExecutePass(data, rgContext));
- }
- }
-
- // ExecutePass is the render function for each of the blit render graph recordings.
- // This is good practice to avoid using variables outside of the lambda it is called from.
- // It is static to avoid using member variables which could cause unintended behaviour.
- static void ExecutePass(PassData data, RasterGraphContext rgContext)
- {
- // Calling blit without a material will copy without any additional tranformations.
- Blitter.BlitTexture(rgContext.cmd, data.source, scaleBias, 0, false);
- }
- }
-
- [Tooltip("The material used when making the blit operation.")]
- public Material[] displayMaterials = new Material[1];
-
- UpdateRefPass m_UpdateRefPass;
- CopyBackRefPass m_CopyBackRefPass;
-
- // Here you can create passes and do the initialization of them. This is called everytime serialization happens.
- public override void Create()
- {
- m_UpdateRefPass = new UpdateRefPass();
- m_CopyBackRefPass = new CopyBackRefPass();
-
- // Configures where the render pass should be injected.
- m_UpdateRefPass.renderPassEvent = RenderPassEvent.AfterRenderingPostProcessing;
- m_CopyBackRefPass.renderPassEvent = RenderPassEvent.AfterRenderingPostProcessing;
- }
-
- // Here you can inject one or multiple render passes in the renderer.
- // This method is called when setting up the renderer once per-camera.
- public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
- {
- // Since they have the same RenderPassEvent the order matters when enqueueing them.
-
- // Early exit if there are no materials.
- if (displayMaterials == null)
- {
- Debug.LogWarning("TexterRefRendererFeature materials is null and will be skipped.");
- return;
- }
-
- m_UpdateRefPass.Setup(displayMaterials);
- renderer.EnqueuePass(m_UpdateRefPass);
- renderer.EnqueuePass(m_CopyBackRefPass);
- }
- }
-
|