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