17
$\begingroup$

A few years ago I tried to implement this GPU Gem in OpenGL to generate 3D procedural terrain using Marching Cubes. The article suggests to implement Marching Cubes in a geometry shader to maximum efficiency. This means I need to run the shader once for every voxel in the domain, and it'll generate the entire geometry in that cell.

One problem I stumbled upon was how to get the geometry shader running without actually having anything to render outside of that shader. My solution (which seemed rather hacky) was to render a point in each cell, discard it with the geometry shader and emit my triangles instead. I never found a proper solution and this workaround remained in the final code.

So, is there anyway to tell OpenGL to start a rendering pass from the geometry shader without any input geometry? Or will I always have to send some dummy points to the GPU to get things running.

$\endgroup$
15
$\begingroup$

No, there is not really a way to do that.

A geometry shader invocation requires an input primitive and generates 0 or more output primitives. Without an input primitive, there is not really a way to actually invoke the geometry shader. Of course you can stretch the limits of the geometry shader's maximum number of output primitives for each input primitive (don't know the practical limits right now, should be on the order of thousands maybe). So you maybe could generate 1024 triangles for each point, but you always have to have some input primitives.

What you don't need however is an actual notion of geometry. You don't really have to render 3D points at any reasonable location, they could as well have just some abstract index or texture coordinates or whatever as attributes and not necessarily a meaningful 3D position. Noone dictates what attributes your vertices have. And you can even render vertices without any attributes. But you have to render some primitives to invoke the geometry shader on them, even if those primitives don't have any actual attributes (how you then compute your output geometry in the geometry shader is a different question, though).

But what you actually did, rendering a point for each grid cell and generating the marching cubes triangles for that cell from it, is exactly the straight-forward approach. Of course what attributes this cell contains is up to you, it could be a 3D position, a texcoord into a 3D texture, whatever, but those are the grid cells you render. Purely semantically spoken, you don't actually "discard" those points and then "replace" them by triangles, you "convert" each point into a set of triangles. That's exactly what the geometry shader is for and there's nothing "hacky" or "improper" about it. Noone says the geometry shader has to generate the same output primitive type as was input to be "proper".


What you can do to achieve a largely input-less way of rendering your voxel grid (and this might be what you were actually asking for) would be to just draw a set of attributeless points. This means you don't need any attribute arrays at all and just disable them all and invoke a simple glDrawArrays with the number of cells you need. Then in the vertex shader or the geometry shader you can generate the necessary 3D grid cell index with a little index magic from the input vertex ID (i.e. gl_VertexID, which is the only information you have) and then compute your marching cubes geometry from a lookup into the 3D volume texture (or whatever datastructure).

So, in retrospect I should relativate my statement from the beginning: You can't generate primitives without any input primitives, but you can generate them without any input geometry.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.