Is the profiler lying/can GL use previous binds/will... - Printable Version
+- iDevGames Forums (http://www.idevgames.com/forums)
+-- Forum: Development Zone (/forum-3.html)
+--- Forum: Graphics & Audio Programming (/forum-9.html)
+--- Thread: Is the profiler lying/can GL use previous binds/will... (/thread-3859.html)
Is the profiler lying/can GL use previous binds/will... - Jones - Sep 21, 2006 05:01 PM
Sorry for creating so many new topics recently... But I'm combining several topics in one this time.
I'm trying to add (what I think is) a cool feature to my terrain (as in heightmaps/mountains/etc...) class. This is a feature all game engines/3d basics should have if they use terrains. I say this because when I used to use Dark Basic the lack of said feature drove me crazy.
It basically works like this. The user can pass several texture units (another class, in this case) to the terrain along with a list of heights the length of the amount of textures. The terrain then uses 3D OpenGL textures to blend all those texture units into one and uses different depths in that texture as it renders the terrain. This creates a smooth blend between the grass and rock on the mountainside, etc...
This brings me to my questions.
a) Can the OpenGL profiler lie?
b) If OpenGL receives a corrupt/broken texture at glBindTexture, will it use the previously bound texture?
c) What *might* be the problem if OpenGL is only using one layer of a 3D texture?
I ask 'a' because in the profiler I see my 3D texture perfectly fine, but OpenGL is only using the last layer loaded.
This brings me to 'b' and more explaining. Here's what the coder might do:
Now, in it's current state, my code will draw the terrain using only the last loaded texture. (So in the example, "rock.tga".) The order I place them in the array has no effect, however if OpenGL was only using depth 0 then whichever was *first in the array* would be drawn.
If I've confused you by explaining poorly I'll try to clarify a bit here...
I could inverse the 0 & 1 in the above code (in the array) and the rock texture would still be drawn, despite the fact that 'ApplyTextures' would add the rock data to the final image data *last*.
Anyways, this leads me to believe that the rock is being drawn (or grass, if it is called last) because the GL texture unit for those two textures was the last valid one called. Meaning that the internal GL-tex for the terrain is being rejected for being smurfy or something, and the last bound is being taken. Make sense?
Thirdly, 'c'. If 'b' is a no (in other words OpenGL is *not* behaving that way...) then what *might* be wrong. This (meaning one layer in a 3D tex being used) has happened to me before, and I fixed it. I just can't remember how. Has this kind of thing happened to you before? How did *you* fix it? (Slap my brain until I remember... )
Thanks greatly for your posts!
Is the profiler lying/can GL use previous binds/will... - OneSadCookie - Sep 21, 2006 05:08 PM
Well, that was totally confusing
Yes, the OpenGL profiler can lie, however it sounds like it's not in this case. The last successful call to glBindTexture will always win. If you think something is failing, use the OpenGL profiler's "break on error" feature to catch OpenGL errors as you make them.
Is the profiler lying/can GL use previous binds/will... - Jones - Sep 21, 2006 05:48 PM
OneSadCookie Wrote:Well, that was totally confusing
Hehe, wait till I write the documentation for this stuff...
OneSadCookie Wrote:Yes, the OpenGL profiler can lie, however it sounds like it's not in this case. The last successful call to glBindTexture will always win. If you think something is failing, use the OpenGL profiler's "break on error" feature to catch OpenGL errors as you make them.
Thanks, I'll try that.
EDIT: Where might I find this "break on error" feature? I can't seem to find it...
EDIT 2: Found it.
Is the profiler lying/can GL use previous binds/will... - Jones - Sep 21, 2006 06:09 PM
I'm not sure if that helped. But I did notice one thing, thanks to the profiler.
In my draw loop, glBindTexture is receiving '0' as the texture. That can't be right, and I'm not sure why it's listing it as such.
Is the profiler lying/can GL use previous binds/will... - arekkusu - Sep 21, 2006 07:09 PM
for a) I think that Profiler is (more or less) doing glGetTexImage on your texture and then drawing it as a bunch of 2D quads. So it will show whatever data is there, regardless of the "completeness" state. Note that this is different than runtime OpenGL. Also, there is no reason why Profiler should work like runtime OpenGL. It is a tool, and the ability to see your texture data is useful. A "texture is incomplete!" warning might be a nice feature to add, though.
for b), what is supposed to happen is that if you bind an incomplete texture to a unit:
* in fixed function, texturing "acts as if it is disabled" for that unit.
* in programs/shaders, you should get black (0,0,0,1) for that unit.
So depending on how you are texturing you could see "the previous bound texture", if that means "the texture bound to the previous unit". But you shouldn't get the last "complete" texture you bound the current unit-- glBindTexture does not no-op if the texture is incomplete ("completeness" can't be known until you actually try to draw.)
Yes, this is confusing.
Is the profiler lying/can GL use previous binds/will... - Jones - Sep 21, 2006 10:02 PM
As far as I can tell, it *looks* complete in OpenGL profiler, if that counts for anything. (No solid grey blocks of missing pixels...)
I'm going to force drawing on the second layer.
Alrighty then... it's the binding going wrong. When I glGenTextures'd the unit in question, I passed it a real pointer to a GLuint rather than the address of a real GLuint, could that be the problem?
Is the profiler lying/can GL use previous binds/will... - arekkusu - Sep 21, 2006 10:56 PM
Show the code you're using to load each layer into a slice of your 3D texture.
Is the profiler lying/can GL use previous binds/will... - Frogblast - Sep 21, 2006 10:58 PM
Definitly check to see if any of the currently bound textures are Incomplete.
Also, passing a texture name of 0 into glBindTexture is perfectly OK, as long as that is what you intended to do. There is a default (and non-deletable) texture at name 0. This oddity is an ancient artifact from OpenGL 1.0, when texture objects didn't exist. There was no glGenTextures/glBindTexture. If you wanted to change which texture you were drawing with, you called glTexImage2D.
I'm not sure what you meant in your last post. The pointer you pass to glGenTextures must already point to valid memory. OpenGL will not allocate it for you.
Is the profiler lying/can GL use previous binds/will... - Jones - Sep 22, 2006 06:58 AM
arekkusu Wrote:Show the code you're using to load each layer into a slice of your 3D texture.
It's pretty long, so I'll snip it down to the area that I think is causing the trouble.
Is the profiler lying/can GL use previous binds/will... - akb825 - Sep 22, 2006 10:37 AM
When you bind the texture, don't cast the pointer to GLuint, you need to dereference it. (with *) Just FYI, whenever you have a pointer, and a function takes the type it's pointing to, you always dereference it. I have yet to see an instance where you need to cast a pointer into the type it's pointing to. The closest you will ever get is casting a pointer to a long to hold it in an integer for a while, where you'd then cast it back into the pointer in order to get that pointer back. (why you'd ever do that I don't know, but at least it's valid)
BTW, is target actually pointing to anything? Do you pass in the address to a GLuint that you stored somewhere else when calling that function, or did you just declare a pointer and pass that in? That, too, could cause a problem, but I know for a fact your call to glBindTexture is causing a major problem.
Is the profiler lying/can GL use previous binds/will... - Jones - Sep 22, 2006 02:06 PM
No it was an actual GLuint, not a pointer. Thanks for the tip on the de-referencing though. I'll try that.
Ok, deref'd the pointer. The program still loads and displays with one texture. When I run it through OpenGL profiler *all* the glBindTexture calls seem to receive 0 as the target, and it will always crash when run in the profiler.
I'm still not sure what's happening here. It's not my texture depth generation code, I've dropped all the array values into exel and they all line up the way they should. OpenGL just *does not* use the 3D texture.
Is the profiler lying/can GL use previous binds/will... - akb825 - Sep 22, 2006 02:43 PM
I don't know, this looks an awful lot like a pointer to me:
Regardless, glGenTextures must have a pointer, so regardless one will be wrong, even if you mistyped the function declaration. You will need to pass in a pointer, just to use glGenTextures, but you then need to dereference it for whenever you use something like glBindTexture.
Is the profiler lying/can GL use previous binds/will... - Jones - Sep 22, 2006 02:47 PM
I do. It's not a pointer when being used to draw, only that once, in the construction of the 3D texture.
*target receives a value like this: &x where x is the texture unit of the terrain (which is *not* a pointer).
A quick test revealed that OpenGL is indeed using the last bound texture, I tested this by binding the grass texture after both had been loaded, and then drawing the terrain. I got grass.
This confirms my worst fear. There is something wrong with the way I'm giving OpenGL the textures. And it's not a memory error, so I'm not sure *how* to debug it.
glGetError says that right after the calls to glGenTextures and glBindTexture that there is no error, and none after the call to glTexImage3D.
Is the profiler lying/can GL use previous binds/will... - Jones - Sep 22, 2006 03:34 PM
The two images match in every way so it's not that...
Here, take a peek for yourselves:
The values come in sets of identical twos, and they all match up. Next I'm gonna write out all the code for making the 3D texture manually. I've actually done this for the same two textures in a demo project and it worked.
I'm betting it's the pointer stuff. Perhaps instead I shall re-write the function itself to not use pointers.
EDIT: Tried it, seems it's not the pointer stuff.
Is the profiler lying/can GL use previous binds/will... - LongJumper - Sep 22, 2006 06:29 PM
I'm confused. Are you trying to to bind two textures and then draw them both onto the same geometry?
If that is the case, you will need to use multitexturing, which is not the same as: