Hi ding, the current draw function bind and unbinds the texture automatically. I wouldnāt bet my life on the fact that this can have considerable overheads when used thousands of times per frame - but I used to develop video games in the late 90s early 00s⦠I wasnāt an engine coder, but our engine coders always tried to minimize the number of gl commands as much as possible. Even duplicate commands supposedly have overheads. Maybe these days with powerbeasts nvidia and ati are pumping out this is a bit overkill, but the habits live on.
Essentially when you are drawing a texture with opengl, you are not really drawing a texture with opengl - there are 2 steps involved. First you tell the opengl state machine which texture to use - that texture becomes active. Then you draw quads, triangles etc. Until you change textures, or unbind any texture, everything you draw will be with that texture.
So I still donāt get how that will speed things up.
everytime you issue the command glBindTexture( target, name ); there is a bit of overhead, even if it is the same texture you are binding. LIke I said, I donāt know if in this day and age this is a big deal - should do some tests - but 4-5 years ago it was definitely worth avoiding. If you want to have as many particles as possible, then I would suggest this optimization route. If you only want a couple hundred it probably wonāt matter.
So if it is just one image I am working with this would have no benefit at all? I am guessing that this would be beneficial only if I was repeating the above step multiple times with a different texture each time. Is that right?
not exactly, as I mentioned above, the overhead comes from actually telling opengl which texture to use, for every single particle. Everytime you call the ofImage::draw() function, its binding the same texture again.
To me(if I am understanding things right) it seems that you would only need to have an unbind function seeing as the draw method already rebinds the texture automatically.
We would still need the bind function, because the purpose of this is to have a new draw function which does not bind the texture. a fastDraw() function which just draws a quad:
function fastDrawQuad(x, y, scaleX, scaleY) {
// the texture coordinates and vertex coordinates should be precalculated
glPushMatrix();
glTranslatef(x, y, 0);
glScalef(scaleX, scaleY, 1);
glBegin( GL_QUADS );
glTexCoord2f(tx0,ty0); glVertex3i(px0, py0,0);
glTexCoord2f(tx1,ty0); glVertex3i(px1, py0,0);
glTexCoord2f(tx1,ty1); glVertex3i(px1, py1,0);
glTexCoord2f(tx0,ty1); glVertex3i(px0, py1,0);
glEnd();
glPopMatrix();
}
That is all you need to do 5000 times for 5000 particles, all the stuff found in the draw function, before and after you can do just once before rendering the particle system.
Ultimately the code should be something like
bindTexture() {
glEnable(textureTarget);
glBindTexture( textureTarget, (GLuint)textureName[0] )
}
preCalcCoordinates() {
// calculate tx0, tx0, ty0, ty1, px0... etc.
}
for(each particle) {
ofImage.fastDrawQuad();
}
unbind() {
glDisable(textureTarget);
glBindTexture( textureTarget, 0);
}
again to repeat - unless you really really want to push your machine to the limits, then you donāt really need to go through all this trouble.
@Zach:
I understand that you guys are trying to keep it simple⦠and that can be quite hard when dealing with C++!!! at the end of the day its free software! so we canāt complain and demand anything!! I think its just gonna evolve as user needs become more and more obvious⦠but essentially I think its best be a balance of minimal steps and easy to use methods which have slightly less performance (e.g. the ofImage::draw()) but also include methods for more advanced users as alternatives (e.g. the bind, unbind, fast draw methods).
Having written this, maybe it does make sense to do implement this through class extending. THough I would prefer if the simple classes extended the advanced classes instead of the other way round. E.g. in the core there is (ignore the class names):
class ofImageAdvanced, which has the binding, unbinding, fast draw functionality etc.
and extending that is ofImage, which has the all in one draw() command.
just a thought
(I remember a similar issue came up with the loading of images with textures, and the ability to create the texture manually at some point after the image was loaded - an issue in multithreaded apps).