纹理贴图的步骤
1.创建纹理对象,并为它指定一个纹理,纹理包含1维,2维,3维。描述纹理的数据由1~4个元素组成,用于表示RGBA四元组。调整常量或者深度成分
glGenTextures(1, &texture[0]);
glBindTexture(GL_TEXTURE_2D, texture[0]);
2.确定纹理如何应用到每个像素上
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
3.启用纹理贴图功能
GL_TEXTURE_1D,GL_TEXTURE_2D,GL_TEXTURE_3D,GL_TEXTURE_CUBE_MAP如果同时启用了2维3维,则以后者为准,如果启用了GL_TEXTURE_CUBE_MAP,则其他被启用的纹理均不在生效
4.绘制场景,提供纹理坐标和几何图形坐标
指定纹理
void glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);定义一个2维纹理
GL_TEXTURE_1D |
1维纹理 | |
GL_TEXTURE_2D |
2维纹理 | |
GL_PROXY_TEXTURE_1D |
1维代理纹理 | |
GL_PROXY_TEXTURE_2D | 2维代理纹理 | |
GL_TEXTURE_CUBE_MAP_POSITIVE_X |
立方体X轴正方向纹理 | |
target | GL_TEXTURE_CUBE_MAP_NEGATIVE_X |
立方体X轴负方向纹理 |
GL_TEXTURE_CUBE_MAP_POSITIVE_Y |
立方体Y轴正方向纹理 | |
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y |
立方体Y轴负方向纹理 | |
GL_TEXTURE_CUBE_MAP_POSITIVE_Z |
立方体Z轴正方向纹理 | |
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z | 立方体Z轴负方向纹理 | |
GL_PROXY_TEXTURE_CUBE_MAP | 立方体代理纹理 | |
level | 多重细节层时指定的分辨率,对于普通来说设置为0 | |
纹理内部数据格式,图像数据转换为纹理数据希望以哪种数据格式存储 | ||
GL_LUMINANCE | 只含有亮度成分 | |
interna | GL_LUMINANCE_ALPHA | 含有亮度和A成分 |
lformat | GL_DEPTH_COMPONENT | 深度缓存 |
GL_RGB | RGB颜色格式 | |
GL_RGBA | RGBA颜色格式 | |
height width |
必须是2m+2b,其中m是一个非负的整数,b是border值,纹理最大值取决于OPENGL,但它最少是64*64 | |
border | 边框,0代表无,1代表有 | |
format | 图像数据颜色格式 | |
type | GL_BYTE GL_UNSIGNED_BYTE GL_SHORT GL_UNSIGHED_SHORT …… |
图像数据数据类型 |
pixels | 图像数据 |
void glCopyTexImage2D (GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
void glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
替换当前一幅现有的二维图像的全部或一块连续的区域
和修改原有的纹理对比,创建新纹理的开销更大一些,用新的信息修改一个现有纹理的全部或一部分常常比重头创建一个新纹理和合适
void glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
使用帧缓冲区的图像数据代替现有的一幅二维纹理图像的一部分或全部
纹理代理
由于纹理资源有限,因此来判断是否有足够的纹理空间来存储是十分重要的,纹理代理作用就在于此
1.查询系统支持纹理图像最大宽度和最大高度
glGetIntegerv(GL_MAX_TEXTURE_SIZE,size);
GL_MAX_3D_TEXTURE_SIZE 3D纹理图像
GL_MAX_CUBE_TEXTURE_SIZE 立方体纹理图像
2.使用纹理代理查询纹理资源
2.1 设置要查询的内容
glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_RGBA, 10240, 10240,
0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
2.2 查询纹理资源
void glGetTexLevelParameteriv (GLenum target, GLint level, GLenum pname, GLint *params);
pname:GL_TEXTURE_WIDTH
GL_TEXTURE_HEIGHT
GL_TEXTURE_DEPTH
GL_TEXTURE_BORDER
GL_TEXTURE_INTERNAL_FORMAT
GL_TEXTURE_RED_SIZE
GL_TEXTURE_BLUE_SIZE
GL_TEXTURE_GREED_SIZE
GL_TEXTURE_ALPHA_SIZE
GL_TEXTURE_LUMINANCE_SIZE
GL_TEXTURE_INTENSITY_SIZE
如果没有足够的资源容纳这个纹理代理,宽度,高度,边框宽度以及成分分辨率的纹理状态变量都设置为0
创建帧缓冲区的数据来定义纹理单元
一维纹理
void glTexImage1D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
一维纹理可以看成是高度为1的2为纹理
三维纹理
void glTexImage3D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei depth ,GLint border, GLenum format, GLenum type, const GLvoid *pixels);
三维纹理可以看成由一层层的2纹理组成
#include "header.h" #define checkImageWidth 64 #define checkImageHeight 64 #define subImageWidth 16 #define subImageHeight 16 static GLubyte checkImage[checkImageHeight][checkImageWidth][4]; static GLubyte subImage[subImageHeight][subImageWidth][4]; static GLuint texName[2]; float quard=0.0f; 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; } } for (i = 0; i < subImageHeight; i++) { for (j = 0; j < subImageWidth; j++) { c = ((((i&0x4)==0)^((j&0x4))==0))*255; subImage[i][j][0] = (GLubyte) c; subImage[i][j][1] = (GLubyte) 0; subImage[i][j][2] = (GLubyte) 0; subImage[i][j][3] = (GLubyte) 255; } } } void init(void) { GLuint size[2]; glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE,size); glClearColor (0.0, 0.0, 0.0, 0.0); glShadeModel(GL_FLAT); glClearDepth(1.0f); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); makeCheckImages(); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); /* glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_RGBA, 1024, 1024, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D,0,GL_TEXTURE_DEPTH,size);*/ glGenTextures(2, &texName[0]); glBindTexture(GL_TEXTURE_2D, texName[0]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 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_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glCopyTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,0,0,100,100,0); } void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); glEnable(GL_TEXTURE_2D); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); glBindTexture(GL_TEXTURE_2D, texName[0]); glRotatef(quard,1,0,0); glBegin(GL_QUADS); glTexCoord2f(0.0, 0.0) ;glVertex3f(0.0, 100, 0); glTexCoord2f(0.0, 1.0); glVertex3f(100, 100, 0); glTexCoord2f(1.0, 1.0); glVertex3f(100, 0, 0); glTexCoord2f(1.0, 0.0); glVertex3f(0, 0, 0); glEnd(); glBindTexture(GL_TEXTURE_2D, texName[1]); glColor3f(1,0,0); glBegin(GL_QUADS); glTexCoord2f(1.0, 0.0) ;glVertex3f(150, 100, 0); glTexCoord2f(1.0, 1.0); glVertex3f(250, 100, 0); glTexCoord2f(0.0, 1.0); glVertex3f(250, 0, 0); glTexCoord2f(0.0, 0.0); glVertex3f(150, 0, 0); glEnd(); glFlush(); glDisable(GL_TEXTURE_2D); } void reshape(int w, int h) { glViewport(0, 0, (GLsizei) w, (GLsizei) h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-0, (GLdouble) w, -0, (GLdouble) h,-100,100); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0.0, 0.0, -3.6); } void keyboard (unsigned char key, int x, int y) { switch (key) { case 's': case 'S': glBindTexture(GL_TEXTURE_2D, texName[0]); glTexSubImage2D(GL_TEXTURE_2D, 0, 12, 44, subImageWidth, subImageHeight, GL_RGBA, GL_UNSIGNED_BYTE, subImage); glutPostRedisplay(); break; case 'a': case 'A': glBindTexture(GL_TEXTURE_2D, texName[1]); glCopyTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,0,0,100,100,0); glutPostRedisplay(); break; case 'B': case 'b': glBindTexture(GL_TEXTURE_2D, texName[1]); glCopyTexSubImage2D(GL_TEXTURE_2D,0,10,10,20,20,120,120); glutPostRedisplay(); break; case 'r': case 'R': glBindTexture(GL_TEXTURE_2D, texName[0]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, checkImageWidth, checkImageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, checkImage); glutPostRedisplay(); break; case 27: exit(0); break; default: break; } } void rotate() { quard+=0.1; glutPostRedisplay(); } void mouse(int button,int state,int x,int y) { switch(button) { case GLUT_LEFT_BUTTON: if(GLUT_DOWN==state) { glutIdleFunc(rotate); }else { //glutIdleFunc(0); } break; } } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(600, 480); glutInitWindowPosition(100, 100); glutCreateWindow("纹理贴图"); glewInit(); init(); glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); glutMouseFunc(mouse); glutMainLoop(); return 0; }