
Using multiple textures
Posted Wednesday, 4 May, 2011 - 18:21 by fkj inThe texture examples I've seen only shows how to use a single texture (to keep it simple obviously), but I'm trying to use two textures, and am having a problem. I use the following code to load a texture (I believe there is nothing special about this code):
Bitmap bitmap = new Bitmap( path ); BitmapData data = bitmap.LockBits( new System.Drawing.Rectangle( 0, 0, bitmap.Width, bitmap.Height ), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppRgb ); int textureId = GL.GenTexture(); GL.TexImage2D( TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, data.Width, data.Height, 0, OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0 ); bitmap.UnlockBits( data );
Loading two textures I get textureId's 1 and 2. This is done once in the start of the program (...OnLoad...).
I then use only the first texture on some quads (GL.BindTexture( 1 ) etc.).
It all works fine but for one thing, it always uses the last texture loaded! If I only load the first texture it looks fine, but it's like it always uses the last texture nomatter what id I try to use. Note that BindTexture() is never called using 2 anywhere in the code, and GetError() returns no error on neither TexImage2D or BindTexture. Both textures works fine if only one texture is loaded.
What am I missing? Do I have to do something extra to make two textures available?
(using: OpenTK 1.1 (by Subversion), my driver supports only OpenGL 2.1)


Comments
Re: Using multiple textures
Try adding a call to GL.BindTexture between GenTexture and TexImage2D. The code above tries to upload texture data to texture #id 0, which leads to undefined behavior.
Re: Using multiple textures
It did not solve the problem:
It is always the last of the two textures that is used, even though I'm only using GL.BindTexture( TextureTarget.Texture2D, 1 ) when applying textures.
Re: Using multiple textures
Try displaying both textures on screen, do they show the same thing? Are the contents of the pngs different?
There are just too many things that could be at fault here, it's impossible to say what the cause could be without seeing more of your code (at least rendering function).
Re: Using multiple textures
Do you have two objects that should have the different textures or do you want to multitexture your object?
In the first case you can (inside the renderloop):
BindTexture 1
render Geometry
BindTexture 2
render Geometry
in the 2nd case you need to:
Activate TextureUnit1
BindTexture 1
Activate TextureUnit2
BindTexture 2
render Object
(take a look at multitexturing-tutorials)
Re: Using multiple textures
@Radar: I have two objects (quads) that should use different textures.
@Fiddler: (the remaining)
The textures are very different, and using both textures, then in all cases image data from the last texture will be used (i.e. apparently binding will be to the last texture no matter what texture id is used).
The code is distributed over a number of classes (effeciency is not an issue, I'm just trying to learn some OpenGL). The concepts are as follows:
The game window has a world, a world has a player and a collection of renderable objects. The player has the camera. A Cube is a renderable object that has a collection of six squares. Each square has a texture.
When the game window is asked to render, it asks the players camera to setup, and then asks each renderable object (the world has) to render itself. The cube will ask the squares to render themselves, and they will do this by asking the texture to bind and attach itself to the square (i.e. quad).
The code has been edited down, but should contain all relevant code:
A Console.WriteLine( ... ) in Texture.Bind() shows that 'textureId' is always 1 (as it should be), but image data is from the texture having id 2 (the last one loaded using the code previously shown).
I would expect it to be some small thing, that does some kind of reset, that I do not notice due to my limited experience with OpenGL.
Re: Using multiple textures
Ok, another sanity check: what happens if you switch the loading order for the two textures (i.e. load the second one first and vice versa)?
Your rendering code appears to be in order. My first guess was that the second texture was overwriting the data of the first texture (i.e. both TexImage2d calls would upload to the same texture id). My second guess is that the texture ids passed to the Texture constructors are incorrect (i.e. do you actually assign the results of GL.GenTexture() to the Texture constructors?)
Re: Using multiple textures
I've tried all this before and none of it exposed the error!
But is my rendering code really in order?
I tried to comment all instance of GL.BindTexture( ... ), and the program performed consistently (in various tests) with not binding anything at all! (i.e. exactly the same behaviour with or without any bindings)
I then checked if I was using a debug version of OpenTK (compiled in debug mode, and not release mode), and I found I mistakenly was using a version compiled in release mode (using a version compiled in debug mode adds extra error checking. @Fiddler: I know you know this, but others reading this might benefit from knowing it). Then something came up!
GL.End() threw an exception (something like "illegal operation") in:
I then tried to comment various things, and the result was that GL.BindTexture() is not allowed between GL.Begin(...) and GL.End() (is this correct?).
I then changed it to:
Now GL.End() does not throw any exception, and secondly my framerate hits bottom - something (costly) is really happening - it's really binding a texture (or trying to).
The behaviour is still not correct, but the error has changed to something that (hopefully) makes more sence.
If I use the last texture loaded it still works fine (apart from the framerate going down). If I use the first texture loaded it does no longer use image data from the last texture loaded (but the framerate still goes down), but uses the current color (white) to fill the quads. In the render code, the texture id is correct (1), and GL.GetError() after GL.BindTexture(...) claims there is no error, but the texture is obviously not bound! When I switch between using the first and last texture loaded, I only swap the loading order, everything else is the same (except the texture id, obviously).
Re: Using multiple textures
Ok, this is a good step forward.
A white texture typically indicates some invalid or undefined texture state.
Are your textures dimensions powers-of-two? Some video cards (e.g. older Intel chips) don't support non-POT textures, which could explain the discrepancy. (What video card are you using?)
Have you enabled mipmapping? (GL.TexParameter(..., TextureParameter.LinearMipmapLinear or LinearMipmapNearest)). In this case, you must provide a complete mipmap chain for the texture to be considered valid. Try disabling mipmapping explicitly (set TextureParameter.Linear for both textures).
Regarding performance, calling GL.Begin/GL.End like this can really hurt. Try reorganizing your rendering code like this:
Re: Using multiple textures
The textures are 256x256 and 32x32, and mipmaps are not enabled, but asking about the texture parameters got me onto the right track!
I had the misconception that setting the texture parameters affected all loaded textures. Because of this I loaded all (both) textures before I set the texture parameters (setting Min/Mag to Near, by the way). When I placed the same code after loading each texture, there were no more errors! Previously only the last texture had the texture parameters set.
To sum up, there were three errors. Two in loading the textures:
1. Not binding the texture after GenTexture() (believing this to be implicit)
2. Not setting texture parameters after loading each texture (believing these to be "global" to all loaded textures)
and one in rendering:
3. Binding textures between Begin() and End()
Performance is another issue, this code is just for learning the basics.
Thank you for taking time to help!
Re: Using multiple textures
You are welcome, this was a tough one to crack! (Multiple interrelated issues, that's exactly like the issue I'm hunting down right now at work.)