Texture Mapping (1)

In memory of my great friend and colleague, late Dr. Mark Harris. This page was made possible by his great lectures in this course in 2000.

We started going over some of the texture mapping options available in OpenGL. The nonlinearity of perspective division results in some distortions when using perspective projections (but not othographic projections). Here is an example of texture mapping using regular patterns. In htis example, the polygon is drawn, then the pattern is also drawn (map) on it.



#include <GL/glut.h >
#pragma warning( disable : 4305 )
typedef GLfloat point3[3];
GLfloat w=.3; //x- and y- bounds for frustum

// List all vertices in array and reference later by index
point3 p[8]={
{0,0,0},
{0,0,1},
{1,0,1},
{1,0,0},
{0,1,0},
{0,1,1},
{1,1,1},
{1,1,0}
};

typedef unsigned char rgb[3];
const int DIM=8;
rgb texture[DIM][DIM];

void drawPoint(int i){
// Draw point i
glVertex3fv(p[i]);
}

void drawFace(int i1,int i2,int i3,int i4){
// draw a face of the cube, mapping texture
glBegin(GL_POLYGON);
glTexCoord2d(0,0);
drawPoint(i1);
glTexCoord2d(1,0);
drawPoint(i2);
glTexCoord2d(1,1);
drawPoint(i3);
glTexCoord2d(0,1);
drawPoint(i4);
glEnd();
}

void drawCube()
{
drawFace(0,3,2,1); //bottom
drawFace(1,2,6,5); //front
drawFace(2,3,7,6); //right side
drawFace(0,1,5,4); //left
drawFace(3,0,4,7); //back side
drawFace(4,5,6,7); //top
}

void myinit(void)
{
int i,j;
//generate checkerboard texture map
for(i=0;i < DIM;i++){
for(j=0;j < DIM;j++){
texture[i][j][0]=255;
texture[i][j][1]=(i+j)%2?255:0;
texture[i][j][2]=(i+j)%2?255:0;
}
}
gluBuild2DMipmaps(GL_TEXTURE_2D,3,DIM,DIM,GL_RGB,GL_UNSIGNED_BYTE,texture);


/* attributes */
glClearColor(1.0, 1.0, 1.0, 1.0); /* white background */
/* set up viewing */
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-w,w,-w,w,.4,8);
glEnable(GL_TEXTURE_2D);
// Point to our texture map
glTexImage2D(GL_TEXTURE_2D,0,3,DIM,DIM,0,GL_RGB,GL_UNSIGNED_BYTE,texture);
// Describe how to enlarge or reduce texture:
// when texture area is small, bilinear filter the closest MIP map
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST );
// when texture area is large, bilinear filter the first MIP map
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
}
void display( void )
{
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(1.5,1.5,1.5,0.5,.5,.5,0,1,0);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); /*clear the window */
double x=1;
for(int i=0;i < 1;i++){
drawCube();
glTranslatef(1,0,0);
glScalef(.5,.5,.5);
}
glFlush(); /* clear buffers */
}

void key(unsigned char key,int x, int y)
{
static int level=1;
glTexImage2D(GL_TEXTURE_2D,level++,3,DIM,DIM,0,GL_RGB,GL_UNSIGNED_BYTE,texture);
glutPostRedisplay();
}


void main(int argc, char** argv)
{
/* Standard GLUT initialization */
glutInit(&argc,argv);
glutInitDisplayMode (GLUT_RGB|GLUT_DEPTH);
glutInitWindowSize(500,500); /* 500 x 500 pixel window */
glutInitWindowPosition(0,0); /* place window top left on display */
glutCreateWindow("Cube"); /* window title */
glutDisplayFunc(display); /* display callback invoked when window opened */
glutKeyboardFunc(key);

myinit(); /* set attributes */
glEnable(GL_DEPTH_TEST); /* Enable hidden--surface--removal */
glutMainLoop(); /* enter event loop */
}

 The tears along the diagonals of each face show the problem. If we change the projection from

	glFrustum(-w,w,-w,w,.4,8);

to

glOrtho(-1,1,-1,1,-10,10);

we get this image:

If we go back to the original perspective projection version and add the line

	glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);

we get a nice improvement on the distorted image: