- Home /
Is it possible to render geometry in a ComputeBuffer outside play mode?
Hi guys, I've been playing around with procedurally generated terrain recently and have now decided that I can't be bothered to press play every time I want to see my mesh, so I made some basic editor GUI-elements to allow for more convenient mesh generation. On the CPU, that worked quite well, but of course having to wait a minute for the base mesh to be calculated is not exactly streamlining the whole process. So I moved to ComputeShaders for mesh creation, following a tutorial I found online. By following it, I have succeeded in getting a button to fill a ComputeBuffer with verteces consisting each of a position and a uv-coordinate.
Now there are a few problems: The tutorial uses a call to Graphics.DrawProceduralIndirect from Update, which I have gotten to work in the past, but now I would like to continually draw the geometry without the game playing - is that possible? Calling DrawProceduralIndirect once did nothing, as far as I could tell. Furthermore, my console is flooded with warnings telling me that I need to release my ComputeBuffers, because if I don't, the garbage collector will. This is an issue, because I do not want to release these buffers - I want to continuously render their contents, after all.
One possible solution I can think of is sending all triangles to the CPU, throwing them into a mesh and finally using a built-in mesh renderer to display them. I would prefer not to have to resort to this approach, however, since 1) I'm not sure that would be a staggering increase in performance and 2) I would like to write custom shaders for displacement and the like later on, so it would be much more intuitive to leave the geometry on the GPU.
Here are the exerpts of my code I think relevant:
public class TerrainRenderer : MonoBehaviour
{
[SerializeField] private Material terrainMat;
private ComputeBuffer meshBuffer;
private ComputeBuffer indirectDrawArgs;
private bool buffersInitialized;
private void DrawTerrain()
{
Bounds bounds = new Bounds(transform.position, transform.lossyScale);
Graphics.DrawProceduralIndirect(terrainMat, bounds, MeshTopology.Triangles, indirectDrawArgs);
}
public void ReleaseBuffers()
{
meshBuffer.Release();
indirectDrawArgs.Release();
buffersInitialized = false;
}
public void UpdateBuffers(ComputeBuffer mesh, ComputeBuffer drawArgs)
{
if (buffersInitialized) ReleaseBuffers();
meshBuffer = mesh;
indirectDrawArgs = drawArgs;
buffersInitialized = true;
DrawTerrain();
}
}
// From class TerrainGenerator
public void GenerateMeshOnGPU()
{
// This method fills both the meshBuffer and the drawArgs buffer appropriately.
GetComponent<MeshGenerator>().CreateMeshOnGPU(subdivisions, scale, out ComputeBuffer meshBuffer, out ComputeBuffer drawArgs);
targetRenderer.UpdateBuffers(meshBuffer, drawArgs); // targetRenderer is a reference to an instance of TerrainRenderer
}
My question, then, is this: Is what I have described even possible? If so, could you point me to a resource on this topic? Thanks in advance!