Monday, November 9, 2015

opengl - Are interleaved vertex data formats better than non-interleaved formats?


I have been reading up on data formatting for 3D objects so that I can render my meshes as fast as possible in OpenGL. I am quite new to OpenGL so bear with me.


The format for interleaving your meshes goes something like:


position, normal, texture1, texture2 //this I understand


Most formats for 3D meshes, however, don't use this structure. From my understanding the interleaved format is fast for execution but isn't necessarily the best in terms of size, since you never really have as many unique normals as you do vertices, since (if you are using hard shading) all normals for a face would be the same.


A hard shaded basic cube for example has 8 unique vertices and 6 unique normals.



So my question is, is it worth it to set up an interleaved format like this despite the fact that if you had 3 separate buffers you would use MUCH less data?


Also (remember I'm new) is it somehow possible to do pack your vertex information like:


all positions, all normals, all tex1, all tex2 //so all of one type in a sequence


and have different sets of indices for each type? Or is that just dumb?



Answer



Yes, interleaved is worth it.


Interleaved VBOs has no effect on the size of data. Even with separate VBOs for each attribute, you only have a single index buffer, so you need to duplicate any vertex attributes appropriately. That means that you have a single value of an attribute shared by multiple vertices, you must duplicate it for each vertex, no matter how you laid out your buffer objects. Yes, this means that some model formats require a lot of processing to put into a renderable format.


The GPU is generally much happier with a single interleaved buffer. Vertex processing happens by taking all the data for a single vertex and then running the shader. It's much faster to grab all that data in one go from a single memory location than to query multiple memory locations, due to how memory buses and caches work.


You could use a library like Open Asset Import Library to read your source format and then process it into a custom, efficient-to-render (for your engine) format and save that to disk as part of your content pipeline. You could also write a model software plugin that directly loads/saves the engine format, though this tends to be harder and you generally want the fully-featured native format around as your asset source (you almost certainly do want a plugin that can visualize the model in your renderer, though, so artists can see how things look while working on it and not being forced to guess or wait; iteration speed is king). Your engine then loads that efficient, processed file for rendering. Ideally your format is something you can copy directly into a vertex buffer and index buffer and whatever metadata structures you need (again, this is why this format is generally custom for an engine and not a general-purpose format).


You can pack multiple attribute streams into a single VBO end-to-end like you ask, though again it's still inefficient. The GPU must access multiple locations in the buffer for each vertex, which negatively impacts memory performance (same goes for CPU memory accesses). Interleaved is the way to go.



No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...