PDA

View Full Version : Please Help: Bump Mapping/ Multi-Texture Problem



leolol
10-31-2011, 04:02 AM
I've been spending the better half of the last 2 weeks trying to get bump-mapping working, however I seem to be having a problem when combining a normal map with a texture.

Bump mapping seems to work fine, when I apply only the normal map, however when I try to also apply the colour map (regular texture) the results are somewhat strange. I am using GLSL shaders borrowed from existing tutorials, which seem to work fine and other users have reported that all is working well.

I suspect there is something wrong with my JOGL code, however I cant see what exactly.

Screenshots: (First is with just normal Map, other 2 are with normal map and texture)

http://imgur.com/a/ceDpg

Link to my shader and GL code snippets:

http://pastebin.com/9mPmSNX3


Any help would be greatly appreciated, I am only posting here as a last resort after trawling through pages of threads/tutorials over the last few weeks with no joy.

Hope someone out there can help.

Leo

thokra
10-31-2011, 05:01 AM
What exactly do you mean with "the results are somewhat strange"? What result are you expecting?

I find it hard to determine what's wrong with three entirely different camera angles and no clue as to what the outcome is supposed to look like. From what I can see, it seems there are blocky artefacts in the second shots where I suppose the lighting is to be smooth. Right?

How do you calculate your tangents?

BionicBytes
10-31-2011, 06:17 AM
Why has your normal mapped texture (first image) got white (specular?) highlights on it? If the camera (or the model) rotates, does the colour alter w.r.t the camera position/view.
It should do if your lighting calculations are in camera space.

Are you rotating the models? If so, are you recaululating the tangents or at least the tangent to world matrix.

leolol
10-31-2011, 06:41 AM
Hi There,

Thanks for replying,

Well initially the textures weren't rendering properly (I could get the bumpmap with no texture (that blue 1st screenshot) or the regular texture without bumpmap but not both (the blotchy artefact one was the attempt of rendering both)) I have since found that this was a problem with setting the textures to the right numbers, which brings me to my current problem:

gl.glActiveTexture(GL2.GL_TEXTURE1);
texture.enable(gl);
texture.bind(gl);
setUniform1i(gl,shaderID,"colorMap",texture.getTextureObject(gl));
texture.disable(gl);

gl.glActiveTexture(GL2.GL_TEXTURE2);
normalMap.enable(gl);
normalMap.bind(gl);
setUniform1i(gl,shaderID,"normalMap",normalMap.getTextureObject(gl));
normalMap.disable(gl);


This works great, and I now get a bump-mapped colour textured model. However the new problem arises when I try to draw numerous objects, as they all override GL_TEXTURE1 and GL_TEXTURE2.

Screenshot: (as you can see, the skybox is taking the same texture when it shouldn't)

http://imgur.com/NPGGf

How would I go about making this implementation work for multiple objects? Something to do with GenTextures perhaps?

Sorry if I sound vague, my brain is somewhat confused at this point.

Leo

thokra
10-31-2011, 06:53 AM
Well, you need to bind the skybox textures to the appropriate texture unit before rendering. In the simplest case it's 6 binding calls to the same unit (e.g. GL_TEXTURE0).

Be aware that every unit can have exactly one texture object bound to it (Stating only one texture would be inaccruate due to cube maps, texture arrays etc.).

Determine which unit(s) the sampler(s) in your skybox shader is(are) associated with, bind the appropriate textures and render.

BionicBytes
10-31-2011, 07:06 AM
As previosuly stated, it's a classic case when using glActiveTexture (GL_TEXTURE0 + somenumber);

I always render each of my objects with the binding of the textures backwards, for example:

glActiveTexture (GL_TEXTURE3);
glBindTexture (reflectTex.target, reflectTex.id);
glActiveTexture (GL_TEXTURE2);
glBindTexture (specularTex.target, SpecularTex.id);
glActiveTexture (GL_TEXTURE1);
glBindTexture (bumpTex.target, bumpTex.id);
glActiveTexture (GL_TEXTURE0);
glBindTexture (albedoTex.target, albedoTex.id);

bindshader, drawobject, etc

Notice how the ActiveTexture always finishes at GL_TEXTURE0.
That's important because many of the other scene rendering objects rely upon the default state and assume the texture being bound is associated to ActiveTexture #0. So the golden rule is that you should preserve the state if you change it, or resetup the state for each draw call.

Also, notice that when shaders are used, there is no need to enable each texture target for each ActiveTexture. Only when using the fixed function do you have to do that.

leolol
10-31-2011, 09:52 AM
I think I'm having problems with this whole GL_TEXTURE thing.

As advised, I switched the active textures from 1, 2 to 1, 0, so it is counting downwards, however this totally messes everything up and I only see a dimly lit colour texture without any bump mapping.

I am totally confused. Does each unique texture have to have a unique GL_TEXTURE number?

> Well, you need to bind the skybox textures to the appropriate texture unit before rendering. In the simplest case it's
6 binding calls to the same unit (e.g. GL_TEXTURE0).

Is that only valid if all 6 textures are the same?

So sorry for bothering you all, every time I think I'm starting to understand this, something else breaks.

Thanks so much for your help,

Leo

leolol
10-31-2011, 10:02 AM
So to clarify the following code works:

gl.glActiveTexture(GL2.GL_TEXTURE2);
normalMap.enable(gl);
normalMap.bind(gl);
setUniform1i(gl,shaderID,"normalMap",normalMap.getTextureObject(gl));
normalMap.disable(gl);

gl.glActiveTexture(GL2.GL_TEXTURE1);
texture.enable(gl);
texture.bind(gl);
setUniform1i(gl,shaderID,"colorMap",texture.getTextureObject(gl));
texture.disable(gl);


However switching to GL_TEXTURE1 then GL_TEXTURE0, does not work.

BionicBytes
10-31-2011, 10:16 AM
Several thing wrong here.
Firstly, you don't need to enable any texture if you are using shaders.
So this code:


normalMap.enable(gl);
is redundant if it does what I think it does which is glEnable (GL_TEXTURE2D);
as is
normalMap.disable(gl);


Secondly, changing the order of the glActiveTexture commands should never mess up your code becuase the same textures are being bound to the same texture units, so nothing has changed.
In your case however, you are not doing things correctly.


Your uniform parameters which you sent to the shaders should be the 'n' value in glActiveTexture (GL_TEXTURE0 +n ) not the texture ID.
Therefore, the following code


gl.glActiveTexture(GL2.GL_TEXTURE1);
texture.enable(gl);
texture.bind(gl);
setUniform1i(gl,shaderID,"colorMap",texture.getTextureObject(gl));
texture.disable(gl);

gl.glActiveTexture(GL2.GL_TEXTURE2);
normalMap.enable(gl);
normalMap.bind(gl);
setUniform1i(gl,shaderID,"normalMap",normalMap.getTextureObject(gl));
normalMap.disable(gl);

...becomes....


gl.glActiveTexture(GL2.GL_TEXTURE2);
normalMap.bind(gl);
setUniform1i(gl,shaderID,"normalMap",2);

gl.glActiveTexture(GL2.GL_TEXTURE1);
texture.bind(gl);
setUniform1i(gl,shaderID,"colorMap",1);


I'm assuming your wrapper for glUniform1i actually sets the correct values....

leolol
10-31-2011, 10:22 AM
Wow, thank you so much for that. Changing that one thing has fixed everything.

Having spent so much time staring at the same bit of code I guess I fell victim to such a silly mistake!

Again, many thanks for your help, it is very much appreciated.

Leo

thokra
10-31-2011, 10:38 AM
I think I'm having problems with this whole GL_TEXTURE thing.


Ok, let's start over. Graphics hardware has something called "texture units" or "texture mapping units", which to my knowledge act(ed) as dedicated processing elements handling, for example, texture filtering, decompression etc. The amount of texture units per GPU is finite. OpenGL 4 capable hardware is required to provide at least 80 units.

Check out http://www.opengl.org/sdk/docs/man4/xhtml/glActiveTexture.xml

Then there's the concept of "texture objects" in OpenGL. Basically it's a regular buffer holding some defined amount of data. Usually when it comes to textures this data comprises of values interpreted as color. What you get when callin glGenTextures() is one or a number of handles which uniquely identify a texture object.

At least with OpenGL you can have one texture object bound to one texture unit. The symbolic constants GL_TEXTUREi refer to a specific "texture unit". OpenGL maintains one active texture unit as the current state. So, if you want to change the texture a texture unit is working on, you will have to tell OpenGL which unit and which texture.

Therefore you do the following:




// here you select a texture unit - in this case it's unit 0
glActiveTexture(GL_TEXTURE0);

// now you bind a specific texture object to unit 0
glBindTexture(GL_TEXTURE_2D, tex_object);

// oops, unit didn't change so tex_object2 is now bound
glBindTexture(GL_TEXTURE_2D, tex_object2);

// for use in shader you associate a texture unit and uniform sampler -
// location named "NormalMap" will now use unit 0 which samples the texture
// defined in tex_object2
glUniform1i("NormalMap", 0);





I am totally confused. Does each unique texture have to have a unique GL_TEXTURE number?


No, kind of the other way around. Only one texture can be bound to a specific texture unit at a time. You can bind the same texture to multiple units, although probably not useful in most cases.



Is that only valid if all 6 textures are the same?


Now you can probably answer this yourself but I'll do it anyway. No, the textures are arbitrary, but in the case of a skybox, which can be implemented using 6 differently oriented planes with 6 different textures, you can use a single texture unit.



glActiveTexture(GL_TEXTURE0);

// bind first texture
// render first plane

// bind second texture
// render second plane
// an so forth ...



HTH.