0

Attempting to switch drawing mode to GL_LINE, GL_LINE_STRIP or GL_LINE_LOOP when your cube's vertex data is constructed mainly for use with GL_TRIANGLES presents some interesting results but none that provide a good wireframe representation of the cube.

Is there a way to construct the cube's vertex and index data so that simply toggling the draw mode between GL_LINES/GL_LINE_STRIP/GL_LINE_LOOP and GL_TRIANGLES provides nice results? Or is the only way to get a good wireframe to re-create the vertices specifically for use with one of the line modes?

Caustic
  • 377
  • 1
  • 2
  • 9
  • 1
    Would it be acceptable to have two index arrays? You wouldn't need to replicate the actual vertex data, but have separate index arrays that you use depending on whether you draw lines or triangles. – Reto Koradi Sep 05 '14 at 01:03
  • It's a better solution than no solution at all. – Caustic Sep 05 '14 at 01:45
  • If you don't care about using deprecated features you could supply some [edge flags](http://www.felixgers.de/teaching/jogl/polygonEdgeRemoval.html) :) – genpfault Sep 05 '14 at 02:44

1 Answers1

1

The most practical approach is most likely the simplest one: Use separate index arrays for line and triangle rendering. There is certainly no need to replicate the vertex attributes, but drawing entirely different primitive types with the same indices sounds highly problematic.

To implement this, you could use two different index (GL_ELEMENT_ARRAY_BUFFER) buffers. Or, more elegantly IMHO, use a single buffer, and store both sets of indices in it. Say you need triIdxCount indices for triangle rendering, and lineIdxCount for line rendering. You can then set up you index buffer with:

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuf);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
             (triIdxCount + lineIdxCount) * sizeof(GLushort), 0,
             GL_STATIC_DRAW);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER,
                0, triIdxCount * sizeof(GLushort), triIdxArray);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER,
                triIdxCount * sizeof(GLushort), lineIdxCount * sizeof(GLushort),
                lineIdxArray);

Then, when you're ready to draw, set up all your state, including the index buffer binding (ideally using a VAO for all of the state setup) and then render conditionally:

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuf);
if (renderTri) {
    glDrawElements(GL_TRIANGLES, triIndexCount, GL_UNSIGNED_SHORT, 0);
} else {
    glDrawElements(GL_LINES, lineIdxCount, GL_UNSIGNED_SHORT,
                   triIndexCount * sizeof(GLushort));
}

From a memory usage point of view, having two sets of indices is a moderate amount of overhead. The actual vertex attribute data is normally much bigger than the index data, and the key point here is that the attribute data is not replicated.

If you don't strictly want to render lines, but just have a requirement for wireframe types of rendering, there are other options. There is for example an elegant approach (never implemented it myself, but it looks clever) where you only draw pixels close to the boundary of polygons, and discard the interior pixels in the fragment shader based on the distance to the polygon edge. This question (where I contributed an answer) elaborates on the approach: Wireframe shader - Issue with Barycentric coordinates when using shared vertices.

Community
  • 1
  • 1
Reto Koradi
  • 53,228
  • 8
  • 93
  • 133