0

I have a level I need to render. It is broken into hundreds of submeshes with information on which submesh can see which submesh. Each level has a pool of textures that all of those submeshes can reference. All submeshes have vertices that are sorted by texture. Here is an example.

Submesh 1

Index[1, 3, 4, 5, 6, 2, 7, 8, 10...] Texture 1

Index[12, 15, 16, 12, 13, 19] Texture 2

When there are 1000 submeshes and 20 textures possible, the amount of texture swapping gets ridiculous even factoring in visibility.

I have all of my submeshes sequentially in a VBO. I have been trying to figure out the best way to go about optimizing rendering and eliminate all unnecissary texture swaps. If I just sort the VBO, I lose the submesh connections and the visibility data becomes useless. Or is there a better way to do that?

Or should i create an index list every frame based on visibility or is that too slow?

Edit: Here is a breakdown of my current setup.

VBO with all of the vertices in order running from submesh 1 texture 1, submesh 1 texture 2, all the way to submesh n, texture n.

I have an IBO which is just all of the indices to all of the meshes, in the same relative order.

When I render, I consult the submesh and have an starting index and count which are the start index in the IBO for that submesh and texture and then the count which is the number that have that texture.

This is essentially why I am doing so much swapping which is really slowing things down.

4

3 回答 3

5

VBO with all of the vertices in order running from submesh 1 texture 1, submesh 1 texture 2, all the way to submesh n, texture n.

There's your problem. A "submesh" should be a single rendering call, not multiple rendering calls. Each "submesh" should be the equivalent of your "submesh X, texture Y" pairs. A particular submesh uses a particular set of glVertexAttribPointer calls, glBindTexture calls, and a single glDrawElements call to render.

Each submesh in this scheme uses a specific texture. Therefore, you can sort your draw order by which textures they use. So all submeshes that use texture 1 can be rendered at the same time, with just one glBindTexture call between them.

For best performance, since all of your "submeshes" use the same buffers (and therefore, it's a good change that they all use the same vertex format), you should also try to use glDrawElementsBaseVertex to render a particular "submesh", rather than making separate glVertexAttribPointer calls for each submesh.

The idea there is to make your VBO effectively one long array, with all of every submesh's vertices in the same array. Each submesh stores a base offset to its index data, a count of vertices to render, and a base vertex offset, which represents where which index that submesh's data starts in the big array.

At the start of rendering all submeshes, you make one set of glVertexAttribPointer calls. And then it's just glBindTexture and glDrawElementsBaseVertex from then on. You don't call glVertexAttribPointer ever for each submesh. You use the BaseVertex to define where each submesh's data comes from in the VBO.

于 2013-05-14T08:44:09.580 回答
1

After your edit:

You need a mid step, which would short meshes to render based on texture id. You need to make a drawing call (glDrawElements), per submesh. With this in mind you can do the following:

Basically you do the same, but instead of rendering stuff, store that mesh into a display list for the texture it needs.

Create an object called display list, which holds an array of submesheses (pointers) to be rendered. Create an array of such objects, 1 per texture id you have.

In your algorithm, before rendering stuff, fill the above structure and don't render anything yet.

When you are done resolving what is visible and needs rendering, traverse the the array of display lists (0....num_textures) and render the submeshses for that texture. HINT: In this step you can find adjacent submeshes and just perform one call to glDrawElements.

Optimized the above idea.

This is easy to implement and will minimize texture state changes.

于 2013-05-14T08:39:42.670 回答
0

Surely you'll have a index buffer as well, you pass into glDrawElements. I suggest rearranging the contents in the index buffer. Or, if you don't want to modify the data, call glDrawElements for each submesh separately with the right offset and vertex count and sort the meshes by texture.

于 2013-05-14T06:52:45.027 回答