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(); }