glTexSubImage2D函数

提供修改图像函数,因为修改一个纹理比重新创建一个纹理开销小得多 ,对于一些视频捕捉程序可以先将视频图像存储在更大的初始图像中(该图像大小要求是2的次方,OGL 2.0后没有这个限制),创建一个渲染用的纹理, 然后反复调用glTexSubImage2D(修改的图像区域不用是2的次方)函数从图像视频图像区域读取数据到渲染纹理图像中。渲染用的纹理图像只需要创建一次即可 。 函数原型: glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); target参数必须是glCopyTexImage2D中的对应的target可使用的值。 level 是mipmap等级。 xoffset,yoffset是要修改的图像的左下角偏移。width,height是要修改的图像宽高像素。修改的范围在原图之外并不受到影响。 format,type描述了图像数据的格式和类型,和glTexImage2D中的format, type一致。 pixels 是子图像的纹理数据,替换为的值。 子图像也受到glPixelStore*()和glPixelTransfer*()以及其它像素传输操作所设置模式的影响。

glCopyTexSubImage2D函数

从帧缓存区GL_READ_BUFFER读取一块像素矩形,并替换一个现有的纹理数组的一部分或全部,相当于调用了glCopyTexImage2D和glTexSubImage2D函数。 glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); glCopyTexSubImage2D — copy a two-dimensional texture subimage target Specifies the target texture. Must be GL_TEXTURE_2D GL_TEXTURE_CUBE_MAP_POSITIVE_X GL_TEXTURE_CUBE_MAP_NEGATIVE_X GL_TEXTURE_CUBE_MAP_POSITIVE_Y GL_TEXTURE_CUBE_MAP_NEGATIVE_Y GL_TEXTURE_CUBE_MAP_POSITIVE_Z GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 像素是从当前的GL_READ_BUFFER读取的,它处理的过程像调用了glCopyPixels,但像素数据并不是放在帧缓存区中,而是放入纹理内存中 。glPixelTransfer*和其它像素传输操作的设置也会对它产生作用。 在OGL 3.0及以后的版本,应该可以使用帧缓存区对象直接渲染到纹理内存,从而高效的执行和glCopyTexSubImage2D相同的操作。 OGL3.1增加了纹理单元位置而不是规范化的纹理坐标来定位纹理,这些纹理通过GL_TEXTURE_RACTANGLE的target来指定,若想在渲染时候直接用纹理单元映射为像素就可以这样做。使用纹理矩形也有一些限制,不能基于mipmap的过滤,也不能是压缩的纹理。下面是对矩形纹理的修改操作。 /* Create checkerboard textures */ #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; 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) 0; subImage[i][j][1] = (GLubyte) 0; subImage[i][j][2] = (GLubyte) c; subImage[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(1, &texName); glBindTexture(GL_TEXTURE_2D, texName); 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); void display(void) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_TEXTURE_2D); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); glBindTexture(GL_TEXTURE_2D, texName); glBegin(GL_QUADS); glTexCoord2f(0.0, 0.0); glVertex3f(-2.0, -1.0, 0.0); glTexCoord2f(0.0, 1.0); glVertex3f(-2.0, 1.0, 0.0); glTexCoord2f(1.0, 1.0); glVertex3f(0.0, 1.0, 0.0); glTexCoord2f(1.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(2.41421, 1.0, -1.41421); glTexCoord2f(1.0, 0.0); glVertex3f(2.41421, -1.0, -1.41421); glEnd(); glFlush(); glDisable(GL_TEXTURE_2D); 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, -3.6); void keyboard (unsigned char key, int x, int y) switch (key) { case 's': case 'S': glBindTexture(GL_TEXTURE_2D, texName); int offsetX = 0;// 12; int offsetY = 0;// 44; glTexSubImage2D(GL_TEXTURE_2D, 0, offsetX, offsetY, subImageWidth, subImageHeight, GL_RGBA, GL_UNSIGNED_BYTE, subImage); glutPostRedisplay(); /* glCopyTexSubImage2D*/ break; case 'r': case 'R': glBindTexture(GL_TEXTURE_2D, texName); 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; int main(int argc, char** argv) glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(250, 250); glutInitWindowPosition(100, 100); glutCreateWindow(argv[0]); init(); glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); glutMainLoop(); return 0; #else int main(int argc, char** argv) fprintf (stderr, "This program demonstrates a feature which is not in OpenGL Version 1.0.\n"); fprintf (stderr, "If your implementation of OpenGL Version 1.0 has the right extensions,\n"); fprintf (stderr, "you may be able to modify this program to make it run.\n"); return 0; #endif glTexSubImage2D函数提供修改图像函数,因为修改一个纹理比重新创建一个纹理开销小得多,对于一些视频捕捉程序可以先将视频图像存储在更大的初始图像中(该图像大小要求是2的次方,OGL 2.0后没有这个限制),创建一个渲染用的纹理,然后反复调用glTexSubImage2D(修改的图像区域不用是2的次方)函数从图像视频图像区域读取数据到渲染纹理图像中。渲染用的纹理图像只需要创建一次即可。
一种是直观的使用 gl Get Tex Image ,然后获取数据到内存再贴上去,这种方法很慢 另一种是使用FBO,将 纹理 附加到FBO,然后用 gl Copy Tex Sub Image 2D ,不涉及跟内存交换数据,速度飞快。 方法一:获取 纹理 再拷贝 unsigned char * data = new unsigned char[normal_ tex ture.width*normal_ tex ture.Hight*4]; gl Bind Tex ture( GL _ TEX TURE_ 2D ,src_id); 在频繁调用以下 GL ES20. gl Tex Sub Image 2D 函数时, public static native void gl Tex Sub Image 2D ( int target, int level, int xoffset, int yoffset, int width, int height, int format, int type, java.nio.B
gl Copy Tex Sub Image 2D - 复制二维 纹理 子图像 void gl Copy Tex Sub Image 2D ( GL enum target, GL int level, GL int xoffset, GL int yoffset, GL int x, GL int y, GL sizei width, GL sizei height); target 指定活动 纹理 单元的目标 纹理 ...