上传Pixel Data OpenGL的备用行

时间:2014-12-23 14:20:37

标签: opengl

我使用glTexImage2D将隔行扫描图像上传到OpenGL纹理,当然这些图像上传了整个图像。我需要的是只上传替代行,所以在第一个纹理奇数行和第二个偶数行上。

我不想在CPU上创建另一个像素数据副本。

2 个答案:

答案 0 :(得分:3)

an ancient SGI extension (GL_SGIX_interlace)用于传输隔行像素数据,但您的实现可能不支持。

您可能考虑的替代方案是内存映射像素缓冲区对象。您可以通过两次传递填充此缓冲区,然后在调用glTexImage2D (...)时将其用作图像数据源。你基本上是自己进行去隔行扫描,但是由于这是通过映射缓冲区对象的内存来完成的,所以你不会在CPU上制作不必要的图像副本。

显示如何执行此操作的伪代码:

GLuint deinterlace_pbo;
glGenBuffers (1, &deinterlace_pbo);

// `GL_PIXEL_UNPACK_BUFFER`, when non-zero is the source of memory for `glTexImage2D`
glBindBuffer (GL_PIXEL_UNPACK_BUFFER, deinterlace_pbo);

// Reserve memory for the de-interlaced image
glBufferData (GL_PIXEL_UNPACK_BUFFER, sizeof (pixel) * interlaced_rows * width * 2,
              NULL, GL_STATIC_DRAW);

// Returns a pointer to the ***GL-managed memory*** where you will write the image
void* pixel_data = glMapBuffer (GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);

// Odd Rows First
for (int i = 0; i < interlaced_rows; i++) {
  for (int j = 0; j < width; j++) {
    //Fill in pixel_data for each pixel in row (i*2+1)
  }
}

// Even Rows
for (int i = 0; i < interlaced_rows; i++) {
  for (int j = 0; j < width; j++) {
    //Fill in pixel_data for each pixel in row (i*2)
  }
}

glUnmapBuffer ();

// This will read the memory in the object bound to `GL_PIXEL_UNPACK_BUFFER`
glTexImage2D (..., NULL);
glBindBuffer (GL_PIXEL_UNPACK_BUFFER, 0);

答案 1 :(得分:3)

您可以将GL_UNPACK_ROW_LENGTH设置为实际行长度的两倍。这将有效地跳过每隔一行。如果纹理的大小为width x height

glPixelStorei(GL_UNPACK_ROW_LENGTH, 2 * width);

glBindTexture(GL_TEXTURE_2D, tex1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);

glPixelStorei(GL_UNPACK_SKIP_PIXELS, width);
glBindTexture(GL_TEXTURE_2D, tex2);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);

glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);

您可以相应地增加数据指针,而不是将GL_UNPACK_SKIP_PIXELS设置为跳过第一行。