I've been learning OpenGL graphics programming and I've decided I'd quite like to make a simple game using OpenGL.

Drawing something in OpenGL, needless to say, is quite the endeavour. However it usually follows the following steps:

1) Use an array to outline where the vertices are of what I want to draw, as well as

2) Create a vertex array object VAO to store the vertex buffer objects and store how the data is formatted, etc.

3) Generating vertex buffer objects VBOs and element buffer objects EBOs (if applicable). Binding the relevant buffer data to them (ie, passing in the vertex data to the VBO and vertex drawing order to the EBO).

4) Instructing OpenGL on how the data is actually formatted within the array I defined at the start (the vertex coordinates, texture coordinates, etc) using glVertexAttribPointer.

5) Binding the textures if necessary, enabling the vertex and fragment shaders, binding the vertex array, and then finally drawing.

6) Unbinding the vertex array

Since I'm almost always following these 6 steps when I want to draw things I thought I'd be able to abstract it. I thought I could do this by passing in a batch of vertices to a 'render' class every render call which would do these steps every time for me so I can render things more easily without the great big spiel that takes a good 20 lines of code every time I want to draw a box.

This would be immensely helpful. For example, suppose I wanted to draw a heightmap. All I'd have to do would be to pass in the vertex locations/textures to bind/shaders to use, etc, and it'd draw it for me! Possibly even alongside some trees/rocks that I could pass in to that one render call.

However I've realised that there're a lot of technical limitations with this and I'm beginning to question whether this is even a fundamentally correct approach to OpenGL rendering.The reason why I think this is fundamentally wrong is because it still doesn't really avoid the big spiel of code that I have to go through every time I want to draw some vertices - I just create a 'middleman' class inbetween, which is a bit useless and unnecessary.

What are the best practises when it comes to creating a simplified and easy-to-use rendering 'pipeline' like what I'm trying to describe?

  • \$\begingroup\$ Just to be clear, you're not repeating steps 1-3 every frame, right? Only when you load a new asset, then you re-use those buffers each frame those assets need to be drawn? \$\endgroup\$ – DMGregory May 4 at 16:49
  • \$\begingroup\$ See also: Should I unbind buffers? \$\endgroup\$ – DMGregory May 4 at 16:57

For most rendering use cases, the vertices of a model don't change every frame. Much of what we want to draw in a game is either completely static geometry, like the terrain or buildings; re-used props that need the same vertex buffer every time, just different transforms/materials; or character meshes that might animate according to a skeleton, but still use the same underlying mesh every frame.

So it's wasteful to create and dispose of the vertex data every frame, when we could just leave that data in video memory and reference it when we need it.

Instead you'll usually create a data structure to represent your mesh, that references the appropriate buffers/attribute bindings to use when drawing. You create this data structure once when the mesh is loaded/created and its data uploaded to video memory, and any object that needs to be drawn with this mesh will reference this data structure.

When you draw a frame, you look up into this data structure to find and use the appropriate, already-populated buffers, rather than re-creating them from scratch.

So, there's still a middle-man, but the extra layer does most of its work when assets are loaded / unloaded, and provides just a minimal bit of boilerplate reduction in each draw call. Your main savings is moving the rest of the work outside your draw loop entirely.

| improve this answer | |

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.