OpenGL中内存和显存之间的拷贝操作

1. 从内存至显存
1.1 对Buffer object的操作,比较简单:

glGenBuffers(NumBuffers, Buffers);
glBindBuffer(GL_ARRAY_BUFFER, Buffers[ArrayBuffer]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

1.2 对Texture的操作,要注意根据内存中数据的存放格式,设置正确的format和type。这是容易导致纹理填充失败的原因之一。
其次,通过glPixelStore设置的GL_UNPACK_XXX的参数也会影响到填充操作。
spec:
If target is GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE or one of the GL_TEXTURE_CUBE_MAP targets, data is read from data as a sequence of signed or unsigned bytes, shorts, or longs, or single-precision floating-point values, depending on type. These values are grouped into sets of one, two, three, or four values, depending on format, to form elements. Each data byte is treated as eight 1-bit elements, with bit ordering determined by GL_UNPACK_LSB_FIRST (see glPixelStore).
void glTexImage2D(     GLenum target,
      GLint level,
      GLint internalformat,  // Texture的颜色格式
      GLsizei width,
      GLsizei height,
      GLint border,
      GLenum format,     // 内存数据data的颜色格式
      GLenum type,       // 内存数据data的排放格式
      const void * data);

char *data = ...;  // CPU memory
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
GLenum err1 = glGetError();
// data的数据内容为【R(1 byte), G(1 byte), B(1 byte), A(1 byte)】, 【R(1 byte), G(1 byte), B(1 byte), A(1 byte)】...
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
GLenum err2 = glGetError();
// check err1 and err2
glBindTexture(GL_TEXTURE_2D, 0);

在指定正确format和type后,如果依然填充失败,可以检查如下参数:

glGetIntegerv(GL_UNPACK_SWAP_BYTES, &old_unpack_swap_bytes);
glGetIntegerv(GL_UNPACK_LSB_FIRST, &old_unpack_lsb_first);
glGetIntegerv(GL_UNPACK_ROW_LENGTH, &old_unpack_row_length);
glGetIntegerv(GL_UNPACK_IMAGE_HEIGHT, &old_unpack_image_height);
glGetIntegerv(GL_UNPACK_SKIP_ROWS, &old_unpack_skip_rows);
glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &old_unpack_skip_pixels);
glGetIntegerv(GL_UNPACK_SKIP_IMAGES, &old_unpack_skip_images);
glGetIntegerv(GL_UNPACK_ALIGNMENT, &old_unpack_alignment);
// 参考如下设置
glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);
glPixelStorei(GL_UNPACK_LSB_FIRST, 0);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// call glTexImage2D or glTexSubImage2D
// 恢复设置
glPixelStorei(GL_UNPACK_SWAP_BYTES, old_unpack_swap_bytes);
glPixelStorei(GL_UNPACK_LSB_FIRST, old_unpack_lsb_first);
glPixelStorei(GL_UNPACK_ROW_LENGTH, old_unpack_row_length);
glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, old_unpack_image_height);
glPixelStorei(GL_UNPACK_SKIP_ROWS, old_unpack_skip_rows);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, old_unpack_skip_pixels);
glPixelStorei(GL_UNPACK_SKIP_IMAGES, old_unpack_skip_images);
glPixelStorei(GL_UNPACK_ALIGNMENT, old_unpack_alignment);

2. 从显存到内存
典型的,从FBO中读取渲染完成的画面至内存。这里也需要注意glPixelStore设置的参数会影响到是否成功读取。

glPixelStorei(GL_PACK_ALIGNMENT, 1);  /* default is 4 */
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
glPixelStorei(GL_PACK_SKIP_ROWS, 0);
glPixelStorei(GL_PACK_SKIP_PIXELS, 0);

char *data = malloc(...);  // CPU memory
GLenum lastBuffer;
glGetIntegerv(GL_READ_BUFFER, &lastBuffer);
// 如果已经通过glBindFramebuffer(GL_READ_FRAMEBUFFER, ...)指定了读取源,则不需要再通过glReadBuffer指定
glReadBuffer(GL_FRONT_LEFT);
glReadPixels(0, 0, width, height, format, GL_UNSIGNED_BYTE, data);
glReadBuffer(lastBuffer);

 

你可能感兴趣的:(Linux,Graphics)