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.