null
null

Reputation: 625

OpenGL - How to render many different models?

I'm currently struggling with finding a good approach to render many (thousands) slightly different models. The model itself is a simple cube with some vertex offset, think of a skewed quad face. Each 'block' has a different offset of its vertices, so basically I have a voxel engine on steroids as each block is not a perfect cube but rather a skewed cuboid. To render this shape 48 vertices are needed but can be cut to 24 vertices as only 3 faces are visible. With indexing we are at 12 vertices (4 for each face).

But, now that I have the vertices for each block in the world, how do I render them?


What I've tried:

I am aware of frustum culling and occlusion culling, but I already have problems with some cubes in front of me (tested with a 128x128 world).


My requirements:

  1. Draw some thousand models.

  2. Each model has vertices offsets to make the block less cubic, stored in another VBO.

  3. Each block has to be an individual object, as you should be able to place/remove blocks.

Any good performance advices?

Upvotes: 0

Views: 1267

Answers (2)

Ripi2
Ripi2

Reputation: 7198

Any decent graphics card (since about 2010) is able to render a few millions vertices in a blinking.

The approach is different depending on how many changes per frame. In other words, how many data must be transferred to the GPU per frame.

For the case of small number of changes, storing the data in one big VBO or many smaller VBOs (and their VAOs), sending the changes by uniforms, and calling several glDraw***, shows similar performance. Different hardwares behave with little difference. Indexed data may improve the speed.

When most of the data changes in every frame and these changes are hard or impossible to do in the shaders, then your app is memory-transfer bound. Streaming is a good advise.

Upvotes: 0

Nicol Bolas
Nicol Bolas

Reputation: 473192

This is not desireable as I need every cube to have different textures, lighting, etc... Selecting a single cube within that huge mesh is not possible.

Programmers should avoid declaring that something is "impossible"; it limits your thinking.

Giving each face of these cubes different textures has many solutions. The Minecraft approach uses texture atlases. Each "texture" is really just a sub-section of one large texture, and you use texture coordinates to select which sub-section a particular face uses. But you can get more complex.

Array textures allow for a more direct way to solve this problem. Here, the texture coordinates would be the same, but you use a per-vertex integer to select the correct texture for a face. All of the vertices for a particular face would have an index. And if you're clever, you don't even really need texture coordinates. You can generate them in your vertex shader, based on per-vertex values like gl_VertexID and the like.

Lighting parameters would work the same way: use some per-vertex data to select parameters from a UBO or SSBO.

As for the "individual object" bit, that's merely a matter of how you're thinking about the problem. Do not confuse what happens in the player's mind with what happens in your code. Games are an elaborate illusion; just because something appears to the user to be an "individual object" doesn't mean it is one to your rendering engine.

What you need is the ability to modify your world's data to remove and add new blocks. And if you need to show a block as "selected" or something, then you simply need another per-block value (like the lighting parameters and index for the texture) which tells you whether to draw it as a "selected" block or as an "unselected" one. Or you can just redraw that specific selected block. There are many ways of handling it.

Upvotes: 2

Related Questions