cancel
Showing results for 
Search instead for 
Did you mean: 

Archives Discussions

gstcyclops
Journeyman III

GL_CLAMP bug

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!

0 Likes
8 Replies
kenwang
Staff

I will take a look.

0 Likes

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?

 

 

0 Likes

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?

0 Likes

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.

0 Likes

// 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;

    }

}



0 Likes

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.

0 Likes

It's proved to be not a bug of AMD card. Please refer to the OpenGL 2.1 spec, because the GL_CLAMP is depricated since OpenGL 3.0.

when you are using GL_CLAMP, the texture coordinate will be clampled to half pixel over the boundary, and you specifed GL_LINEAR fileter, the border color will be used to generate the color where textue coordinate is not in 0.0 and 1.0.

0 Likes

I will take a look.

my website

0 Likes