OpenGL: Multiple material per VBO.

OpenGL: Multiple material per VBO.

Postby dusted » 23 Jan 2011, 17:46

Hi, I'm writing a loader/renderer, and using VBO's for awesomeness, as of now I have a VBO with an interleaved array (XYZnXnYnZtUtV) and it works great.
I'm rendering as a bunch of triangles, and when it comes to applying materials to the tris I'm in doubt on how to do it most efficiently..

I want to be able to support multiple materials per vbo.
What I'd love to do is something like creating an array of material properties, and then somehow tell that triangle n..N should use mat 0 from the array, and so on, in order to avoid several glmaterialfv calls (for ambient, diffuce, spec, and friends).
I have no idea if anything like that is even remotely possible, but in short, I'd like to simply pump my materials properties into opengl once and for all, like I'm doing with the vertex data.

The only thing I can think of is something like a material group, and material properties structs
{l Code}: {l Select All Code}
typedef struct  {
int matIndex; //Index into material array.
int start; //Apply this material from this offset into VBO.
int stop; //and this many triangles
} matGroup;

typedef struct {
  GLuint textureID; //there may be a diffrent texture for this part of the model
.. a bunch of material properties, like GLfloat spec[3]; for specular light color
} matProps;

struct model {
 GLuint vboName; //Name given to VBO
 matProp* materials; //Array of materials.
 matGroup* groups; //Array of material groups
 int groupCount; //Number of groups
}


Then, when rendering the model, the code would loop the groups, something like
{l Code}: {l Select All Code}
for(i=0; i < model->groupCount; i++)
{
//Set texture (maybe do a check to see that it's not allready bound
 glBindTexture(GL_TEXTURE_2D, model->materials[ model->groups[i].matIndex ].textureID);
//  Set material properties for this group of triangles.
  glMaterialfv( someGlEnum, model->materials[ model->groups[i].matIndex ].someMaterialProperty );
 ... multiple glMaterialfv calls here, one for each property.
//Finally, render this part of the geometry
     glDrawArrays(GL_TRIANGLES, model->groups[i].start, model->groups[i].stop);

}


This is just pseudo C, nothing I've done, the general idea would be to keep a list of indicies into the geometry in the buffer object, and then set material properties and render, for each chunk of geometry.
It's not too pretty, any way to get opengl to remember material properties, and save a lot of calls? The idea of VBOs was to save lots of calls, so it's counterproductive to have to split the objects into parts based on material properties/textures and such.

I'm stuck, and any hint as to what I need to read would be much appreciated :) Keywords of sorts ? I have the red book for opengl 2.1 and if there's a chapter there I could read that'd be great, I've gone through the pages about VBOs but no mention of material properties there.
User avatar
dusted
 
Posts: 83
Joined: 27 Feb 2010, 04:35

Re: OpenGL: Multiple material per VBO.

Postby amuzen » 24 Jan 2011, 17:43

The simplest solution is to just go with the approach of the pseudocode. If you cache the values and only call the GL functions when the values change, the state changes hardly introduce any overhead, I think.

There are other approaches that might allow you to avoid some of the state changes but they aren't horribly pretty and come with some limitations. For example, you could bake the material properties to a texture that you index in a shader based on the material ID of the vertex. The drawback of the method is that you need to generate the texture and do an extra texture lookup for each vertex. It isn't horribly elegant really and you still need to bind the textures.

Alternatively, you could reduce the number of GL calls by storing the material properties to display lists that you call when you switch material groups. That'd allow you to switch the material with just one call, though I'm not sure if it has significance performance wise. Might be worth a shot if you target GL 2 and don't mind display lists being deprecated in 3.

There might be other options too, such as using multiple display lists, but I don't think it's worth the trouble. I'd just go for the pseudocode.
User avatar
amuzen
LoS Moderator
 
Posts: 327
Joined: 05 Dec 2009, 02:49

Re: OpenGL: Multiple material per VBO.

Postby dusted » 26 Jan 2011, 16:57

Thank you, I think it might beautify my code quite a bit to be able to store an array of displaylist names instead of an array of material properties, and since I'm also going to be using multitexturing and envmapping in some cases, this will reduce the logic needed in the rendering code :)
Great idea, thank you :)
I'm writing for 2.1 because I have the redbook, and I assume that new gfx drivers won't remove support for 2.1 anytime soon, as that'd break about all existing games.
User avatar
dusted
 
Posts: 83
Joined: 27 Feb 2010, 04:35

Who is online

Users browsing this forum: No registered users and 1 guest

cron