Completely disable filtering

I have a texture I read in which I do not want filtered. The reason is that it represents very discrete data about a real-world scenario, and I need the edge between colors to be abrupt. When reading in the texture, my code includes:


glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

However, when I look at my image it is still very roughly filtered. The filter is only in one axis direction; the other is not filtered. The difference is very stark between using GL_LINEAR and GL_NEAREST, but GL_NEAREST still applies some filter which I can’t seem to turn off.

I am very new at opengl coding, so excuse my lack of useful terminology.

If this helps, this is what I’m seeing…

How sure are you this filtering isn’t in the source texture data?

I.e. read back and print your texel values.

gluBuild2DMipmaps pre-scales (and thus blurs) the image if it’s NPOT. How do you upload the texture data to the gpu?

For me, there is no filtering at all on the picture.
What do you want to see instead ?

Thank you for the replies. I’m away for part of today, but when I get back I’ll take a closer look at how I read in the texture. The source (a ppm image) has only three color values, blue, pink, and white. The blending is what I want to avoid. I believe I fill the texture with the values, cell by cell, of the ppm, as I recall.

What I’d like to see…

Note that there’s another blue rectangle drawn in the picture above, so that’s a known discrepancy. Also the zoom levels are a bit different.

I use OpenCV to read in the image (cvLoadImage) to get an IplImage structure. Then (after flipping the image for some coordinate frame problems) I make the following OpenGL calls. Note that channels, width, and height are filled from the OpenCV image structure.


glBindTexture(GL_TEXTURE_2D, textureId); 

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
  
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 0);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 

if( channels == 3)
{
  gluBuild2DMipmaps(GL_TEXTURE_2D, channels, width, height, GL_RGB, GL_UNSIGNED_BYTE, newData);
}
else if( channels == 4)
{
  gluBuild2DMipmaps(GL_TEXTURE_2D, channels, width, height, GL_RGBA, GL_UNSIGNED_BYTE, newData);
}

Indeed, Ilian Dinev was right : you should not use gluBuild2dMipmaps if you want to keep your source data intact. And there no point in building mipmaps if GL_TEXTURE_MIN_FILTER is GL_NEAREST.

It sounds like your image is not power-of-two.
If your hardware supports it, you can use it directly with glTexImage2D :
http://www.opengl.org/wiki/NPOT_Textures
Otherwise, you will have to pad the image data up to the nearest power of two in both width and height, and adapt texture coordinates accordingly.

So, if I replace my mipmaps code with a call to glTexImage2D to define the textures, it may work? And if not, I can simply pad to a power-of-2 size?

When I try this, I no longer see my texture. The computer I’m using is fairly new, but is there any way if I can see whether or not it’s capable of displaying NPOT textures?

Replaced mipmap lines with:


if( channels == 3 )
{
  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, newData);
}
else if( channels == 4 )
{
  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, newData);
}

The internalFormat should be GL_RGB(A)8 instead of just GL_RGB(A), but the problem is more likely to be caused by no NPOT support.

First you should do a check with a 256*256 texture, so that NPOT problems are ruled out.
If that does not work, then your problem lies elsewhere…

If it works, then you probably don’t have NPOT support.
To check if the GL_ARB_texture_non_power_of_two extension is available on your hardware, here is a tutorial about the concept and practice of extensions in OpenGL :
http://www.opengl.org/sdk/docs/tutorials/ClockworkCoders/extensions.php
I recommend using GLEW or Glee to make things easier.

Thanks. I took a look at GLEW, and it turns out my video card does not support GL_ARB_texture_non_power_of_two. I’m also having a problem where my textures are getting VERY big when I pad to the next power of two, so I guess I’ll cut them and lose data…oh well.

Just to clarify, power-of-two does not mean square.
Example for a source image of 129480, the POT sizes to be used would be 256512, roughly twice the data.
The worse case is “only” 4 times more texture data.

And your video card is ?

Does your card support GL_ARB_texture_rectangle or GL_EXT_texture_rectangle? This would be ideal if I understand you correctly.

If I run glxinfo and check, I do see GL_ARB_texture_rectangle but not GL_EXT_texture_rectangle. With these extensions, how do I actually go about using them with GLEW? Do I just make my glTexImage2D call with a different target value (i.e. GL_ARB_texture_rectangle instead of GL_TEXTURE_2D)?

And my video card is Quadro FX 350M, so I believe it supports OpenGL 2.1. The textures I’m generating need to be either 3 or 4 channel, and around 4500x6200. They could possibly be bigger.

EDIT: When I use GL_ARB_texture_rectangle, it seems to generate the textures but they do not show up on my screen. I read somewhere that NPOT textures are indexed from 0 to tex-size, not 0 to 1. Is this true?

All the info is here

http://www.opengl.org/registry/specs/ARB/texture_rectangle.txt

Quote:

Overview

 OpenGL texturing is limited to images with power-of-two dimensions
 and an optional 1-texel border.  The ARB_texture_rectangle extension
 adds a new texture target that supports 2D textures without requiring
 power-of-two dimensions.

 Non-power-of-two sized (NPOTS) textures are useful for storing video
 images that do not have power-of-two sized (POTS).  Re-sampling
 artifacts are avoided and less texture memory may be required by
 using non-power-of-two sized textures.  Non-power-of-two sized
 textures are also useful for shadow maps and window-space texturing.

 However, non-power-of-two sized textures have limitations that
 do not apply to power-of-two sized textures.  NPOTS textures may
 not use mipmap filtering; POTS textures support both mipmapped
 and non-mipmapped filtering.  NPOTS textures support only the
 GL_CLAMP, GL_CLAMP_TO_EDGE, and GL_CLAMP_TO_BORDER wrap modes;
 POTS textures support GL_CLAMP_TO_EDGE, GL_REPEAT, GL_CLAMP,
 GL_MIRRORED_REPEAT, and GL_CLAMP_TO_BORDER (and GL_MIRROR_CLAMP_ATI
 and GL_MIRROR_CLAMP_TO_EDGE_ATI if ATI_texture_mirror_once is
 supported) .  NPOTS textures do not support an optional 1-texel
 border; POTS textures do support an optional 1-texel border.

 NPOTS textures are accessed by dimension-dependent (aka
 non-normalized) texture coordinates.  So instead of thinking of
 the texture image lying in a [0..1]x[0..1] range, the NPOTS texture
 image lies in a [0..w]x[0..h] range.

 This extension adds a new texture target and related state (proxy,
 binding, max texture size).

Btw - these two resources may be of some help

http://www.opengl.org/sdk/docs/man/

http://www.opengl.org/registry/

I was just reading over that, and it does answer some questions. I guess I’m just confused about implementation, since it’s still not showing anything.

In my texture generation, I do a check:


if(glewIsSupported("GL_ARB_texture_rectangle"))
{
#ifdef GL_TEXTURE_RECTANGLE_ARB
  cout << "NPOT available. Using GL_ARB_texture_rectangle." << endl;
  glBindTexture(GL_TEXTURE_RECTANGLE_ARB, textureId); 
  glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP); 
  glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 
  if( channels == 3)
  {
    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB8, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, newData);
  }
  else if( channels == 4)
  {
    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB8, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, newData);
  }
#endif
}

Then, when drawing, I index the texture from 0 to width and 0 to size. However, nothing is drawn. The output shows that it successfully enters this function.

Is there something else I need to do to use GL_ARB extensions?
This fails with my test 256x256 texture as well, so I’m not sure what’s wrong.

EDIT: I don’t know if this matters, but “glewIsSupported(“GL_ARB_non_power_of_two”)” fails. Also, using GL_TEXTURE_RECTANGLE_ARB in the glBindTexture function call produces a lot of “Error: Invalid Value” when drawing.


if(glewIsSupported("GL_ARB_texture_rectangle"))
{
#ifdef GL_TEXTURE_RECTANGLE_ARB

  cout << "NPOT available. Using GL_ARB_texture_rectangle." << endl;
 
  glBindTexture(GL_TEXTURE_RECTANGLE_ARB, textureId); 
  glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP); 
  glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 
  
  if( channels == 3)
  {
    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, newData);
  }
  else if( channels == 4)
  {
    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, newData);
  }

#endif
}

Try the above for a start (assuming that your source data is RGB/RGBA and not BGR/BGRA).

How are you drawing the texture_rectangle? Are you using [0-width] rather than [0-1] when specifying each vertex?

OK, I figured it out. I was still using the old glEnable code where I actually draw. This needed to also be GL_TEXTURE_RECTANGLE_ARB, not GL_TEXTURE_2D.

I don’t know if this matters, but “glewIsSupported(“GL_ARB_non_power_of_two”)” fails…

It should be glewIsSupported(“GL_ARB_texture_non_power_of_two”)

Are you using the latest drivers?