3
\$\begingroup\$

I have created a large variety of shaders for my game engine for different use cases. The vertex input for the shaders depend on what I want to do with them. For example, if I want to just render the wireframe of a mesh, I do not need texture coordinates, normals, etc. because I just need basic vertex information. However, when I render animated meshes (I use Skinned Animation), then I need additional information like joint link weights for each vertex.

My question is: What is the best way to manage Vertex Buffers? Do I create a Vertex Buffers for each use case when I create the model and store them for later use, i.e. I select at run-time which of the stored Vertex Buffers to use for rendering? Do I create the Vertex Buffer I need at run-time in each render cycle? What is the best way to do it?

I am using DirectX 11 and C# (using SharpDX as wrapper).

\$\endgroup\$
8
  • 1
    \$\begingroup\$ How often do you need to draw wireframes and is drawing wireframes a performance-critical path? \$\endgroup\$ Commented Aug 11, 2020 at 20:03
  • \$\begingroup\$ I mainly use a single type of vertex input for rendering a mesh, e.g. a model is normally either static (rock, brick, ..) or animated (NPCs, ...) and rendered either solid textured or as wireframe. I have a few vertex shaders that I use for all types of models like teleporting effects that do not need any texture information. But these are special cases and it might be okay to expand their vertex input layout for the sake of more simple Vertex Buffer management. \$\endgroup\$ Commented Aug 11, 2020 at 20:16
  • \$\begingroup\$ What I'm asking here is: is wireframe mode a "developer" setting where it might actually be OK if it runs slightly suboptimal? \$\endgroup\$ Commented Aug 11, 2020 at 21:32
  • \$\begingroup\$ Yes, it is for development only, e.g. when I check if the terrain meshes are correct or procedural generated content is properly meshed. Most of my meshes use one major Vertex and Pixel Shader and then a few shaders for special occasions like object highlighting or a teleporter effect. \$\endgroup\$ Commented Aug 12, 2020 at 8:27
  • \$\begingroup\$ Using an input layout, you can define separate buffers for each set of components e.g. a position buffer, a normal buffer, a texco buffer, tan/bitan, etc. You generate these once when you load the model. Based on which shader you are running, bind only the buffers with the data you need. This will minimize the amount of data needed for the operation. \$\endgroup\$ Commented Aug 12, 2020 at 12:57

1 Answer 1

2
\$\begingroup\$

If there was just one "proper strategy" or "best way", the API would give you only that one option to ensure everyone got the best outcome.

But that's not how gamedev works. Different games have different needs.

  • In one game, every mesh needs texture coordinates and normals and tangents, so they can set up every buffer following that pattern, consistently, and never change it.

  • In another game, meshes sometimes need to be drawn without normals/tangents, but only rarely/unpredictably (say, when the player toggles to X-Ray vision), so it makes sense to keep using the full buffer all the time even if it contains some unneeded info for some passes.

  • In another game, all the environment meshes need normals and tangents, character meshes need all that plus skinning information, but the UI meshes need only texture coordinates, and all these sets are disjoint. So the developers can simply tag each mesh asset with the appropriate vertex buffer contents it needs as part of their asset metadata, and build the buffer once on load, never changing it after that.

  • In another game, the same mesh is viewed with wildly different shaders in different game states, and it's performance-critical that it not have any excess information in its vertex buffer, so the game re-generates its buffer each time it transitions to a new state to have just the info needed in that state.

  • ...etc.

We don't know which of these games you're making. You might not even know that yet!

But it's probably a safe bet that your models typically need texture coordinates and normals, so build a basic buffer that contains what you need for most of the cases you've come across thus far.

Then, when you find a case that needs more information, change your code to suit that case. (Maybe you tag the asset as needing a different buffer structure on import, maybe you re-generate the buffer when you enter the specific state that needs the extra info)

When you find a case that needs less information, profile. Maybe it's not a problem to be sending the extra data down the pipe, and you can focus on something else for now, until it becomes a problem.

\$\endgroup\$
2
  • \$\begingroup\$ Calculating the Vertex Buffer for each mesh in each frame is very expensive. Maybe I should re-phrase my question to: Is it better to store multiple Vertex Buffers for my meshes for different use cases or to have too many properties in my Vertex Input Layout? For example, when I render my scene, I first create a shadow map to enable Soft Shadowing. For calculting the shadow map, I do not need detail information about my meshes' vertices (texture coords, normals, ...), I just need to know where the vertices are. But in the same render cycle, I will need all information for final rendering. \$\endgroup\$ Commented Aug 12, 2020 at 8:32
  • 1
    \$\begingroup\$ Note that nowhere in this answer does it say anything about re-generating buffers every frame. You already know not to do that if the data hasn't changed in between. Whether having two copies of the buffer is a performance win in your use case is a question that profiling will answer much more accurately than asking Internet randos. 😉 \$\endgroup\$
    – DMGregory
    Commented Aug 12, 2020 at 11:28

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .