Jump to content
  • Advertisement
Sign in to follow this  
BlueSpud

OpenGL Questions about mesh rendering performance

This topic is 2137 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello,

I've been working on my mesh rendering lately for my game engine and with large models I have run into problems. I know that the best thing in OpenGL is to avoid state changes to improve performance. With the model I was rendering, with one solid texture, I was getting ~35-40 fps. After I added multi texturing, I get  ~25-28. I'm using draw lists and here is my code:

//make the list
        int materiali = 0;
        list = glGenLists(1);
        glNewList(list, GL_COMPILE);
        glBegin(GL_TRIANGLES);
        for (int i = 0; i < ModelRegistry.models[m].m.obj.size(); i++)
        {
            if (i == ModelRegistry.models[m].m.materialFaces[materiali].i)
                {
                    //we have a texture change here
                    for (int i = 0; i < Materials.size(); i++)
                        {

                            if  (strcmp( ModelRegistry.models[m].m.materialFaces[materiali].name.c_str(), Materials[i].name.c_str()) == 0)
                                {
                                    materiali++;
                                    if (strcmp( lastMaterial.c_str(), Materials[i].name.c_str()) != 0)
                                    {
                                        glEnd();
                                        lastMaterial = Materials[i].name;
                                        glActiveTexture(GL_TEXTURE0);
                                        glBindTexture(GL_TEXTURE_2D, Materials[i].textureID);
                                        glActiveTexture(GL_TEXTURE1);
                                        glBindTexture(GL_TEXTURE_2D, specularID);
                                        glActiveTexture(GL_TEXTURE2);
                                        glBindTexture(GL_TEXTURE_2D, normalID);
                                        glBegin(GL_TRIANGLES);
                                    }
                                    break;
                                }
                        }

                }
            glNormal3f(ModelRegistry.models[m].m.obj[i].nx1, ModelRegistry.models[m].m.obj[i].ny1, ModelRegistry.models[m].m.obj[i].nz1);
            glTexCoord2f(ModelRegistry.models[m].m.obj[i].tx1, ModelRegistry.models[m].m.obj[i].ty1);
            glVertex3f(ModelRegistry.models[m].m.obj[i].x1,ModelRegistry.models[m].m.obj[i].y1,ModelRegistry.models[m].m.obj[i].z1);
            glNormal3f(ModelRegistry.models[m].m.obj[i].nx2, ModelRegistry.models[m].m.obj[i].ny2, ModelRegistry.models[m].m.obj[i].nz2);
            glTexCoord2f(ModelRegistry.models[m].m.obj[i].tx2, ModelRegistry.models[m].m.obj[i].ty2);
            glVertex3f(ModelRegistry.models[m].m.obj[i].x2,ModelRegistry.models[m].m.obj[i].y2,ModelRegistry.models[m].m.obj[i].z2);
            glNormal3f(ModelRegistry.models[m].m.obj[i].nx3, ModelRegistry.models[m].m.obj[i].ny3, ModelRegistry.models[m].m.obj[i].nz3);
            glTexCoord2f(ModelRegistry.models[m].m.obj[i].tx3, ModelRegistry.models[m].m.obj[i].ty3);
            glVertex3f(ModelRegistry.models[m].m.obj[i].x3,ModelRegistry.models[m].m.obj[i].y3,ModelRegistry.models[m].m.obj[i].z3);

        }
               glEnd();
            glEndList();

Here are my questions, they should be fairly basic, even if you don't understand the code.

 

Can new textures be bound inside glBegin() ?

 

Is there anything faster than glBindTexture() ?

 

Is the accessing data from the std::vector slowing down the rendering?

 

Does the GPU have to go through the for loop every time the list is called?

 

Those are other questions, but I think those are the big ones. Any input would be appreciated because the visual result of the rendering is great, just the frame rate isn't. Thanks.

Share this post


Link to post
Share on other sites
Advertisement
Sorry I'm not going to directly answer your question, but is there a specific reason you are not using "modern" OpenGL? E.g. hardware constraints, portability, or something?

It seems to me that the most effective path to optimization is to use a more modern approach - VBOs, Shaders, etc, if at all possible.

Share this post


Link to post
Share on other sites

Sorry I'm not going to directly answer your question, but is there a specific reason you are not using "modern" OpenGL? E.g. hardware constraints, portability, or something?

It seems to me that the most effective path to optimization is to use a more modern approach - VBOs, Shaders, etc, if at all possible.

I was under the impression that Draw Lists were the fastest. I am using shaders, just not for textures. I'm using program 0 to render just textures. As for not using other aspects of modern OpenGl, I want to have this run on lower end computers.

Share this post


Link to post
Share on other sites

I was under the impression that Draw Lists were the fastest.

Your power level of mistaken…it’s over 9,000!!!

 

I am using shaders, just not for textures.

Why would you do that? Why would you ever mix fixed-functionality and programmable pipelines? Are you maintaining 2 separate lighting pipelines?

 

As for not using other aspects of modern OpenGl, I want to have this run on lower end computers.

You are aware that any version of OpenGL that supports shaders (which you are using) also supports VBO’s and IBO’s, right?
VBO’s and IBO’s have been core since OpenGL 1.5.
Shaders have been core since OpenGL 2.0.


In short, your excuse about compatibility makes no sense and it doesn’t make sense to discuss performance issues until you start using VBO’s and IBO’s.


Ask again when you have switched to VBO’s and IBO’s (and preferably shaders for anything, not just “everything but textures”).


L. Spiro

Share this post


Link to post
Share on other sites


Sorry I'm not going to directly answer your question, but is there a specific reason you are not using "modern" OpenGL? E.g. hardware constraints, portability, or something?

It seems to me that the most effective path to optimization is to use a more modern approach - VBOs, Shaders, etc, if at all possible.

I was under the impression that Draw Lists were the fastest. I am using shaders, just not for textures. I'm using program 0 to render just textures. As for not using other aspects of modern OpenGl, I want to have this run on lower end computers.
I'm not familiar with fixed mode, so I couldn't say on improving performance if you are sticking with that. Be aware, however, that display lists were deprecated way back in 3.1 (or maybe 3.0?), I'd hazard a guess that they are probably 'emulated' somehow by hardware nowadays.

Share this post


Link to post
Share on other sites

I was under the impression that Draw Lists were the fastest.

Your power level of mistaken…it’s over 9,000!!!
 

I am using shaders, just not for textures.

Why would you do that? Why would you ever mix fixed-functionality and programmable pipelines? Are you maintaining 2 separate lighting pipelines?
 

As for not using other aspects of modern OpenGl, I want to have this run on lower end computers.

You are aware that any version of OpenGL that supports shaders (which you are using) also supports VBO’s and IBO’s, right?
VBO’s and IBO’s have been core since OpenGL 1.5.
Shaders have been core since OpenGL 2.0.
In short, your excuse about compatibility makes no sense and it doesn’t make sense to discuss performance issues until you start using VBO’s and IBO’s.
Ask again when you have switched to VBO’s and IBO’s (and preferably shaders for anything, not just “everything but textures”).
L. Spiro
Maybe I was not specific enough. I have a deferred lighting system in place, so I am not using the fixed functionality lighting. I render it in several passes, one being the albedo. I use shaders for all the other passes except that. I simply don't use a shader for that pass because binding program 0 yields the same results as creating a simple shader to render geometry with texture. If just using a simple shader is faster, it would be easy to create a shader to do that, I would do it but I haven't been able to notice a difference.

As for the draw lists vs the vertex buffer objects, I was unaware that vbos were in the older OpenGL versions and I thought it was added it 3.2. I've tried both vertex buffer objects and display lists. Based on my experiences, draw lists are significantly faster, and I've also seen that on the internet. It could just be my video card though. I've also read that internally, the data is stored the same way as vbos in some cases. To me they just seem easier to implement and control, but that's just my opinion. The preformence problem might be somewhere else, and I'll see if I can track that down. Thank you for your input.

Share this post


Link to post
Share on other sites

How many times does this section...

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, Materials[i].textureID);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, specularID);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, normalID);

...actually get called - how many texture binds are there? If the code is being entered hundreds of times that is going to be a problem. Try pre-sorting (off-line) all your triangle by texture.

Share this post


Link to post
Share on other sites

To me they just seem easier to implement and control

This may be the problem. If you have the mindset that applies to display lists and you want per-frame control, you are probably misusing VBO’s.
If you are updating VBO’s frequently, you very well may have poorer performance with them.

 

 


Based on my experiences, draw lists are significantly faster, and I've also seen that on the internet.

Display lists can never be faster than a properly used VBO because display lists always have the additional overhead of memory copies that properly used VBO’s do not.



And while we are on performance, you have 2 strcmp()’s inside a nested loop.

donotwant.jpg

 

 

Assign materials ID’s and do a simple integer compare.

 

 

 


I simply don't use a shader for that pass because binding program 0 yields the same results as creating a simple shader to render geometry with texture. If just using a simple shader is faster, it would be easy to create a shader to do that, I would do it but I haven't been able to notice a difference.

It is faster to use a simple shader.

The fixed-function pipeline is just emulated via shaders.  They often do more work than is necessary.

 

 


I render it in several passes, one being the albedo.

A deferred renderer should make no more than 1 pass to render the necessary components for later lighting etc.

It’s bad enough that you are using the slower fixed-function pipeline to do the albedo pass, but even worse that you are making an extra pass for it, something you would not need to do if you were just using shaders for everything.

 

 

L. Spiro

Share this post


Link to post
Share on other sites

A display list is simply an array of commands + data. A VBO is an array of data only. So each command the gpu has to go "oh this is a glVertex3f call, the next 12 bytes are x,y,z floats". Time is wasted in determining the next command. A VBO you just say here is an array of vertices, draw it. It doesn't have to analyze every single piece of data and what the command is for it. It knows they are verts and that you want to draw them.

Share this post


Link to post
Share on other sites

 

To me they just seem easier to implement and control

This may be the problem. If you have the mindset that applies to display lists and you want per-frame control, you are probably misusing VBO’s.
If you are updating VBO’s frequently, you very well may have poorer performance with them.

 

 

 

 


Based on my experiences, draw lists are significantly faster, and I've also seen that on the internet.

Display lists can never be faster than a properly used VBO because display lists always have the additional overhead of memory copies that properly used VBO’s do not.


And while we are on performance, you have 2 strcmp()’s inside a nested loop.

donotwant.jpg

 

 

Assign materials ID’s and do a simple integer compare.

 

 

 

 

 


I simply don't use a shader for that pass because binding program 0 yields the same results as creating a simple shader to render geometry with texture. If just using a simple shader is faster, it would be easy to create a shader to do that, I would do it but I haven't been able to notice a difference.

It is faster to use a simple shader.

The fixed-function pipeline is just emulated via shaders.  They often do more work than is necessary.

 

 

 

 


I render it in several passes, one being the albedo.

A deferred renderer should make no more than 1 pass to render the necessary components for later lighting etc.

It’s bad enough that you are using the slower fixed-function pipeline to do the albedo pass, but even worse that you are making an extra pass for it, something you would not need to do if you were just using shaders for everything.

 

 

L. Spiro

 

I optimized the deferred renderer a bit, making it use one pass and one shader for all three components and that did help significantly. I'm not sure if you are familiar with the obj file format, but that is what I'm using. I also don't take the material file from the obj, I take it from another file that specifies position, collision mesh, etc. I want all the models to be reusable with different mtl files so I use names instead of ids. It makes more sense to compare the names once in a display list than use some mesh-mtl specific id numbers, because they would need to match. It would end up being more load time than just doing the comparing. The second comparing just helps keep OpenGl state changing down. Eventually I'll sort the mesh, but I think the mesh I'm using is already sorted. Thanks for you help, but the framerate is fine after all the optimizations, so I think I'm good.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!