在纹理贴图场景时,必须为每个顶点提供物体坐标和顶点坐标,经过变换之后,物体坐标决定了应该在屏幕上的那个地点渲染每个特定的顶点,纹理坐标决定了纹理图像中的那个纹理单元将分配给这个顶点
void glTexCoord{1,2,3,4}{sifd} (Type coords);
纹理的放大与缩小
1.原始大小
glTexCoord2f(0.0f, 0.0f); glVertex2f(-1.0f, -1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex2f( 1.0f, -1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex2f( 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex2f(-1.0f, 1.0f);
1.X轴重复(放大与缩小)
glTexCoord2f(0.0f, 0.0f); glVertex2f(-1.0f, -1.0f);
glTexCoord2f(n*1.0f, 0.0f); glVertex2f( 1.0f, -1.0f);
glTexCoord2f(n*1.0f, 1.0f); glVertex2f( 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex2f(-1.0f, 1.0f);
当n=2时 当n=0.5时
2.Y轴重复(放大与缩小)
glTexCoord2f(0.0f, 0.0f); glVertex2f(-1.0f, -1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex2f( 1.0f, -1.0f);
glTexCoord2f(1.0f, n*1.0f); glVertex2f( 1.0f, 1.0f);
glTexCoord2f(0.0f, n*1.0f); glVertex2f(-1.0f, 1.0f);
当n=2时 当n=0.5时
3.纹理水平移动
glBegin(GL_QUADS);
glTexCoord2f(roll+0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 0.0f);
glTexCoord2f(roll+1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 0.0f);
glTexCoord2f(roll+1.0f,1.0f); glVertex3f( 1.0f, 1.0f, 0.0f);
glTexCoord2f(roll+0.0f,1.0f); glVertex3f(-1.0f, 1.0f, 0.0f);
glEnd()
其中roll决定纹理水平移动的幅度,roll应该在0.1之间
4.纹理上下移动
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f+roll); glVertex3f(-1.0f, -1.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f+roll); glVertex3f( 1.0f, -1.0f, 0.0f);
glTexCoord2f(1.0f,1.0f+roll); glVertex3f( 1.0f, 1.0f, 0.0f);
glTexCoord2f(0.0f,1.0f+roll); glVertex3f(-1.0f, 1.0f, 0.0f);
glEnd()
其中roll决定纹理上下移动的幅度,roll应该在0.1之间
纹理的重复与截取
当我们进行纹理放大时,纹理会以重复的形式进行平铺GL_REPEAT,但有时我们希望纹理坐标放大,可纹理并不进行重复的平铺,这就用到了截取GL_CLAMP
纹理重复:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
下图左边为2*2纹理的重复,右边为1*1纹理
glTexCoord2f(0.0, 0.0); glVertex3f(-2.0, -1.0, 0.0);
glTexCoord2f(0.0, 2.0); glVertex3f(-2.0, 1.0, 0.0);
glTexCoord2f(2.0, 2.0); glVertex3f(0.0, 1.0, 0.0);
glTexCoord2f(2.0, 0.0); glVertex3f(0.0, -1.0, 0.0);
glTexCoord2f(0.0, 0.0); glVertex3f(1.0, -1.0, 0.0);
glTexCoord2f(0.0, 1.0); glVertex3f(1.0, 1.0, 0.0);
glTexCoord2f(1.0, 1.0); glVertex3f(3, 1.0, -0);
glTexCoord2f(1.0, 0.0); glVertex3f(3, -1.0, -0);
纹理截取
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP)
glTexCoord2f(0.0, 0.0); glVertex3f(-2.0, -1.0, 0.0);
glTexCoord2f(0.0, 2.0); glVertex3f(-2.0, 1.0, 0.0);
glTexCoord2f(2.0, 2.0); glVertex3f(0.0, 1.0, 0.0);
glTexCoord2f(2.0, 0.0); glVertex3f(0.0, -1.0, 0.0);
glTexCoord2f(0.0, 0.0); glVertex3f(1.0, -1.0, 0.0);
glTexCoord2f(0.0, 1.0); glVertex3f(1.0, 1.0, 0.0);
glTexCoord2f(1.0, 1.0); glVertex3f(3, 1.0, -0);
glTexCoord2f(1.0, 0.0); glVertex3f(3, -1.0, -0);
左边的图为2*2纹理放大,右边为1*1纹理放大(原始大小)
glTexParameter*()函数的参数 |
参数(pname) | 值(param) | |||||||
GL_TEXTURE_WRAP_S 从左至右纹理环绕模式 GL_TEXTURE_WRAP_T 从下至上纹理环绕模式 GL_TEXTURE_WRAP_R 从里至外纹理环绕模式 |
GL_CLAMP:截取 GL_REPEAT:重复 GL_MIRRORED_REPEAT:镜像重复 GL_CLAMP_TO_EDGE:忽略边框截取 GL_CLAMP_TO_BORDER:代边框的截取 |
|||||||
GL_TEXTURE_MAG_FILTER | GL_NEAREST或GL_LINEAR | |||||||
GL_TEXTURE_MIN_FILTER | GL_NEAREST 速度快,效果差 GL_LINEAR 计算量大。效果好 GL_NEAREST_MIPMAP_NEAREST 速度快,效果差 GL_LINEAR_MIPMAP_NEAREST GL_NEAREST_MIPMAP_LINEAR GL_LINEAR_MIPMAP_LINEAR 计算量大。效果好 |
|||||||
GL_TEXTURE_BORDER_COLOR | ||||||||
GL_TEXTURE_PRIORITY | (0,1)纹理优先级 | |||||||
GL_TEXTURE_BASE_LEVEL | 浮点值 | |||||||
GL_TEXTURE_MAX_LEVEL | 浮点值 | |||||||
GL_TEXTURE_MIN_LOD | 浮点值 | |||||||
GL_TEXTURE_MAX_LEVEL | 浮点值 | |||||||
GL_TEXTURE_LOD_BIAS | ||||||||
GL_TEXTURE_COMPARE_MODE 纹理比较模式 |
GL_COMPARE_R_TO_TEXTURE 深度比较 | |||||||
GL_DEPTH_TEXTURE_MODE | GL_RED:R GL_LUMINANCE:亮度 GL_INSENSITY GL_ALPHA:A |
|||||||
GL_TEXTURE_COMPARE_FUNC 纹理比较方式 |
GL_LEQUAL,GL_GEQUAL,GL_LESS,GL_GREATER,GL_EQUAL, GL_NOTEQUAL,GL_ALWAYS,GL_NEVER |
|||||||
GL_GENERATE_MIAMAP 自动生成多重细节层 |
GL_TRUE,GL_FALSE |
纹理坐标DEMO
#include "header.h" GLuint texture[1]; float rollx=0.0f; float rolly=0.0f; bool isX=false; bool isY=false; float xdouble=1.0f; float ydouble=1.0f; AUX_RGBImageRec *LoadBMP(char *Filename) { FILE *File=NULL; if (!Filename) { return NULL; } File=fopen(Filename,"r"); if (File) { fclose(File); return auxDIBImageLoad(Filename); } return NULL; } int LoadGLTextures() { int Status=FALSE; AUX_RGBImageRec *TextureImage[1]; memset(TextureImage,0,sizeof(void *)*1); if (TextureImage[0]=LoadBMP("Data/NeHe.bmp")) { Status=TRUE; glGenTextures(1, &texture[0]); // Typical Texture Generation Using Data From The Bitmap glBindTexture(GL_TEXTURE_2D, texture[0]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); } if (TextureImage[0]) { if (TextureImage[0]->data) { free(TextureImage[0]->data); } free(TextureImage[0]); } return Status; } GLvoid ReSizeGLScene(GLsizei width, GLsizei height) { if (height==0) { height=1; } glViewport(0,0,width,height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); // Calculate The Aspect Ratio Of The Window gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } int InitGL(GLvoid) { if (!LoadGLTextures()) { return FALSE; } glEnable(GL_TEXTURE_2D); glShadeModel(GL_SMOOTH); glClearColor(0.0f, 0.0f, 0.0f, 0.5f); glClearDepth(1.0f); glEnable(GL_DEPTH_TEST); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); return TRUE; } void DrawGLScene(GLvoid) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); glTranslatef(0.0f,0.0f,-5.0f); glBindTexture(GL_TEXTURE_2D, texture[0]); glBegin(GL_QUADS); // Front Face glTexCoord2f(0.0f+rollx, 0.0f+rolly); glVertex2f(-1.0f, -1.0f); glTexCoord2f(xdouble*1.0f+rollx, 0.0f+rolly); glVertex2f( 1.0f, -1.0f); glTexCoord2f(xdouble*1.0f+rollx,ydouble*1.0f+rolly); glVertex2f( 1.0f, 1.0f); glTexCoord2f(0.0f+rollx, ydouble*1.0f+rolly); glVertex2f(-1.0f, 1.0f); glEnd(); glFlush(); } void scroll() { if(isX) { rollx+=0.002f; if (rollx>1.0f) { rollx-=1.0f; } } if (isY) { rolly+=0.002f; if (rolly>1.0f) { rolly-=1.0f; } } glutPostRedisplay(); } void keyboard(unsigned char key,int x,int y) { switch (key) { case ‘x‘: isX=true; isY=false; glutIdleFunc(scroll); break; case ‘y‘: isY=true; isX=false; glutIdleFunc(scroll); break; case ‘X‘: xdouble=xdouble+0.5f; break; case ‘Y‘: isY=true; ydouble=ydouble+0.5f; break; } } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(640,480); glutCreateWindow("纹理坐标"); glutReshapeFunc(ReSizeGLScene); glutDisplayFunc(DrawGLScene); glutKeyboardFunc(keyboard); InitGL(); glutMainLoop(); return 0; }
纹理截取DEMO
#include "header.h" #define checkImageWidth 64 #define checkImageHeight 64 static GLubyte checkImage[checkImageHeight][checkImageWidth][4]; static GLubyte otherImage[checkImageHeight][checkImageWidth][4]; static GLuint texName[2]; void makeCheckImages(void) { int i, j, c; for (i = 0; i < checkImageHeight; i++) { for (j = 0; j < checkImageWidth; j++) { c = ((((i&0x8)==0)^((j&0x8))==0))*255; checkImage[i][j][0] = (GLubyte) c; checkImage[i][j][1] = (GLubyte) c; checkImage[i][j][2] = (GLubyte) c; checkImage[i][j][3] = (GLubyte) 255; c = ((((i&0x10)==0)^((j&0x10))==0))*255; otherImage[i][j][0] = (GLubyte) c; otherImage[i][j][1] = (GLubyte) 0; otherImage[i][j][2] = (GLubyte) 0; otherImage[i][j][3] = (GLubyte) 255; } } } void init(void) { glClearColor (0.0, 0.0, 0.0, 0.0); glShadeModel(GL_FLAT); glEnable(GL_DEPTH_TEST); makeCheckImages(); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glGenTextures(2, texName); glBindTexture(GL_TEXTURE_2D, texName[0]); 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); glBindTexture(GL_TEXTURE_2D, texName[1]); 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); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, checkImageWidth, checkImageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, otherImage); glEnable(GL_TEXTURE_2D); } void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glBindTexture(GL_TEXTURE_2D, texName[0]); glBegin(GL_QUADS); glTexCoord2f(0.0, 0.0); glVertex3f(-2.0, -1.0, 0.0); glTexCoord2f(0.0, 4.0); glVertex3f(-2.0, 1.0, 0.0); glTexCoord2f(4.0, 4.0); glVertex3f(0.0, 1.0, 0.0); glTexCoord2f(4.0, 0.0); glVertex3f(0.0, -1.0, 0.0); glEnd(); glBindTexture(GL_TEXTURE_2D, texName[1]); glBegin(GL_QUADS); glTexCoord2f(0.0, 0.0); glVertex3f(2.5, -1.0, 0.0); glTexCoord2f(0.0, 1.0); glVertex3f(2.5, 1.0, 0.0); glTexCoord2f(1.0, 1.0); glVertex3f(0.5, 1.0, -0); glTexCoord2f(1.0, 0.0); glVertex3f(0.5, -1.0, -0); glEnd(); glFlush(); } void reshape(int w, int h) { glViewport(0, 0, (GLsizei) w, (GLsizei) h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1.0, 30.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0.0, 0.0, -5); } void keyboard(unsigned char key, int x, int y) { switch (key) { case 27: exit(0); break; } } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(250, 250); glutInitWindowPosition(100, 100); glutCreateWindow("纹理截取"); init(); glutReshapeFunc(reshape); glutDisplayFunc(display); glutKeyboardFunc (keyboard); glutMainLoop(); return 0; }