Multitexturing problems

Started by
7 comments, last by purpledog 15 years, 12 months ago
Hello again. I did google and check old GDnet threads about this issue, but I can't seem to find what I'm doing wrong. So I want to blend topics together to make this anaglyph 3d (blue/red), but first I just wanted to blend the two pics over each other before I'll do anything fancy to it. But I'm having a problem getting my shader to see both textures. Here's my rendering code:

Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);
Gl.glDisable(Gl.GL_DEPTH_TEST);
Gl.glUseProgram(p4);

Gl.glActiveTexture(Gl.GL_TEXTURE0);
Gl.glEnable(Gl.GL_TEXTURE_2D);
Gl.glBindTexture(Gl.GL_TEXTURE_2D, leftEye);

Gl.glActiveTexture(Gl.GL_TEXTURE1);
Gl.glEnable(Gl.GL_TEXTURE_2D);
Gl.glBindTexture(Gl.GL_TEXTURE_2D, rightEye);

orthoView(openGLControl.Width, openGLControl.Height);
Gl.glLoadIdentity();

Helper.RenderTexturedQuad2D(new Vector3D(0, 2048, 0), new Vector3D(2048, 0, 0.0f), new Vector3D(0.0f, 0.0f, 1.0f));

And here's my simple shader


uniform sampler2D left;
uniform sampler2D right;
	
void main()
{
	vec4 leftColor = texture2D(left,gl_TexCoord[0].st);
	vec4 rightColor = texture2D(right,gl_TexCoord[0].st);
	
	gl_FragColor = leftColor * 0.5 + rightColor * 0.5;
}


The shader apparently only sees texture0, so both the left & right sampler2d equals that texture. Ideas? /MindWipe
"To some its a six-pack, to me it's a support group."
Advertisement
You need to bind the uniform to the active texture as well.

A texture is bound to a "sampler" (I'm not sure of the terminology here), and the sampler is bound to a uniform... And you missing the last step.

In your example, it's going to be something like:
glUniform(locationLeft,0);
glUniform(locationRight,1);

You can get the location using glGetUniformLocation.

Just to make things double clear, you are actually playing with 3 numbers here:
- the texId
- the active texture (or sampler)
- the uniform location
And you "just" need to bind them all (in the darkness if you wish)


edit: replaced glGetAttribLocation by glGetUniformLocation.

[Edited by - purpledog on April 22, 2008 9:11:21 AM]
purpledog pretty much has it covered, there is just one thing I want to add and that is that you don't need to call "Gl.glEnable(Gl.GL_TEXTURE_2D);" when using shaders; texture are implicately enabled by the act of sampling from them in a shader.
Quote:Original post by purpledog
You need to bind the uniform to the active texture as well.

A texture is bound to a "sampler" (I'm not sure of the terminology here), and the sampler is bound to a uniform... And you missing the last step.

In your example, it's going to be something like:
glUniform(locationLeft,0);
glUniform(locationRight,1);

You can get the location using glGetAttribLocation.

Just to make things double clear, you are actually playing with 3 numbers here:
- the texId
- the active texture (or sampler)
- the uniform location
And you "just" need to bind them all (in the darkness if you wish)



I see, thanks for the info. But... it's not working. Shouldn't:

Gl.glActiveTexture(Gl.GL_TEXTURE0);
Gl.glEnable(Gl.GL_TEXTURE_2D);
Gl.glBindTexture(Gl.GL_TEXTURE_2D, leftEye);
Gl.glUniform1i(Gl.glGetAttribLocation(p4, "left"), 0);

Gl.glActiveTexture(Gl.GL_TEXTURE1);
Gl.glEnable(Gl.GL_TEXTURE_2D);
Gl.glBindTexture(Gl.GL_TEXTURE_2D, rightEye);
Gl.glUniform1i(Gl.glGetAttribLocation(p4, "right"), 1);

do it?

/MindWipe
"To some its a six-pack, to me it's a support group."

The problem is that you need to specify the samplers from OpenGL. In your shading code, sampler is just a variable (a uniform variable which you can assign from OpenGL).

Before sampling can take place you have to initialize each sampler variable. You do this with glUniform1i function call. The parameters to this function call are, first, the location of the uniform variable in your GLSL code (e.g. the uniform location of "left" or "right") and secondly the texture unit identifier (e.g. 0 for GL_TEXTURE0) - it is important to realize it is NOT the OpenGL texture ID you use for the sampler variable, it is the Texture Unit to which the texture is bound (common mistake).

When you have linked the program you can retrieve the location of each uniform variable with the function call glGetUniformLocation. Note that this retrieves only active uniforms - an active uniform can be thought of as one whose value actually contributes to the output of each shader. Note that the compiler may strip uniforms if they are not deemed active then you will have a problem (an opengl error) when you try to access the uniform with the (invalid) location (also common mistake).

I suggest you retrieve all active uniforms and their location in some data structure (e.g. hashmap) after you have linked your problem successfully. Each time you need to change a uniform, you look up the location in this data structure.

Lets assume you have found the location of each active uniform. Whenever your problem is enabled, you can use function calls like glUniform1i(uniformLocationForLeft, 0) and glUniform1i(uniformLocationForRight, 1) to make your program work. The values for the uniforms stay until the program is relinked (i.e. you do not have to set them ever frame, only when you want them to change).

I recommend the book OpenGL Shading Language (so-called Orange Book) or look at Lighthouse3D tutorials on GLSL (http://www.lighthouse3d.com/opengl/glsl/).

kind regards,
Nicolai

Wups, I see now others have already helped - but look at glGetUniformLocation (see above post) instead of glGetAttribLocation :)
Quote:Original post by ndhb
The problem is that you need to specify the samplers from OpenGL. In your shading code, sampler is just a variable (a uniform variable which you can assign from OpenGL).

Before sampling can take place you have to initialize each sampler variable. You do this with glUniform1i function call. The parameters to this function call are, first, the location of the uniform variable in your GLSL code (e.g. the uniform location of "left" or "right") and secondly the texture unit identifier (e.g. 0 for GL_TEXTURE0) - it is important to realize it is NOT the OpenGL texture ID you use for the sampler variable, it is the Texture Unit to which the texture is bound (common mistake).

When you have linked the program you can retrieve the location of each uniform variable with the function call glGetUniformLocation. Note that this retrieves only active uniforms - an active uniform can be thought of as one whose value actually contributes to the output of each shader. Note that the compiler may strip uniforms if they are not deemed active then you will have a problem (an opengl error) when you try to access the uniform with the (invalid) location (also common mistake).

I suggest you retrieve all active uniforms and their location in some data structure (e.g. hashmap) after you have linked your problem successfully. Each time you need to change a uniform, you look up the location in this data structure.

Lets assume you have found the location of each active uniform. Whenever your problem is enabled, you can use function calls like glUniform1i(uniformLocationForLeft, 0) and glUniform1i(uniformLocationForRight, 1) to make your program work. The values for the uniforms stay until the program is relinked (i.e. you do not have to set them ever frame, only when you want them to change).

I recommend the book OpenGL Shading Language (so-called Orange Book) or look at Lighthouse3D tutorials on GLSL (http://www.lighthouse3d.com/opengl/glsl/).

kind regards,
Nicolai de Haan Brøgger



Thanks for an awesome explanation!!

Apparently glGetAttribLocation returns -1 for both left and right so I guess I'll have to findout why.

/MindWipe
"To some its a six-pack, to me it's a support group."
Quote:Original post by ndhb
Wups, I see now others have already helped - but look at glGetUniformLocation (see above post) instead of glGetAttribLocation :)


Oh! Right! Awesome! Now it works!

Super thanks to all of you!
"To some its a six-pack, to me it's a support group."
Quote:Original post by ndhb
Wups, I see now others have already helped - but look at glGetUniformLocation (see above post) instead of glGetAttribLocation :)


Aouch, sorry for that, my mistake!

This topic is closed to new replies.

Advertisement