I came across a nasty problem in my program when i tried to use the same texture unit (number 0) for different texture types (i.e. a normal 2D texture and a cube map) in my shader. It appeared so that the GL issues a 502H (Invalid Operation) after the first glDrawArrays call. In my application code i load up the textures to different texture targets:
void setup_textures()
{
unsigned int width, height;
int components;
unsigned int format;
float param[8];
vector<unsigned char> pngData;
GLenum texture_target;
glGenTextures(2, textures);
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, param);
for(int i = 0; i < 2; i++) {
texture_target = (i == 0) ? (GL_TEXTURE_CUBE_MAP) : (GL_TEXTURE_2D); // The first texture is the cube map
glActiveTexture(GL_TEXTURE0);
glBindTexture(texture_target, textures[i]);
glTexParameterf(texture_target, GL_TEXTURE_MAX_ANISOTROPY_EXT, param[0]);
glTexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_REPEAT);
if(texture_target == GL_TEXTURE_CUBE_MAP) glTexParameteri(texture_target, GL_TEXTURE_WRAP_R, GL_REPEAT);
loadPNG(pngData, width, height, PNGFile[i], LCT_RGBA, 8) // PNGFile[0] is my 2D texture file and PNGFile[1] is the cube texture
if(texture_target == GL_TEXTURE_CUBE_MAP) {
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &pngData[0]);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &pngData[0]);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &pngData[0]);
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &pngData[0]);
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &pngData[0]);
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &pngData[0]);
} else if(texture_target == GL_TEXTURE_2D)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &pngData[0]);
glGenerateMipmap(texture_target);
}
return;
}
In my render function i bind the texture to its corresponding target and tell the shader which texture type to use (by means of a bool uniform):
void render(HDC hdc)
{
GLenum texture_target;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
for(int i = 0; i < 2; i++) {
texture_target = (i == 0) ? (GL_TEXTURE_CUBE_MAP) : (GL_TEXTURE_2D);
glBindVertexArray(objVertexArray[i]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(texture_target, textures[i]);
glUniform1i(uniIsCubeMap, texture_target == GL_TEXTURE_CUBE_MAP); // Tell the shader the texture type
glDrawArrays(GL_TRIANGLES, 0, nVertices[i]);
}
SwapBuffers(hdc);
return;
}
In the fragment shader the texture type is determined based on is_cube_map uniform:
#version 330 core
uniform sampler2D texture_map;
uniform samplerCube texture_map_cube;
uniform bool is_cube_map;
smooth in vec3 texcoords;
out vec4 fragcolor;
void main(void)
{
vec4 texel;
if(is_cube_map) {
texel = textureCube(texture_map_cube, texcoords.stp);
} else {
texel = texture(texture_map, texcoords.st);
}
fragcolor = texel;
}
I also set the both texture sampler uniforms to 0 (texture unit number 0) in my application code:
glUniform1iARB(uniTextureMap, 0);
glUniform1iARB(uniTextureMapCube, 0);
What would be the problem? Is is really not a valid thing to do?
Yes, it is very much not a valid thing to do.
You should completely forget that OpenGL even allows you to bind different texture targets to the same texture unit. There is absolutely nothing useful you can do with this ability. If you need to bind a texture to modify it, unbind it afterwards. If you need to bind a texture to use it for rendering, then nothing else should be bound to that texture unit.
In any case, your drawing function should have gotten GL_INVALID_OPERATION
, because it is illegal for two samplers in the same program/pipeline to refer to the same texture unit, but use different sampler types.
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