Graphics.RenderPrimitives not working as intended

I’ve noticed that RenderPrimitives was not working the same way as DrawProcedural. So I made a little test to see what the difference is:

public class RenderPrimitivesTest : MonoBehaviour
{
    [SerializeField] private int rows;
    [SerializeField] private int cols;
    [SerializeField] private float spacing;
    [SerializeField] private Material material;
    [SerializeField] private bool RenderPrimitives = false;
    private RenderParams renderParams;
    private List<float3> vertices = new List<float3>(); // 3 vertices per triangle>
    private List<uint> encodedVertices = new List<uint>();
    private ComputeBuffer vertexBuffer;

    void Start()
    {
        renderParams.material = material;
        renderParams.worldBounds = new Bounds(Vector3.zero, Vector3.one * 1000);
        renderParams.layer = 0;
        renderParams.camera = null;
        renderParams.matProps = null;
        renderParams.receiveShadows = true;
        renderParams.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.On;

        for (int i = 0; i < rows; i++)
        {
            for (int j = 0; j < cols; j++)
            {
                vertices.Add(new float3(i * spacing, 0, j * spacing));
                vertices.Add(new float3(i * spacing, 0, (j + 1) * spacing));
                vertices.Add(new float3((i + 1) * spacing, 0, j * spacing));
            }
        }
        for (int i = 0; i < vertices.Count; i++)
        {
            encodedVertices.Add(EncodeVertex32Bit(vertices[i]));
        }

        vertexBuffer = new ComputeBuffer(vertices.Count, sizeof(uint), ComputeBufferType.Structured, ComputeBufferMode.Dynamic);
        vertexBuffer.SetData(encodedVertices, 0, 0, vertices.Count);

        material.SetBuffer("vertexBuffer", vertexBuffer);
    }

    void Update()
    {
        if (RenderPrimitives)
        {
            Graphics.RenderPrimitives(renderParams, MeshTopology.Quads, rows * cols * 3);
        }
        else
        {
            Graphics.DrawProcedural(material, new Bounds(Vector3.zero, Vector3.one * 1000), MeshTopology.Quads, rows * cols * 3, 1, null, null, UnityEngine.Rendering.ShadowCastingMode.On, true, 0);
        }
    }

    private void OnDestroy()
    {
        vertexBuffer.Release();
    }

    public static uint EncodeVertex32Bit(float3 pos)
    {
        return (uint)pos.x
               | ((uint)pos.y << 6)
               | ((uint)pos.z << 12);
    }
}

The Shader:

Shader "Custom/VertexDebugger"
{
    Properties
    {
        _Color ("Color", Color) = (1,1,1,1)
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }

        Pass
        {
            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma target 4.5

            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            #include "HLSLSupport.cginc"

            CBUFFER_START(UnityPerMaterial)
            float4 _Color;
            CBUFFER_END

            StructuredBuffer<uint> vertexBuffer;

            void DecodeVertex32Bit(uint vertex, out float3 position)
            {
                position.x = (vertex & 63);               // Extract first 6 bits (x)
                position.y = (vertex >> 6) & 63;          // Extract next 6 bits (y)
                position.z = (vertex >> 12) & 63;         // Extract next 6 bits (z)
            }

            struct v2f
            {
                float4 vertex : SV_POSITION;
            };

            v2f vert (uint vertexID : SV_VertexID)
            {
                v2f o;
                float3 pos;
                DecodeVertex32Bit(vertexBuffer[vertexID], pos);
                o.vertex = TransformObjectToHClip(float4(pos, 1));

                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                return fixed4(_Color);
            }
            ENDHLSL
        }
    }
    FallBack "Diffuse"
}

When using DrawProcedural, these are the results:

When using RenderPrimitives, these are the results:


Additionally RenderPrimitives only seems to be working if a MeshRenderer with the material is active, while DrawProcedural does not rely on that.

Can you check the wireframe mode for RenderPrimitives drawing in editor once?

Update
Please replace

        renderParams.material = material;

with

        renderParams = new RenderParams(material);

With exactly the same as before I was getting a different result now for some reason.
Changing from:

 renderParams.material = material;

to:

 renderParams = new RenderParams(material);

fixed it completely though. Now I’m getting the same results with both commands, and even the bounding box works for RenderPrimitives now.
There is still one thing though, where it only looks correct when you’re close enough to it.


Then a little closer:

It also depends on the angle at which I look at it. When I look to the right it looks normal, when I look to the left it looks weird again. This happens for both commands though so I’m not sure it’s relevant.
Ty though for the answer

Check the wireframe mode again to see how the polygons are submitted. Try with an existing mesh and pass the mesh data for quick reference.



When I use a Mesh for the vertices like this:

        int length = mesh.vertexCount;
        for (int i = 0; i < length; i++)
        {
            vertices.Add(mesh.vertices[i]);
        }

the results are weird. With the standard unity cube mesh I get nothing but with the capsule mesh I get this:

If you use a mesh(which you didn’t make), I would recommend to use triangle indices to specify the vertices.
Take the triangle indices in another buffer and dereferencing something like this

float3 vertex = _VertexBuffer[_TrianglesBuffer[vertexId]];

This is because, the vertices you provide may not be in order, so only way is to provide via triangle indices to have correct order.

Also, Go to play mode and in scene view go to the opposite direction to confirm that its winding order issue (For the triangles which showed only half)