Is the profiler lying/can GL use previous binds/will...

Jones
Unregistered
 
Post: #1
Sorry for creating so many new topics recently... But I'm combining several topics in one this time. Wink

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:

Code:
TEXTURE grass_and_rock[2];
TERRAIN mountains;
float where_to_put_textures[2] = {0.0, 4.0};

grass_and_rock[0].Load("grass.tga");
grass_and_rock[1].Load("rock.tga");

mountains.LoadHeightmap("map.tga");
mountains.ApplyTextures(grass_and_rock, where_to_put_textures, 2);

//  Pass the arrays with texture data, the heights to use textures, and a number
//  that represents the number of textures.

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... Rasp)

Thanks greatly for your posts! Grin
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #2
Well, that was totally confusing Rasp

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.
Quote this message in a reply
Jones
Unregistered
 
Post: #3
OneSadCookie Wrote:Well, that was totally confusing Rasp

Hehe, wait till I write the documentation for this stuff... Rasp


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. Smile

EDIT: Where might I find this "break on error" feature? I can't seem to find it...
EDIT 2: Found it. Smile
Quote this message in a reply
Jones
Unregistered
 
Post: #4
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.
Quote this message in a reply
Sage
Posts: 1,232
Joined: 2002.10
Post: #5
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.
Quote this message in a reply
Jones
Unregistered
 
Post: #6
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.

...

No effect.

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?

Thanks!
Quote this message in a reply
Sage
Posts: 1,232
Joined: 2002.10
Post: #7
Show the code you're using to load each layer into a slice of your 3D texture.
Quote this message in a reply
Member
Posts: 87
Joined: 2006.08
Post: #8
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.
Quote this message in a reply
Jones
Unregistered
 
Post: #9
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.

Code:
//    Returns a 3D OpenGL texture unit based on TEXTURE arrays.
    TEX_RESULT_COMP3D Construct3DTexture(    GLuint *target, GLsizei depth,
                                            TEXTURE *texs    ) {
        
/* SNIP */

//    Tell GL to make some room for this texture.
        glGenTextures(1, target);
        glBindTexture(GL_TEXTURE_3D, (GLuint)target);
        
        //    Mipmap it?
        if (t_filt > 1) {
        
            //    These are fixed.
            glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP);    //    Clamp is neccessary
            glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP);    //    for 3d texturing,
            glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP);    //    over repeat.
            
            //    These are variable.
            //    The second is not, because it has a limit of detail.
            glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, RAYNE_ITL_TEX_FILTER_GL_TRANS[t_filt]);
            glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, RAYNE_ITL_TEX_FILTER_GL_TRANS[1]);
        
            //    Use GLU to send the data to GL.
            gluBuild3DMipmaps(    GL_TEXTURE_3D, t1_components, t1_width, t1_height,
                                numberToUse, t1_format, t1_type,
                                tex_dat    );
        
        }
        
        //    Don't mipmap it?
        else {
        
            //    These are fixed.
            glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP);    //    See above for note on
            glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP);    //    usage of GL_CLAMP.
            glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP);
            
            //    These are variable.
            glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, RAYNE_ITL_TEX_FILTER_GL_TRANS[t_filt]);
            glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, RAYNE_ITL_TEX_FILTER_GL_TRANS[t_filt]);
            
            //    Send the data to GL directly.
            glTexImage3D(    GL_TEXTURE_3D, 0, t1_components, t1_width, t1_height, depth, 0,
                            t1_format, t1_type, tex_dat    );
            
            
        }
        
        
        /* SNIP! */
    }
Quote this message in a reply
Moderator
Posts: 1,140
Joined: 2005.07
Post: #10
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.
Quote this message in a reply
Jones
Unregistered
 
Post: #11
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.
Quote this message in a reply
Moderator
Posts: 1,140
Joined: 2005.07
Post: #12
I don't know, this looks an awful lot like a pointer to me:
GLuint *target
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.
Quote this message in a reply
Jones
Unregistered
 
Post: #13
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. Rasp

EDIT:

glGetError says that right after the calls to glGenTextures and glBindTexture that there is no error, and none after the call to glTexImage3D.

Curious.
Quote this message in a reply
Jones
Unregistered
 
Post: #14
The two images match in every way so it's not that...

Here, take a peek for yourselves:

Code:
256 // widths
256
256 // heights
256
3 // components
3
6407 // format
6407
5121 // type
5121

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.
Quote this message in a reply
Moderator
Posts: 133
Joined: 2008.05
Post: #15
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:
glBindTexture(1)
glBindTexture(2)
draw()
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  OpenGL profiler 3.2 - 0.0 Frame Rate? kelvin 0 2,568 Mar 3, 2006 01:21 AM
Last Post: kelvin
  OpenGL Profiler Nick 15 6,703 Mar 29, 2005 06:56 PM
Last Post: Nick
  OpenGL Profiler, or, "where did all my files go?" sealfin 2 2,789 Sep 3, 2004 12:19 AM
Last Post: sealfin
  OpenGL profiler & display lists MattDiamond 9 4,331 Sep 1, 2003 08:07 PM
Last Post: MattDiamond
  OpenGL profiler LongJumper 11 4,430 Apr 4, 2003 08:18 PM
Last Post: Fenris