8 Replies Latest reply on Aug 26, 2011 3:31 AM by wobattery

    GL_CLAMP bug

    gstcyclops
      strange bug affecting GL_CLAMP: the last line is repeated, but somehow faded out

      Hi,

      I face a strange bug on ATI cards on ubuntu.

      I setup the clamping options like this:

      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);

      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

      and I expect to see the edge lines repeated whenever I used a texture coordinate outside [0,1]. However, this is what I get when rendering a full screen quad using a texture containing 4 colored squares (what u see in the middle) with texture coordinates from -0.1 to 1.1:

      http://db.tt/pihAURK


      So it seems like the edges are indeed repeated but somehow faded out.

      Next I attached a screenshot of the same aplication on a NVIDIA card (apart of the graphic card all the other conditions are the same):


      http://db.tt/5wkKK0J


      Here it is impossible to notice the edge of the texture, as expected.



      Setup: ATI HD 5870 on Ubuntu 10.04 x64 with ati-driver-installer-11-5-x86.x86_64.run. Same bug also on ATI HD 6870 and also with ati-driver-installer-11-2-x86.x86_64.run



      Any ideas?



      Thanks!

        • GL_CLAMP bug
          kenwang

          I will take a look.

            • GL_CLAMP bug
              kenwang

              we can not duplicate the issue on Ubantu 10.10 with HD5850, the code piece:

               

               

              void init(void)

              {

                     glClearColor(0.0,0.0,0.0,0.0);

                     glShadeModel(GL_FLAT);

                     glEnable(GL_DEPTH_TEST);

                     glPixelStorei(GL_UNPACK_ALIGNMENT,1);

                     glGenTextures(1, &texName);

                     glBindTexture(GL_TEXTURE_2D,texName);

                     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_NEAREST);

                     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);

                           glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,checkImageWidth,checkImageHeight,0,GL_RGBA,GL_UNSIGNED_BYTE,checkImage);

               

               

              }

               

              void display(void)

              {

                  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

                      glEnable(GL_TEXTURE_2D);

                      glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);

                      glBindTexture(GL_TEXTURE_2D,texName);

                      glBegin(GL_QUADS);

                      glTexCoord2f(-0.1,-0.1);glVertex3f(-2.0,-1.0,0.0);

                      glTexCoord2f(-0.1,1.1);glVertex3f(-2.0,1.0,0.0);

                      glTexCoord2f(1.1,1.1);glVertex3f(0.0,1.0,0.0);

                      glTexCoord2f(1.1,-0.1);glVertex3f(0.0,-1.0,0.0);

               

                      glEnd();

                      glFlush();

                      glDisable(GL_TEXTURE_2D);

              glutPostRedisplay();

              }

               

              can you paster your source code if it's different form yours?

               

               

                • GL_CLAMP bug
                  gstcyclops

                  Thanks for the reply!

                  I did compare my code with yours and the only difference was in the texture filters: I used GL_LINEAR and you used GL_NEAREST. If I use "nearest" too, the texture is rendered corectly.

                  Could you please try with GL_LINEAR?

                    • GL_CLAMP bug
                      kenwang

                      Can you paste your code? It's difficault for us to guess what you have done.

                      for example, I don't kown your texture size, window size, etc.

                        • GL_CLAMP bug
                          gstcyclops

                           

                          // to build: g++ -Wall test.cpp -lGL -lGLU

                          #include <stdlib.h>

                          #include <stdio.h>

                          #include <GL/glx.h>

                          #include <GL/glu.h>

                           

                          //-----------------------------------------------------------------------------

                          // DEFINES

                          //-----------------------------------------------------------------------------

                          #define SCREEN_WIDTH  640

                          #define SCREEN_HEIGHT 480

                          #define TEXTURE_WIDTH  256

                          #define TEXTURE_HEIGHT 256

                           

                          //-----------------------------------------------------------------------------

                          // GLOBALS

                          //-----------------------------------------------------------------------------

                          Display*   g_pDisplay = NULL;

                          Window     g_window;

                          GLXContext g_windowContext;

                          GLuint     g_testTextureID = 0;

                           

                          struct Vertex

                          {

                              float tu, tv;

                              float x, y, z;

                          };

                           

                          Vertex g_cubeVertices[] =

                          {

                              { -0.1f,-0.1f, -1.0f,-1.0f, 1.0f },

                              { 1.1f,-0.1f,  1.0f,-1.0f, 1.0f },

                              { 1.1f,1.1f,  1.0f, 1.0f, 1.0f },

                              { -0.1f,1.1f, -1.0f, 1.0f, 1.0f },

                           

                              { 1.0f,0.0f, -1.0f,-1.0f,-1.0f },

                              { 1.0f,1.0f, -1.0f, 1.0f,-1.0f },

                              { 0.0f,1.0f,  1.0f, 1.0f,-1.0f },

                              { 0.0f,0.0f,  1.0f,-1.0f,-1.0f },

                           

                              { 0.0f,1.0f, -1.0f, 1.0f,-1.0f },

                              { 0.0f,0.0f, -1.0f, 1.0f, 1.0f },

                              { 1.0f,0.0f,  1.0f, 1.0f, 1.0f },

                              { 1.0f,1.0f,  1.0f, 1.0f,-1.0f },

                           

                              { 1.0f,1.0f, -1.0f,-1.0f,-1.0f },

                              { 0.0f,1.0f,  1.0f,-1.0f,-1.0f },

                              { 0.0f,0.0f,  1.0f,-1.0f, 1.0f },

                              { 1.0f,0.0f, -1.0f,-1.0f, 1.0f },

                           

                              { 1.0f,0.0f,  1.0f,-1.0f,-1.0f },

                              { 1.0f,1.0f,  1.0f, 1.0f,-1.0f },

                              { 0.0f,1.0f,  1.0f, 1.0f, 1.0f },

                              { 0.0f,0.0f,  1.0f,-1.0f, 1.0f },

                           

                              { 0.0f,0.0f, -1.0f,-1.0f,-1.0f },

                              { 1.0f,0.0f, -1.0f,-1.0f, 1.0f },

                              { 1.0f,1.0f, -1.0f, 1.0f, 1.0f },

                              { 0.0f,1.0f, -1.0f, 1.0f,-1.0f }

                          };

                           

                          struct BMPImage

                          {

                              int   width;

                              int   height;

                              char *data;

                          };

                           

                          //-----------------------------------------------------------------------------

                          // PROTOTYPES

                          //-----------------------------------------------------------------------------

                          void init(void);

                          void render(void);

                          void shutDown(void);

                           

                          //-----------------------------------------------------------------------------

                          // Name: main()

                          // Desc:

                          //-----------------------------------------------------------------------------

                          int main( int argc, char **argv )

                          {

                              // Open a connection to the X server

                              g_pDisplay = XOpenDisplay( NULL );

                              if( g_pDisplay == NULL )

                                  exit(1);

                           

                              int doubleBufferVisual[]  =

                              {

                                  GLX_RGBA,           // Needs to support OpenGL

                                  GLX_DEPTH_SIZE, 16, // Needs to support a 16 bit depth buffer

                                  GLX_DOUBLEBUFFER,   // Needs to support double-buffering

                                  None                // end of list

                              };

                           

                              // Try for the double-bufferd visual first

                              XVisualInfo* visualInfo = glXChooseVisual( g_pDisplay, DefaultScreen(g_pDisplay), doubleBufferVisual );

                              if( visualInfo == NULL )

                                  exit(1);

                           

                              // Create an OpenGL rendering context

                              g_windowContext = glXCreateContext( g_pDisplay, visualInfo, NULL, GL_TRUE ); // Direct rendering if possible

                              if( g_windowContext == NULL )

                                  exit(1);

                           

                              // Create an X colormap since we're probably not using the default visual

                              Colormap colorMap;

                              colorMap = XCreateColormap( g_pDisplay,

                                                          RootWindow(g_pDisplay, visualInfo->screen),

                                                          visualInfo->visual,

                                                          AllocNone );

                           

                              XSetWindowAttributes winAttr;

                              winAttr.colormap     = colorMap;

                              winAttr.border_pixel = 0;

                              winAttr.event_mask   = ExposureMask           |

                                                     VisibilityChangeMask   |

                                                     KeyPressMask           |

                                                     KeyReleaseMask         |

                                                     ButtonPressMask        |

                                                     ButtonReleaseMask      |

                                                     PointerMotionMask      |

                                                     StructureNotifyMask    |

                                                     SubstructureNotifyMask |

                                                     FocusChangeMask;

                           

                              // Create an X window with the selected visual

                              g_window = XCreateWindow( g_pDisplay, RootWindow(g_pDisplay, visualInfo->screen),

                                                        0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, visualInfo->depth, InputOutput,

                               visualInfo->visual, CWBorderPixel | CWColormap | CWEventMask,

                                                        &winAttr );

                           

                              XSetStandardProperties( g_pDisplay, g_window,

                                                      "OpenGL - GL_CLAMP test",

                                                      "opengl_clamp_test", None, argv, argc, NULL );

                           

                              glXMakeCurrent( g_pDisplay, g_window, g_windowContext );

                              XMapWindow( g_pDisplay, g_window );

                           

                              init();

                           

                              while (true)

                                  render();

                           

                              shutDown();

                           

                          XDestroyWindow( g_pDisplay, g_window );

                          XCloseDisplay( g_pDisplay );

                          }

                           

                          //-----------------------------------------------------------------------------

                          // Name: getBitmapImageData()

                          // Desc: Simply image loader for 24 bit BMP files.

                          //-----------------------------------------------------------------------------

                          bool getBitmapImageData(const char *pFileName, BMPImage *pImage )

                          {

                              FILE *pFile = NULL;

                              unsigned short nNumPlanes;

                              unsigned short nNumBPP;

                          int i;

                           

                              if( (pFile = fopen(pFileName, "rb") ) == NULL )

                          return false;

                           

                              // Seek forward to width and height info

                              fseek( pFile, 18, SEEK_CUR );

                           

                              if( (i = fread(&pImage->width, 4, 1, pFile) ) != 1 )

                          return false;

                              if( (i = fread(&pImage->height, 4, 1, pFile) ) != 1 )

                          return false;

                              if( (fread(&nNumPlanes, 2, 1, pFile) ) != 1 )

                          return false;

                              if( nNumPlanes != 1 )

                          return false;

                              if( (i = fread(&nNumBPP, 2, 1, pFile)) != 1 )

                          return false;

                           

                              if( nNumBPP != 24 )

                          return false;

                           

                              // Seek forward to image data

                              fseek( pFile, 24, SEEK_CUR );

                           

                          // Calculate the image's total size in bytes. Note how we multiply the

                          // result of (width * height) by 3. This is becuase a 24 bit color BMP

                          // file will give you 3 bytes per pixel.

                              int nTotalImagesize = (pImage->width * pImage->height) * 3;

                           

                              pImage->data = (char*) malloc( nTotalImagesize );

                           

                              if( (i = fread(pImage->data, nTotalImagesize, 1, pFile) ) != 1 )

                          return false;

                           

                              //

                          // Finally, rearrange BGR to RGB

                          //

                          char charTemp;

                              for( i = 0; i < nTotalImagesize; i += 3 )

                          {

                          charTemp = pImage->data;

                          pImage->data = pImage->data[i+2];

                          pImage->data[i+2] = charTemp;

                              }

                              return true;

                          }

                           

                          //-----------------------------------------------------------------------------

                          // Name: init()

                          // Desc: Init OpenGL context for rendering

                          //-----------------------------------------------------------------------------

                          void init( void )

                          {

                              glXMakeCurrent( g_pDisplay, g_window, g_windowContext );

                           

                          glClearColor( 1.0f, 1.0f, 1.0f, 1.0f );

                          glShadeModel(GL_FLAT);

                          glEnable(GL_TEXTURE_2D);

                          glEnable(GL_DEPTH_TEST);

                           

                          glMatrixMode( GL_PROJECTION );

                          glLoadIdentity();

                          gluPerspective( 45.0f, SCREEN_WIDTH / SCREEN_HEIGHT, 0.1f, 10.0f );

                           

                          BMPImage textureImage;

                              getBitmapImageData("clamptest.bmp", &textureImage);

                           

                          glPixelStorei(GL_UNPACK_ALIGNMENT,1);

                          glGenTextures( 1, &g_testTextureID );

                          glBindTexture( GL_TEXTURE_2D, g_testTextureID );

                           

                              glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);

                              glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

                              // bad clamp

                          glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

                          glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );

                          // good clamp

                          //glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );

                          //glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );

                           

                          glTexImage2D( GL_TEXTURE_2D, 0, 3, textureImage.width, textureImage.height, 0, GL_RGB, GL_UNSIGNED_BYTE, textureImage.data );

                          free(textureImage.data);

                           

                          glMatrixMode( GL_MODELVIEW );

                              glLoadIdentity();

                          glTranslatef( 0.0f, 0.0f, -5.0f );

                          }

                           

                          //-----------------------------------------------------------------------------

                          // Name: render()

                          // Desc: Called when the GLX window is ready to render

                          //-----------------------------------------------------------------------------

                          void render( void )

                          {

                              glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

                           

                          glBindTexture( GL_TEXTURE_2D, g_testTextureID );

                           

                              glInterleavedArrays( GL_T2F_V3F, 0, g_cubeVertices );

                              glDrawArrays( GL_QUADS, 0, 4 );

                           

                              glXSwapBuffers( g_pDisplay, g_window ); // Buffer swap does implicit glFlush

                          }

                           

                          //-----------------------------------------------------------------------------

                          // Name: shutDown()

                          // Desc:

                          //-----------------------------------------------------------------------------

                          void shutDown( void )

                          {

                              glDeleteTextures( 1, &g_testTextureID );

                           

                              if( g_windowContext != NULL )

                              {

                                  // Release the context

                                  glXMakeCurrent( g_pDisplay, None, NULL );

                           

                                  // Delete the context

                                  glXDestroyContext( g_pDisplay, g_windowContext );

                                  g_windowContext = NULL;

                              }

                          }



                          • GL_CLAMP bug
                            gstcyclops

                            I was trying to tell you that the only difference is in GL_NEAREST, everything else is the same. The window ssize or texture size are not important, it happens all the time. Find bellow the full code of a test scenario. If you give me an email I can send you the zip file with the texture and teh make file.