I am using freeglut, GLEW and DevIL to render a textured teapot using a vertex and fragment shader. This is all working fine in OpenGL 2.0 and GLSL 1.2 on Ubuntu 14.04.
Now, I want to apply a bump map to the teapot. My lecturer evidently doesn't brew his own tea, and so doesn't know they're supposed to be smooth. Anyway, I found a nice-looking tutorial on old-school bump mapping that includes a fragment shader that begins:
uniform sampler2D DecalTex; //The texture uniform sampler2D BumpTex; //The bump-map
What they don't mention is how to pass two textures to the shader in the first place.
Previously I
//OpenGL cpp file glBindTexture(GL_TEXTURE_2D, textureHandle); //Vertex shader gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; //Fragment shader gl_FragColor = color * texture2D(DecalTex,gl_TexCoord[0].xy);
so now I
//OpenGL cpp file glBindTexture(GL_TEXTURE_2D, textureHandle); glBindTexture(GL_TEXTURE_2D, bumpHandle); //Vertex shader gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1; //Fragment shader gl_FragColor = color * texture2D(BumpTex,gl_TexCoord[0].xy); //no bump logic yet, just testing I can use texture 1 instead of texture 0
but this doesn't work. The texture disappears completely (effectively the teapot is white). I've tried GL_TEXTURE_2D_ARRAY, glActiveTexture and few other likely-seeming but fruitless options.
After sifting through the usual mixed bag of references to OpenGL and GLSL new and old, I've come to the conclusion that I probably need glGetUniformLocation
. How exactly do I use this in the OpenGL cpp file to pass the already-populated texture handles to the fragment shader?
(This is homework so please answer with minimal code fragments (if at all). Thanks!)
Failing that, does anyone have a tea cosy mesh?
However, even in OpenGL, using multiple shaders of the same type does not work they way you outline it in your question. Only one of the shaders can have a main() . The other shaders typically only contain functions. So your idea of chaining multiple shaders of the same type into a pipeline will not work in this form.
Data is passed from shader to shader by using the in and out keywords. You create an output shader variable by using the out keyword. The out variable in one shader provides the input data to the next shader declared as an in variable. The only condition is that both of these variables must have the same name.
It is very simple, really. All you need is to bind the sampler to some texture unit with glUniform1i
. So for your code sample, assuming the two uniform samplers:
uniform sampler2D DecalTex; // The texture (we'll bind to texture unit 0) uniform sampler2D BumpTex; // The bump-map (we'll bind to texture unit 1)
In your initialization code:
// Get the uniform variables location. You've probably already done that before... decalTexLocation = glGetUniformLocation(shader_program, "DecalTex"); bumpTexLocation = glGetUniformLocation(shader_program, "BumpTex"); // Then bind the uniform samplers to texture units: glUseProgram(shader_program); glUniform1i(decalTexLocation, 0); glUniform1i(bumpTexLocation, 1);
OK, shader uniforms set, now we render. To do so, you will need the usual glBindTexture
plus glActiveTexture
:
glActiveTexture(GL_TEXTURE0 + 0); // Texture unit 0 glBindTexture(GL_TEXTURE_2D, decalTexHandle); glActiveTexture(GL_TEXTURE0 + 1); // Texture unit 1 glBindTexture(GL_TEXTURE_2D, bumpHandle); // Done! Now you render normally.
And in the shader, you will use the textures samplers just like you already do:
vec4 a = texture2D(DecalTex, tc); vec4 b = texture2D(BumpTex, tc);
Note: For techniques like bump-mapping, you only need one set of texture coordinates, since the textures are the same, only containing different data. So you should probably pass texture coordinates as a vertex attribute.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With