2D texture filtering on squashed quad strip

I am new to 2D texturing and I am wrestling with a combination of distorting the shape of the texture and filtering. For now, my texture is a test pattern consisting of vertical stripes alternating black/white. (Later it will contain live image data.) The contiguous quad strip I am mapping the texture to is drawn with polygons side-by-side in the X direction, with the top vertex pairs of each polygon closer together than the bottom pairs. In the limiting case, all the top vertices are the same, and the display list then draws a pie-shaped sector with the point vertex at the top. The texture pattern is correctly squeezed so that all the stripes originate at the top, and they fan out towards the bottom. This all works.

My problem is that the simple linear filtering I have chosen – as well as a lot of experimental variations – does not produce the expected image smoothing in the lateral X direction, only in the radial direction. In the lateral direction, I can see the boundaries of polygons where I expected to see smooth variation in greyscale.

This problem is clearly associated with the “squeezing” action of the top vertices: the more I spread them apart, approaching rectangles, the smoother the lateral transitions between polygons, until the smoothing reaches the same excellent filtering I see in the axial (vertical Y) direction.

My texture dimensions are 128 lateral by 512 vertical, but I am mapping only a 121x300 region of the texture with my texture coordinates. There are, accordingly, exactly 121 little sector polygons in my quad strip.

My filter settings are as follows.

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

I have tried mip mapping, which improves the look of the top of the image when I tilt it about the X axis so that the apex is farther away, but does not make any difference when viewed en face. I have also tried anisotropic filtering at the maximum level my hardware supports (16.0), with no visible effect.

Here are some images to illustrate the problem.

The first image shows my test pattern, with alternating black/white radial spokes, and no filtering. This renders as expected.

The next image shows my test pattern, again with alternating black/white radial spokes, and linear filtering. The filtering is good at the bottom, and gets worse as you go up towards the middle of the image.

The next one is a zoom (increased scale) of a region near the middle of the image, showing the blocky lateral filtering of spokes.

The next is a zoom of a region near the bottom middle of the image, showing desired lateral filtering across the spokes. Would that I could get this effect everywhere.

The last image is the same format, but the test pattern is changed to a random number generator. Again a zoom of the middle of the image. Note the nice filtering in the axial direction as the data changes, but in the lateral direction, there are borders at the boudaries of the spokes.

thanks in advance,
McKee

Yea, that’s mipmapping for ya, it’s at best a filtering hack, at worst a problem, just learn to live and work with it.
If you have time and processing power you can work around it by writing your own texture filtering (not recommended for real time applications).

I really wish that something is being done about it in future hardware

Actually, he isn’t using mipmapping… and IMHO it is why he get’s such bad results. Try the GL_LINEAR_MIPMAP_LINEAR for the minification (don’t forget to build mipmaps before).

Thanks for the suggestion. But I did already try mipmapping, as follows:

glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, true);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);

As I mentioned in the root message, mipmapping does “improve” the image as I shrink it or rotate it about the X axis. As one end of the shape gets farther from the viewer, it is somewhat more smoothed in the axial direction. But mipmapping has no effect on the problem that vexes me – the discontinuities at the boundaries of polygons in the lateral direction.

The magnification filter should be GL_LINEAR, there is no mipmap involved when magnifying.
But I don’t think this is the problem.

no effect on the problem that vexes me – the discontinuities at the boundaries of polygons in the lateral direction.

Are you completely sure your texture coordinates are correct ?

Trilinear + aniso is actually pretty good, and much better than your screenshots on my video cards (GF3 + GF6800). I just tried, and no discontinuities at all. Maybe your video card is not so good at it ?

What happens when you use triangles instead of quads?

I agree with the above, try aniso settings and see what happens.

Apparently the Geforce 8 is really good at this kind of thing. What video card do you have?

Thanks, ZbufferR, Zengar, and sqrt[-1].

I will try those ideas and reply again to this thread within a day. I did try anisotropic filtering + mipmapping already, but I’ll recheck that. And I’ll try the GL_TRIANGLES experiment.

I am using an ATI Mobility Radeon X300 on an Itronics XR-1 Gobook laptop. It reports OpenGL 2.0 support. I also tried on a Dell Precision 650 with ATI FireGL X1 video card, reporting OpenGL 1.3 support. Same results.

I actually did use GL_LINEAR for the magnification filter, not GL_LINEAR_MIPMAP_LINEAR. You are right, that’s not the problem.

McKee

I tried GL_TRIANGLES – identical results.

I retried mipmapping, and then mipmapping + anisotropic filtering. Neither fixes the lateral discontinuities. Mipmapping causes the image to blur as I rotate about the X axis to almost horizontal; adding anisotropic filtering tends to reduce the blur and keep the original details. But neither effect addresses the basic problem of grey level discontinuities at polygon boundaries.

Here’s the code I have been using for rendering.

  if (m_texture_id < 0)
    glGenTextures(1, &m_texture_id);
  glBindTexture(GL_TEXTURE_2D, m_texture_id);
  glPixelStorei(GL_UNPACK_ALIGNMENT,1);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,  GL_LINEAR);
  #if 1
  // mip mapping helps smooth image as it is tilted about X axis
  glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, true);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
  #endif
  #if 1
  // anisotropic filtering
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 16.0);
  #endif
  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 128, 512, 0, GL_RGBA,GL_UNSIGNED_BYTE, m_Texture.data());
  glEnable(GL_TEXTURE_2D);
  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
  glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
  glCallList(m_DisplayListBase + EDisplayListTexture);
  glDisable(GL_TEXTURE_2D);

… and for generating the display list:

Notes:

  • the current image is attempting to smoothly render 121 scan lines measured in a lateral sweep from a single origin, like a triangle fan; other scan line patterns are possible, hence the desire to maintain generality by using quads
  • num_lines = 121 (lateral direction)
  • num_samples = 300 (axial direction) per line
  • each line is represented by a polygon occupying its part of the texture
  • texture dimensions are 128 x 512, but only 121 x 300 are mapped in this example
  • origins[121] are XYZ points representing the “tops” of the lines; in this case, all origins are identical at the apex
  • ends[121] are the corresponding “bottom” points of each line; they are distributed in the arc as we saw in the screen shots
  • center is an arbitrary point about which to center the polygons
      float texture_extent_x = (float)num_lines / 128;
      float texture_extent_y = (float)num_samples / 512;

#if 0
        glBegin(GL_QUAD_STRIP);
        for (int i = 0; i < num_lines; i++)
          {
          glTexCoord2f(texture_extent_x * i / num_lines,0); 
          vertex = center + origins[i];
          glVertex3f(XYZCoordinates(vertex));
          glTexCoord2f(texture_extent_x * i / num_lines, texture_extent_y);
          vertex = center + ends[i];
          glVertex3f(XYZCoordinates(vertex));
          }
        glEnd();
#elif 1
        glBegin(GL_TRIANGLES);
        for (int i = 0; i < num_lines - 1; i++)
          {
          glTexCoord2f(texture_extent_x * i / num_lines,0); 
          vertex = center + origins[i];
          glVertex3f(XYZCoordinates(vertex));
          glTexCoord2f(texture_extent_x * i / num_lines, texture_extent_y);
          vertex = center + ends[i];
          glVertex3f(XYZCoordinates(vertex));
          glTexCoord2f(texture_extent_x * (i + 1) / num_lines, texture_extent_y);
          vertex = center + ends[i + 1];
          glVertex3f(XYZCoordinates(vertex));
          }
        glEnd();
#endif

MP

ZbuffeR –

Trilinear + aniso is actually pretty good, and much better than your screenshots on my video cards (GF3 + GF6800). I just tried, and no discontinuities at all. Maybe your video card is not so good at it ?

Could you post the code you used to test this problem? Perhaps I could try it verbatim and confirm that our video card is really making the results different.

I think this thread has lost steam … nobody replying in a day and a half. I’m still casting about for a solution. My next step is to open the chapter on shaders …

McKee

Absolutely no need to re-open same topic on different section.
There is a nifty “Active topics” button that allow people willing to help others to do it efficiently. It would simply annoy some people to see the same subject twice.

Back to the topic.
My coding difference is that I used a single rectangular quad, rotated away from the camera for the perspective.

It is quite different from your setup, where quads are non-rectangular : the problem you see must be due to the fact that your quads are trapezoidal, a recent problem and its solution recently happened here :
http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Board=2&Number=229833

Hope that helps. Post here again with your progress (or problems).