Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Question CommandBuffer.Draw* insteadof Graphics.Draw* URP way?

Discussion in 'Universal Render Pipeline' started by PolyCrusher, Apr 22, 2022.

  1. PolyCrusher

    PolyCrusher

    Joined:
    Jul 3, 2012
    Posts:
    15
    How to replace Graphics.DrawProceduralNow in (OnRenderObject) calls with a CommandBuffer to get access to the correct render order in URP?

    Code (CSharp):
    1. using System.Collections.Generic;
    2. using Unity.Mathematics;
    3. using UnityEngine;
    4. using UnityEngine.Rendering;
    5.  
    6. public sealed class CommandBufferRenderInOrder : MonoBehaviour {
    7.  
    8.     public Mesh mesh;
    9.     public Material material;
    10.  
    11.     struct Data {
    12.         public float3 pos;
    13.     }
    14.  
    15.     [SerializeField]  Shader shader;
    16.  
    17.     [SerializeField] float Size = 0.25f;
    18.  
    19.     public enum Type {
    20.         GraphicsWay,
    21.         CommandBufferWay
    22.     }
    23.  
    24.     [SerializeField] Type way = Type.GraphicsWay;
    25.  
    26.     Material pointsMaterial;
    27.  
    28.     ComputeBuffer outputBuffer;
    29.  
    30.     private readonly Dictionary<Camera, CommandBuffer> cameras = new();
    31.  
    32.     private void OnEnable() {
    33.         //RenderPipelineManager.beginCameraRendering += WriteLogMessage;
    34.  
    35.         var points = new List<float4>();
    36.  
    37.         for (int i = 0; i < 1000; i++) {
    38.             points.Add(new float4(
    39.                 i * 0.1f,
    40.                 UnityEngine.Random.Range(-2, 2f),
    41.                 0f,
    42.                 i));
    43.         }
    44.  
    45.         outputBuffer = new ComputeBuffer(points.Count, sizeof(float) * 4);
    46.         outputBuffer.SetData(points.ToArray());
    47.  
    48.         pointsMaterial = new Material(shader);
    49.         pointsMaterial.SetBuffer("_Points", outputBuffer);
    50.     }
    51.  
    52.     private void OnDisable() {
    53.  
    54.         foreach (var kvp in cameras) {
    55.  
    56.             if (kvp.Key) {
    57.  
    58.                 kvp.Key.RemoveCommandBuffer(CameraEvent.AfterForwardOpaque, kvp.Value);
    59.             }
    60.         }
    61.  
    62.         cameras.Clear();
    63.  
    64.         //RenderPipelineManager.beginCameraRendering -= WriteLogMessage;
    65.     }
    66.  
    67.     void OnWillRenderObject() {
    68.         if (way != Type.CommandBufferWay)
    69.             return;
    70.  
    71.         var active = enabled && gameObject.activeInHierarchy;
    72.  
    73.         if (!active) {
    74.  
    75.             OnDisable();
    76.             return;
    77.         }
    78.  
    79.         var camera = Camera.current;
    80.  
    81.         if (!camera || !material || !mesh) {
    82.             return;
    83.         }
    84.  
    85.         var matrix = Matrix4x4.identity;
    86.  
    87.         pointsMaterial.SetFloat("_Size", Size);
    88.         pointsMaterial.SetMatrix("_LocalToWorldMatrix", transform.localToWorldMatrix);
    89.  
    90.         if (!cameras.TryGetValue(camera, out CommandBuffer buffer)) {
    91.             buffer = new CommandBuffer {
    92.                 name = "Command Buffer"
    93.             };
    94.  
    95.             camera.AddCommandBuffer(CameraEvent.AfterForwardOpaque, buffer);
    96.             cameras.Add(camera, buffer);
    97.         } else {
    98.             foreach (var cb in cameras.Values) {
    99.                 cb.Clear();
    100.                 cb.DrawMesh(mesh, matrix, material, 0, 0);
    101.  
    102.                 cb.DrawProcedural(matrix, pointsMaterial, 0, MeshTopology.Points, outputBuffer.count);
    103.             }
    104.         }
    105.     }
    106.  
    107.     public void OnRenderObject() {
    108.         if (way != Type.GraphicsWay)
    109.             return;
    110.  
    111.         pointsMaterial.SetPass(0);
    112.  
    113.         pointsMaterial.SetFloat("_Size", Size);
    114.         pointsMaterial.SetMatrix("_LocalToWorldMatrix", transform.localToWorldMatrix);
    115.  
    116.         Graphics.DrawProceduralNow(MeshTopology.Lines, outputBuffer.count);
    117.     }
    118.  
    119.     void WriteLogMessage(ScriptableRenderContext context, Camera camera) {
    120.         //Debug.Log($"Beginning rendering the camera: {camera.name}");
    121.     }
    122. }
    Thanks
     

    Attached Files:

  2. PolyCrusher

    PolyCrusher

    Joined:
    Jul 3, 2012
    Posts:
    15
    Solution found :)

    Code (CSharp):
    1. using System.Collections.Generic;
    2. using Unity.Mathematics;
    3. using UnityEngine;
    4. using UnityEngine.Rendering;
    5. using UnityEngine.Rendering.Universal;
    6.  
    7. public sealed class CommandBufferRenderInOrder : MonoBehaviour {
    8.  
    9.     [SerializeField] Shader shader;
    10.  
    11.     [SerializeField] float size = 0.25f;
    12.  
    13.     Pass pass;
    14.  
    15.     Material material;
    16.  
    17.     struct Data {
    18.         public float3 pos;
    19.     }
    20.  
    21.     ComputeBuffer buffer;
    22.  
    23.     private void OnEnable() {
    24.         var points = new List<float4>();
    25.  
    26.         for (int i = 0; i < 1000; i++) {
    27.             points.Add(new float4(
    28.                 i * 0.1f,
    29.                 UnityEngine.Random.Range(-2, 2f),
    30.                 0f,
    31.                 i));
    32.         }
    33.  
    34.         buffer = new ComputeBuffer(points.Count, sizeof(float) * 4);
    35.         buffer.SetData(points.ToArray());
    36.  
    37.         material = new Material(shader);
    38.         material.SetBuffer("_Points", buffer);
    39.  
    40.         pass = new Pass {
    41.             renderPassEvent = RenderPassEvent.BeforeRenderingOpaques,
    42.             Material = material,
    43.             Count = buffer.count
    44.         };
    45.  
    46.         RenderPipelineManager.beginCameraRendering += Draw;
    47.     }
    48.  
    49.     private void OnDisable() {
    50.         RenderPipelineManager.beginCameraRendering -= Draw;
    51.     }
    52.  
    53.     void Draw(ScriptableRenderContext context, Camera camera) {
    54.         material.SetFloat("_Size", size);
    55.         material.SetMatrix("_LocalToWorldMatrix", transform.localToWorldMatrix);
    56.  
    57.  
    58.         var renderer = camera.GetComponent<UniversalAdditionalCameraData>().scriptableRenderer;
    59.         if (renderer != null) {
    60.             pass.Matrix = transform.localToWorldMatrix;
    61.             renderer.EnqueuePass(pass);
    62.         }
    63.     }
    64. }
    65.  
    66. class Pass : ScriptableRenderPass {
    67.  
    68.     public Matrix4x4 Matrix { get; set; }
    69.  
    70.     public Material Material { get; set; }
    71.  
    72.     public int Count { get; set; }
    73.  
    74.     public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) {
    75.         CommandBuffer cb = CommandBufferPool.Get("DrawMesh");
    76.         cb.DrawProcedural(Matrix, Material, 0, MeshTopology.Lines, Count);
    77.         context.ExecuteCommandBuffer(cb);
    78.         context.Submit();
    79.         CommandBufferPool.Release(cb);
    80.     }
    81. }
     
  3. amaretto08

    amaretto08

    Joined:
    Jun 5, 2020
    Posts:
    1
    I was just looking for something like this. Thank you so much for coming back and posting the solution.