4
\$\begingroup\$

I'm using OpenGL to display a 3D network, with nodes represented as spheres (I haven't gotten to edges yet). I'm a total novice, and having a bit of trouble wrapping my head around OpenGL.

These networks need to be generated programmatically, so I've got a function that produces vertices for a sphere with radius 1 centred at the origin, and I'm translating and scaling it to produce each of the nodes in the network. I'm using glDrawElements() to draw my nodes, so I'm storing indices for the vertices of my sphere as well.

Once a network is produced, it doesn't change. The camera position can change, but nothing else will. My current strategy is the following:

  • When a network is generated, for each node, make a copy of the unit sphere, and apply the appropriate translation * scale matrix. Store all of the vertices (and associated colours) in a single array/VBO.
  • When drawing, set the scene-to-camera and perspective matrices to a uniform, then use a single glDrawElements() call to draw all my nodes.

So a couple of questions about this:

  1. Since all my nodes are essentially identical, I could just store vertices for one sphere, and transform the sphere on the fly when I render the scene. There might be a lot of nodes, so this could save substantial memory. But each sphere has quite a different set of colours... is there a way to tell OpenGL to use an offset for the colour data but not the vertex data?
  2. Assuming the answer to part 1 is no, would it be better to keep vertices for a single sphere in my VBO, and then substitute the colour data and draw each node with a separate call to glDrawElements()? Or is there some other solution that I'm not thinking of?
\$\endgroup\$
1
\$\begingroup\$

You have several options.

  • You don't need to use interleaved buffers (where the positions, normals, colors, et cetera are all in one buffer separated by stride bytes). When you specify vertex data (specifically when making calls to glVertexAttribPointer), you can specify distinct buffers for each attribute. So you could have one buffer for positions, and other buffers for all your colors, and you can enable or disable them as needed.

  • You could use instancing, passing the color data as per-instance data rather than shared data.

  • You could eschew storing the color data in the vertex buffer at all. After all, if it's just a flat color per vertex, that's a lot of redundancy itself. Instead, pass a shader uniform into your shader that defines the color of the sphere when rendered, and use that color in the fragment shader.

I would recommend the last approach. This way, you create one vertex buffer defining your sphere positions relative to the origin in model space. You can render this buffer many times, setting a different world transformation matrix (which is itself just a shader uniform) as well as a different appropriate color. The world transformation matrix is how you position each sphere in the world, and the color is obviously what controls the color value.

This way you only have a single copy of the geometry (which itself does not contain a lot of redundant extra bytes to specify color data, unless you really need multi-colored spheres), you have support for uniquely coloring each node in your network, and you let the GPU do the transformation work it's designed to do rather than doing it yourself CPU-side.

\$\endgroup\$
  • \$\begingroup\$ I like the idea of instancing, but my nodes are coloured by latitude (a pie chart centred at the "North Pole" that I turn towards the camera). As for separate buffers, what about efficiency of binding/releasing all those buffers each time? \$\endgroup\$ – rainbowgoblin May 14 '14 at 19:36
  • \$\begingroup\$ I guess I could set a per instance colour lookup array, then set latitude indices for my sphere vertices and look up the colours inside the shader. Does this seem doable? \$\endgroup\$ – rainbowgoblin May 14 '14 at 19:42
  • \$\begingroup\$ Don't release the buffers every frame. Binding is not that expensive; if you need to do it, you need to do it. You could probably determine the latitude of a given vertex based on the vertex's model-space coordinate and not need to do any fancy lookups. \$\endgroup\$ – Josh May 14 '14 at 20:34
  • \$\begingroup\$ Well, I'll need the latitude-to-colour lookup for each sphere regardless. And I could use model space coordinates to compute latitude, but it would involve a couple of trig functions, then I'd have to convert that to an index. The alternative is a short int vertex attribute. \$\endgroup\$ – rainbowgoblin May 14 '14 at 20:59
  • \$\begingroup\$ Yes. It's going to be a classic "memory versus time" trade-off you'll have to make based on whatever works best for you. \$\endgroup\$ – Josh May 14 '14 at 22:33

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.