Whee, here we go. :)

Steve wrote:
> I think you have it wrong.
>
> EVERY card implements GL_CLAMP because all that it requires is that
> the texture coordinates are clamped to the range 0..1.

No.  Check the spec, or the recent discussion on the DRI list.  I
thought this must be the case, too, but I was wrong.  Attached is a
simple glut program.  Run it against software mesa and compare against
the NVidia drivers and the specification.  NVidia gets it wrong.

> Very few cards implement GL_CLAMP_TO_EDGE - it was added to OpenGL
> because it does a better visual job of stitching together the edges
> of textures.

No, this is backwards.  CLAMP_TO_EDGE does a *poorer* job of stitching
the edges together when compared with OpenGL 1.0 texture border.  It
was added to the spec because that is all that consumer cards support.

> I don't believe that ATI don't have an efficient implementation of
> GL_CLAMP mode...nearly every software package out there uses it.

Buy one and try it.  They don't.  In their defense, however, they have
a compliant implementation of GL_CLAMP.  No one else does.

> > Running FlightGear under software Mesa creates dark lines in the
> > runways where the default black border is sampled between the
> > tiled textures.
>
> That doesn't happen with GL_CLAMP unless you ask for a texture
> border and PLIB doesn't do that.  None of my games exhibit that
> problem under software Mesa.

Again, read the specification.  The texture border (or border color,
if there is no border) is *always* supposed to be sampled at the
texture edges when using GL_CLAMP.

Andy

--
Andrew J. Ross                NextBus Information Systems
Senior Software Engineer      Emeryville, CA
[EMAIL PROTECTED]              http://www.nextbus.com
"Men go crazy in conflagrations.  They only get better one by one."
 - Sting (misquoted)
#include <stdio.h>

#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>

#define TSZ 32

unsigned char tex[TSZ*TSZ*3];
int state = 0;

/* Tile the texture using four exactly adjacent quads */
void display()
{
    glClear(GL_COLOR_BUFFER_BIT);
    glBegin(GL_QUADS);

    glTexCoord2f(0, 0);  glVertex2f(-0.5, -0.5);
    glTexCoord2f(0, 1);  glVertex2f(-0.5,  0.0);
    glTexCoord2f(1, 1);  glVertex2f( 0.0,  0.0);
    glTexCoord2f(1, 0);  glVertex2f( 0.0, -0.5);
    
    glTexCoord2f(0, 0);  glVertex2f(-0.5, 0.0);
    glTexCoord2f(0, 1);  glVertex2f(-0.5, 0.5);
    glTexCoord2f(1, 1);  glVertex2f( 0.0, 0.5);
    glTexCoord2f(1, 0);  glVertex2f( 0.0, 0.0);

    glTexCoord2f(0, 0);  glVertex2f( 0.0, 0.0);
    glTexCoord2f(0, 1);  glVertex2f( 0.0, 0.5);
    glTexCoord2f(1, 1);  glVertex2f( 0.5, 0.5);
    glTexCoord2f(1, 0);  glVertex2f( 0.5, 0.0);
    
    glTexCoord2f(0, 0);  glVertex2f( 0.0, -0.5);
    glTexCoord2f(0, 1);  glVertex2f( 0.0,  0.0);
    glTexCoord2f(1, 1);  glVertex2f( 0.5,  0.0);
    glTexCoord2f(1, 0);  glVertex2f( 0.5, -0.5);

    glEnd();
    glutSwapBuffers();
}

/* Cycle the texture border mode when the user presses a key */
void keyboard(unsigned char k, int mx, int my)
{
    if(state == 0) {
        printf("GL_CLAMP_TO_EDGE\n");
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    } else if(state == 1) {
        printf("GL_CLAMP\n");
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
    } else if(state == 2) {
        printf("GL_REPEAT\n");
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    }
    if(++state >= 3)
        state = 0;
    glutPostRedisplay();
}

/* Generate a 33%/66% gray mipmapped checkerboard. */
void init()
{
    int i, j;
    for(i=0; i<TSZ; i++) {
        for(j=0; j<TSZ; j++) {
            unsigned char* pix = tex + 3*(i*TSZ + j);
            pix[0] = pix[1] = pix[2] = (i+j)&1 ? 170 : 85;
       }
    }

    gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, TSZ, TSZ, GL_RGB,
                      GL_UNSIGNED_BYTE, tex);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);

    glEnable(GL_TEXTURE_2D);
    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
}

int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
    glutInitWindowSize(512, 512);
    glutCreateWindow("Texture Border Test");
    glutDisplayFunc(display);
    glutKeyboardFunc(keyboard);

    init();
    
    glutMainLoop();
}

Reply via email to