I think I have a problem...

Started by
8 comments, last by CyberSlag5k 18 years, 10 months ago
Before I go insane coding what I think I have to do to get my models drawing really efficiently, lemme run it by you fine people to see if there's not an easier way of doing this. So I'm importing my models from the .an8 format (anim8or's proprietary format), and I decided to take the care to split my models up into separate display lists according to texture and material. Not such a bad gig, except the materials and textures are stored together, like this:

material { "blackOnWhite"
    surface {
      /* RGB chunk no longer used */
      rgb { 224 224 224 }
      lockambiantdiffuse { }
      ambiant {
        rgb { 224 224 224 }
        factor { 0.30000 }
        texturename { "texture2" }
        textureparams {
          blendmode { decal }
          alphamode { none }
        }
      }
      diffuse {
        rgb { 224 224 224 }
        factor { 0.70000 }
        texturename { "texture2" }
        textureparams {
          blendmode { decal }
          alphamode { none }
        }
      }
      specular {
        rgb { 255 255 255 }
        factor { 0.20000 }
      }
      phongsize { 32 }
    }
  }

Now I had been working on compiling a list of textures and saving them in parallel arrays by ID and name, so that I could take each chunk and say "Oh you're the grass texture. You'll make up the 3rd display list of each model. Have a nice day!" I find it's nice to be as courteous as possible to my data, don't you? Anyway, the idea is for each model, I bind the first texture, draw the geometry for that texture, bind the next, draw that geometry, and so on and so forth. I do it this way because if I have 1,000 space ships on the screen at any given moment, and each space ship has 2 different textures, I don't want to re-bind the textures 2,000 times. Instead, I set the texture the first time, draw half of each ship, set the texture the second time, draw the other half, and I'm done. As I think about it, though, I'm doing this based on the assumption that texture switches are costly, but I'm not entirely sure I actually know that. Is that the case? Should I avoid re-binding the same texture over and over again? The reason I ask all of this, is because while the texture thing is somewhat convoluted the way it needs to be done, it is much more complicated when you throw materials into the mix, given a material may have the same material properties as another, only with a different texture. Regardless, it requires me to split the mesh up yet again with regards to the changing materials, all the while accomodating the changing textures from before. That's getting a little nuts. Perhaps someone can suggest a better technique? Or at least say "Silly CyberSlag, changing textures isn't costly", as I am now assuming they are. Thanks in advance!
Without order nothing can exist - without chaos nothing can evolve.
Advertisement
Hi,

Texture switching is indeed costly and so are glMaterialf calls. So its best to sort by material. Probably anima8ors proprietary format already does that so you shouldn't have to do it. Having textures along with materials is the common norm generally and by doing that all costly calls will be called to the minimum extent as possible. Currently this is how I am avoiding the problem you have - I am having a manager which handles all material data, another which handles all texture data. So given a material name - set the material, the material also contains the texture name, so as required texture gets bound and if no texture exist - bind the default texture - 0. Currently it seems to be working well for me. The only major drawback I face is I cant have materials with same names from differnt models.

Hope this helps.
The more applications I write, more I find out how less I know
Thank you for your response, CRACK123. So what you're saying is, only work with the materials and let them handle the textures? So if my mesh has 4 different materials that have textures setup like this:

mat1 - tex1
mat2 - tex1
mat3 - tex1
mat4 - tex2

I will only suffer 1 texture change? In other words, if I attempt to bind a new texture, but it is the same as the one that is presently bound, I won't suffer the costs of a texture change? Or am I misunderstanding...

If I'm reading you correctly, though, then I need only deal with the list of materials per model, and since the textures are supposedly sorted (I'll look into that), the texture switches will only encur costs when a texture really does switch. Is that right? And even if the textures do rebind even though they're the same texture, I suppose I could just save the ID of the present texture and do a check each frame, which wouldn't be costly. Do I have it right?

Thanks again, CRACK123!
Without order nothing can exist - without chaos nothing can evolve.
Quote:Original post by CyberSlag5k
Before I go insane coding....

Quote:
I find it's nice to be as courteous as possible to my data, don't you?


Too late I feel [grin]
*places a call into the loony bin to come and take CyberSlag away*

However, while we wait, CRACK123 is indeed correct, switching textures is a very expensive call, infact its the 2nd most expensive switch you can perform after shader changeds.

The reason, alot of work has to be done by the GPU on a change, such as caches having to be invalidated and flushed and the new data setup. Materials also have some work behind them but they arent as expensive.

So, yes you are quite right to sort by textures first and materials second.

Quote:Original post by CyberSlag5k
I will only suffer 1 texture change? In other words, if I attempt to bind a new texture, but it is the same as the one that is presently bound, I won't suffer the costs of a texture change? Or am I misunderstanding...


I wouldnt rely on the driver to check state for you, manage it yourself via the id check as you mentioned.
(remember to store multiple ids if you are multi-texturing)
Quote:Original post by _the_phantom_
Quote:Original post by CyberSlag5k
Before I go insane coding....

Quote:
I find it's nice to be as courteous as possible to my data, don't you?


Too late I feel [grin]
*places a call into the loony bin to come and take CyberSlag away*


Haha. I won't refute the claim but you know you'd miss me [wink].

Anyway, so just to confirm, attempting to re-bind the same texture doesn't cost anything significant? So doing this:

glBindTexture(GL_TEXTURE_2D, tex1);
glBindTexture(GL_TEXTURE_2D, tex1);
glBindTexture(GL_TEXTURE_2D, tex1);
glBindTexture(GL_TEXTURE_2D, tex1);
glBindTexture(GL_TEXTURE_2D, tex1);

only has the cost associated with a single texture bind? Thus I need not worry about which textures I'm setting because they are already sorted and I'll be re-binding the same texture over and over again with (practically) no cost?

If so, you guys have totally made my day.
Without order nothing can exist - without chaos nothing can evolve.
Quote:glBindTexture(GL_TEXTURE_2D, tex1);
glBindTexture(GL_TEXTURE_2D, tex1);
glBindTexture(GL_TEXTURE_2D, tex1);
glBindTexture(GL_TEXTURE_2D, tex1);
glBindTexture(GL_TEXTURE_2D, tex1);

only has the cost associated with a single texture bind?

NO (last time i checked)
since i had a couple of spare minutes i wrote up a test app (+ i was curious as to weather the situation has changed (with new drivers) since the last time i checked years ago)

int i=1000000;
while ( --i )
{
glBindTexture( GL_TEXTURE_2D, tex0 );
}
runs at ~20fps
/////////////////////////////////////

void otherbind( int id ) // not imlined
{
static int current_id=-1;
if ( current_id != id )
{
glBindTexture( GL_TEXTURE_2D, id );
current_id = id;
}
}

while ( --i )
{
otherbind( GL_TEXTURE_2D, tex0 );
}
runs at ~200fps

thus theres a huge speed difference between the two (thank god)
yeah, I didnt think drivers did any state tracking management.
Quote:Original post by CyberSlag5k
If I'm reading you correctly, though, then I need only deal with the list of materials per model, and since the textures are supposedly sorted (I'll look into that), the texture switches will only encur costs when a texture really does switch. Is that right? And even if the textures do rebind even though they're the same texture, I suppose I could just save the ID of the present texture and do a check each frame, which wouldn't be costly. Do I have it right?



Not quite. What I meant was you would have something like

bind material
bind texture
indices/vertices/normals/colors etc

or you could go like
bind texture
bind material
indices/vertices/normals/colors etc

So it would go something like
texture material model_data
texture material model_data
texture material model_data

So In effect you would be changing/binding textures only when it is actually required, like approximately maybe once in 4-5k polygons maybe - you will not doing any redundant bindings.

Quote:Original post by CyberSlag5k
Thank you for your response, CRACK123. So what you're saying is, only work with the materials and let them handle the textures? So if my mesh has 4 different materials that have textures setup like this:

mat1 - tex1
mat2 - tex1
mat3 - tex1
mat4 - tex2

I will only suffer 1 texture change? In other words, if I attempt to bind a new texture, but it is the same as the one that is presently bound, I won't suffer the costs of a texture change? Or am I misunderstanding...



This is what I would in this case - sort tex1 data completely. then sort mat1, mat2 and mat3 data. Leave mat2 and tex2 as it is or repeat the sorting if required. In effect I will end up reducing a lot of material and texture changes.
The more applications I write, more I find out how less I know
Thanks guys. I think I'm getting closer to knowing what I want to do. Here's where I'm at so far.

I want to split up my meshes into separate display lists according to material and by texture. As the texture is stored in the material, I store the presently bound texture, so I can just split the mesh up by material. Once I have all of my display lists created and I'm ready to draw, I do the following:

Set the first material and bind its texture
Call the first display list for each model
Set the second material and bind its texture iff it is not presently bound (ala the ID check)
Call the second display list
Repeat until out of materials

Sound good? Sounds messy, having to compile a list of materials, but it sounds deliciously efficient.

Am I ready to rock?
Without order nothing can exist - without chaos nothing can evolve.

This topic is closed to new replies.

Advertisement