I don't know what I'm doing wrong but I'm having a big a problem with GL_TEXTURE_MIN_FILTER when loading textures for my scene.
I'm doing a skybox, but that's irrelevant because the problem exists even if I just load the textures and don't do anything with them. Meaning, the code to draw the skybox and attach the textures to the box quads is disabled.
My current code to load textures is the following:
typedef struct sGameTextures {
unsigned int skybox[6];
} GameTextures;
GameTextures gameTextures;
unsigned int loadImageTexture(const char *filepath, int glFormat, int pWrap, int pFilter) {
int texDimension, texWidth, texHeight, texPixelSize;
unsigned int texID, texImage;
unsigned char *texPixels;
unsigned int ilFormat;
switch(glFormat) {
case GL_LUMINANCE:
ilFormat = IL_LUMINANCE;
break;
case GL_RGB:
ilFormat = IL_RGB;
break;
case GL_RGBA:
ilFormat = IL_RGBA;
break;
default:
return -1;
}
ilGenImages(1, &texImage);
ilBindImage(texImage);
if(!ilLoadImage((ILstring)filepath)) {
ilDeleteImages(1, &texImage);
return -1;
}
texWidth = ilGetInteger(IL_IMAGE_HEIGHT);
texHeight = ilGetInteger(IL_IMAGE_WIDTH);
texPixelSize = ilGetInteger(IL_IMAGE_BPP);
// stop if image width or height is not power of 2
if(!texWidth & (texWidth - 1) || !texHeight & (texHeight -1)) {
ilDeleteImages(1, &texImage);
return -1;
}
texDimension = texWidth * texHeight * texPixelSize;
texPixels = new unsigned char[texDimension];
ilCopyPixels(0, 0, 0, texWidth, texHeight, 1, ilFormat, IL_UNSIGNED_BYTE, texPixels);
ilDeleteImages(1, &texImage);
if((texPixelSize * texWidth) % 4 == 0) {
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
} else {
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
}
glGenTextures(1, &texID);
glBindTexture(GL_TEXTURE_2D, texID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, pWrap);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, pWrap);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, pFilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, pFilter);
glTexImage2D(GL_TEXTURE_2D, 0, glFormat, texWidth, texHeight, 0, glFormat, GL_UNSIGNED_BYTE, texPixels);
return texID;
}
void loadGameTextures(void) {
char *boxFace[] = { "front", "back", "left", "right", "top", "bottom" };
char boxTexture[FILENAME_MAX];
for(int i = 0; i < 6; i++) {
sprintf_s(boxTexture, "Resources/Textures/Skybox/Set%d/%s.jpg", 1, boxFace[i]);
gameTextures.skybox[i] = loadImageTexture(boxTexture, GL_RGB, GL_CLAMP, GL_LINEAR);
}
}
void main(int argc, char **argv) {
(...)
ilInit();
ilEnable(IL_ORIGIN_SET);
ilOriginFunc(IL_ORIGIN_LOWER_LEFT);
loadGameTextures();
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_TEXTURE_2D);
glutMainLoop();
}
This is how my scene looks like when I don't load any textures (ie: loadGameTextures()
is never called): https://i.stack.imgur.com/1cCZp.png. Look how the floor is light green and now compare to the following which is much darker: https://i.stack.imgur.com/NYeqD.png.
At first I pinpointed the problem to glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, pFilter);
more exactly when pFilter = GL_LINEAR
. When I commented this line, or replaced pFilter
with GL_LINEAR_MIPMAP_LINEAR
the floor was light green again. However, this was without using the textures, I was just loading them. When I tried to use them, it didn't work, it looked like this: https://i.stack.imgur.com/JRAFJ.png.
The sky now looks white because that's the clear color I use when drawing the skybox quads. We only see white because the textures are not properly working. They are loaded but that option I selected for GL_TEXTURE_MIN_FILTER
, helps on the darkening issue but doesn't display any textures.
Another thing I noticed is that I'm enabling GL_TEXTURE_2D
globally and if I only enable it when I need it (drawing the skybox) and disable it when finished, it will work. The scene won't be dark anymore. But the skybox is just an example, I'll be using textures all over the place and it's a pain to keep enabling/disabling GL_TEXTURE_2D
every time I need to draw some texture. Surely there must be another way around this problem?