PDA

View Full Version : GL_TEXTURE_MIN_FILT dims entire screen



paradoxresolved
09-28-2011, 03:50 PM
I've been observing a strange behavior that I've managed to capture in a very watered-down version of my program. Basically, I have the line:


glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

in a part of the code that generates, binds, and loads a texture. When I comment out that line, the rotating square generated in the Render function is bright blue. When the line is not commented out, the square dims to a dark blue. In my other program the effect was on all the colors on the entire screen. Here is the initialization, Projection setup, and render function of my program.


bool BaseVisualEngine::Initialize()
{
// clear to black background
glEnable(GL_TEXTURE_2D);
glShadeModel(GL_SMOOTH);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glBlendFunc(GL_SRC_ALPHA,GL_ONE);

m_angle = 0.0f;

p_temp_bitmap = new MyBitmap;
if(p_temp_bitmap->load_24_bit_bitmap("C:\\CppPrograms\\New Interface\\Res\\grey.bmp"))
{
glGenTextures(1, &temp_image);
glPixelStorei(GL_UNPACK_ALIGNMENT,4);
glBindTexture(GL_TEXTURE_2D, temp_image);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
/************************************************** ****/
// The following line causes global color dimming :( //
/************************************************** ****/
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, p_temp_bitmap->width, p_temp_bitmap->height, 0, GL_BGRA, GL_UNSIGNED_BYTE, p_temp_bitmap->p_data);
}

return true;
}



void BaseVisualEngine::SetupProjection(int width, int height)
{
if (height == 0) // don't want a divide by zero
{
height = 1;
}

glViewport(0, 0, width, height); // reset the viewport to new dimensions
glMatrixMode(GL_PROJECTION); // set projection matrix current matrix
glLoadIdentity(); // reset projection matrix

// calculate aspect ratio of window
gluPerspective((GLdouble)m_view_angle,(GLfloat)wid th/(GLfloat)height,(GLdouble)m_near_z,(GLdouble)m_far _z);

glMatrixMode(GL_MODELVIEW); // set modelview matrix
glLoadIdentity(); // reset modelview matrix

m_windowWidth = (GLfloat)width;
m_windowHeight = (GLfloat)height;
}




void BaseVisualEngine::Render()
{
// clear screen and depth buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();

// Draw the game screen
glPushMatrix();
// move back 5 units and rotate about all 3 axes
glTranslatef(0.0, 0.0, -5.0f);
glRotatef(m_angle, 1.0f, 0.0f, 0.0f);
glRotatef(m_angle, 0.0f, 1.0f, 0.0f);
glRotatef(m_angle, 0.0f, 0.0f, 1.0f);

// green color
glColor3f(0.5f, 5.0f, 1.0f);

// draw the triangle such that the rotation point is in the center
glBegin(GL_QUADS);
glVertex3f(1.0f, -1.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 0.0f);
glVertex3f(-1.0f, 1.0f, 0.0f);
glVertex3f(1.0f,1.0f,0.0f);
glEnd();
glPopMatrix();

SwapBuffers(hDC);
}


The line in question is in the initialization function.

The "grey.bmp" bitmap is just a 64 by 64 solid dark grey 24 bit bitmap. I know the bitmap is being loaded correctly, because I can render it on screen without difficulty. As you'll notice, in this version of the program, I don't even render it and the weird color glitch still occurs.

Anyone know why the color dims when the line is uncommented?

paradoxresolved
09-29-2011, 04:31 PM
Anyone?

elFarto
09-30-2011, 07:55 AM
The first issue I can see is that your texture isn't mipmap complete. Try adding the line:
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);where you create the texture.

The second issue is that you have a glColor call in there. If you're not using shaders then I believe that the current colour is multiplied with the texture colour. Also a value of 5.0f to the green parameter is out of range. The valid values are between 0.0f and 1.0f inclusive.

Regards
elFarto

Dan Bartlett
09-30-2011, 08:09 AM
If you're intending to texture the quad, you also need to modify the current texture coordinate value when issuing vertices.

Something like this to map the 4 vertices of the quad to the corners of your texture:


glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex3f(1.0f, -1.0f, 0.0f);
glTexCoord2f(1, 0)
glVertex3f(-1.0f, -1.0f, 0.0f);
glTexCoord2f(1, 1)
glVertex3f(-1.0f, 1.0f, 0.0f);
glTexCoord2f(0, 1)
glVertex3f(1.0f,1.0f,0.0f);
glEnd();

paradoxresolved
09-30-2011, 09:34 AM
I added the line as you suggested, elFarto, but it says that GL_GENERATE_MIPMAP is undefined. I downloaded glext.h, but my compiler insists there is a #endif mismatch in the document. :(

What do you mean by shader? The book I learned from discusses shading, but it doesn't mention anything about texture's being involved.

So it's altering the color based on the currently bound texture's color(s)? I was beginning to suspect something along those lines, primarily because the effect depended on the color of the .bmp file. I added the line:



glBindTexture(GL_TEXTURE_2D,0);


shortly before the rendering of the square, and it solved the problem. Still, that seems like an inelegant fix. :(

How can I get OpenGL to stop modifying the color based on the currently bound texture's color(s)?

Dan:
In this case, it was intentional not to render the texture. Thanks though! :)

Dan Bartlett
09-30-2011, 10:39 AM
If you don't change a texture object's minification filter from the initial value of GL_NEAREST_MIPMAP_LINEAR, then you are expected to load mipmap levels for each level from GL_TEXTURE_BASE_LEVEL (initially 0) to the level where the mipmap will be a 1x1 pixel, or GL_TEXTURE_MAX_LEVEL (initially 1000), whichever is lowest.



glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 8, 2, 0, GL_BGRA, GL_UNSIGNED_BYTE, image_level[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 1, 0, GL_BGRA, GL_UNSIGNED_BYTE, image_level[1]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 2, 1, 0, GL_BGRA, GL_UNSIGNED_BYTE, image_level[2]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_BGRA, GL_UNSIGNED_BYTE, image_level[3]);

To limit how many levels you need to load, you can reduce GL_TEXTURE_MAX_LEVEL, or disable mipmapping with GL_TEXTURE_MIN_FILTER = GL_LINEAR or GL_NEAREST, in which case you only need to load the image at GL_TEXTURE_BASE_LEVEL.

If you have up to date headers / extension loader utils / OpenGL version, you can also automatically generate the missing levels, by using GL_GENERATE_MIPMAP, or glGenerateMipmap(GL_TEXTURE_2D), which will generate all the missing mipmap levels from GL_TEXTURE_BASE_LEVEL+1 to GL_TEXTURE_MAX_LEVEL, using the image in GL_TEXTURE_BASE_LEVEL.

As elFarto said, when you didn't add that line, the texture wasn't complete, and accessing an incomplete texture gives you rendering in white, which was then multiplied by the current color, due to the initial value of GL_TEXTURE_ENV_MODE being GL_MODULATE. If it had been modified with:


glTexEnv(GL_TEX_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

Then the color would have been ignored and replaced solely with the texture color, which would have given you a white quad instead. If you use shaders (modern OpenGL) instead of the fixed function pipeline (old OpenGL), then these texture environment settings are ignored, and how colors are combined in the shader is entirely up you.
As you had texturing enabled, and hadn't been varying the texture coordinate, then each of the vertices were issued with the current value of (0,0), so it was rendering the whole quad in the color retrieved from that position.

paradoxresolved
09-30-2011, 11:04 AM
...or disable mipmapping with GL_TEXTURE_MIN_FILTER = GL_LINEAR ...in which case you only need to load the image at GL_TEXTURE_BASE_LEVEL.


Unfortunately, that brings me back to the original state of the program. When I added:


glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

it causes the color of the quad to dim.

Your explanation does make things a little clearer however. . . the fact that a texture is bound in the background is interfering with colors drawn because of the texture environment stuff. My goal is the draw a blue quad, and do nothing at all with the texture (purely as a learning opportunity).

When I include:


glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

it ignores the color entirely, and uses the grey color of the bitmap. This is the opposite of my goal.

So is the solution I'm looking for to unbind all textures with:


glBindTexture(GL_TEXTURE_2D,0);

anytime I want to draw a polygon in a pure color without texture interference? Or maybe disable texturing during pure color drawing?

[Unfortunately, my computer has a crank of the side that I have to turn constantly. There's no way it will handle "modern OpenGL" :(]

Dan Bartlett
09-30-2011, 11:53 AM
Just use:

glDisable(GL_TEXTURE_2D);to disable texturing then, the other stuff is just explaining why it happens as it does.

Using
glBindTexture(GL_TEXTURE_2D, 0); appears to work because the default texture (texture object named 0) is initially incomplete too, so you get the same effect as using an incomplete texture, but if you did this:



glBindTexture(GL_TEXTURE_2D, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

Then texture 0 would also be a complete texture, and the texture image would appear.

If you do use multi-texturing at some stage, you'll need to be aware that glDisable(GL_TEXTURE_2D) only disables texture application for the active texture unit (you set the active texture unit with glActiveTexture(GL_TEXTURE0+i);)

paradoxresolved
09-30-2011, 01:16 PM
Cool! Thanks for the help! :)