Hello,
in my project I’m creating procedural meshes using ComputeShader and the vertex data is stored in ComputeBuffer on the GPU. I need to render the mesh somehow.
I’ve searched for some examples how to correctly make a render directly on GPU without using MeshRenderer component. I’ve found this GitHub - keijiro/NoiseBall3: A Unity example that shows how to use the new implementation of DrawProcedural.
There is said that starting form Unity 2019.1 Graphics.DrawProcedural was improved and allows to make a draw calls inside standard render pipeline which supports lights and shadows.
So I wrote a simple shader just to make the mesh visible, assigned it to the material and put the Graphics.DrawProcedural call inside a function which is called every Update of my terrain chunk:
public void DrawMesh()
{
m_meshMaterial.SetBuffer("_MeshBuffer", m_meshBuffer);
Graphics.DrawProcedural(m_meshMaterial,
new Bounds(Vector3.zero, Vector3.one * 500),
MeshTopology.Triangles, m_maxVertices, 1, null, null,
UnityEngine.Rendering.ShadowCastingMode.TwoSided, true,
0);
}
m_meshBuffer contains vertices with WorldSpace coords previously calculated by ComputeShader.
m_meshMaterial is assigned with this shader:
Shader "Materials/World/MyDrawMesh"
{
SubShader
{
Cull off
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct Vertex
{
float4 position;
float3 normal;
};
StructuredBuffer<Vertex> _MeshBuffer;
struct v2f
{
float4 vertex : SV_POSITION;
float3 color : COLOR;
};
v2f vert (uint id : SV_VertexID)
{
v2f o;
o.vertex = UnityObjectToClipPos(float4(_MeshBuffer[id].position.xyz,
1.0f));
o.color = dot(float3(0, 1, 0), _MeshBuffer[id].normal) * 0.5 + 0.5;
return o;
}
fixed4 frag(v2f i) : SV_Target
{
return float4(i.color, 1.0f);
}
ENDCG
}
}
}
Unfortunately this approach draws nothing. However I do get Draw calls in the render pipeline:
Now if i use the old implementation of Graphics.DrawProcedural (Graphics.DrawProceduralNow) called in OnPostRender method of my main camera using the same shader i get the results.
private void OnPostRender()
{
m_meshMaterial.SetBuffer("_MeshBuffer", m_meshBuffer);
m_meshMaterial.SetPass(0);
Graphics.DrawProceduralNow(MeshTopology.Triangles,
m_maxVertices);
}
But this is not the approach I want because the mesh is being rendered outside the render pipeline hence missing lights and shadows.
How can I render mesh using the new DrawProcedural method? Author of the NoiseBall example uses Surface Shader but during compilation it is converted into standard vertex/fragment shader. Maybe my shader misses some pragmas or tags. I’m new to shaders so it wouldn’t be surprising.