【问题标题】:Render OpenGL ES 2.0 to image将 OpenGL ES 2.0 渲染到图像
【发布时间】:2013-05-06 17:56:56
【问题描述】:

我正在尝试对图像文件进行一些 OpenGL ES 2.0 渲染,与屏幕上显示给用户的渲染无关。我正在渲染的图像与用户屏幕的大小不同。我只需要一个 GL_RGB 数据的字节数组。我熟悉 glReadPixels,但我认为在这种情况下它不会起作用,因为我没有从已经渲染的用户屏幕中提取。

伪代码:

// Switch rendering to another buffer (framebuffer? renderbuffer?)

// Draw code here

// Save byte array of rendered data GL_RGB to file

// Switch rendering back to user's screen.

如何在不中断用户显示的情况下执行此操作?我宁愿不必闪烁用户的屏幕,为单个帧绘制我想要的信息,glReadPixel-ing 然后让它消失。

同样,我不希望它向用户显示任何内容。这是我的代码。不起作用..我错过了什么吗?

unsigned int canvasFrameBuffer;
bglGenFramebuffers(1, &canvasFrameBuffer);
bglBindFramebuffer(BGL_RENDERBUFFER, canvasFrameBuffer);
unsigned int canvasRenderBuffer;
bglGenRenderbuffers(1, &canvasRenderBuffer);
bglBindRenderbuffer(BGL_RENDERBUFFER, canvasRenderBuffer);
bglRenderbufferStorage(BGL_RENDERBUFFER, BGL_RGBA4, width, height);
bglFramebufferRenderbuffer(BGL_FRAMEBUFFER, BGL_COLOR_ATTACHMENT0, BGL_RENDERBUFFER, canvasRenderBuffer);

unsigned int canvasTexture;
bglGenTextures(1, &canvasTexture);
bglBindTexture(BGL_TEXTURE_2D, canvasTexture);
bglTexImage2D(BGL_TEXTURE_2D, 0, BGL_RGB, width, height, 0, BGL_RGB, BGL_UNSIGNED_BYTE, 0);
bglFramebufferTexture2D(BGL_FRAMEBUFFER, BGL_COLOR_ATTACHMENT0, BGL_TEXTURE_2D, canvasTexture, 0);

Matrix::matrix_t identity;
Matrix::LoadIdentity(&identity);
bglClearColor(1.0f, 1.0f, 1.0f, 1.0f);
bglClear(BGL_COLOR_BUFFER_BIT);
Draw(&identity, &identity, this);
bglFlush();
bglFinish();

byte *buffer = (byte*)Z_Malloc(width * height * 4, ZT_STATIC);
bglReadPixels(0, 0, width, height, BGL_RGB, BGL_UNSIGNED_BYTE, buffer);
SaveTGA("canvas.tga", buffer, width, height);
Z_Free(buffer);

// unbind frame buffer
bglBindRenderbuffer(BGL_RENDERBUFFER, 0);
bglBindFramebuffer(BGL_FRAMEBUFFER, 0);
bglDeleteTextures(1, &canvasTexture);
bglDeleteRenderbuffers(1, &canvasRenderBuffer);
bglDeleteFramebuffers(1, &canvasFrameBuffer);

【问题讨论】:

  • 我找到了一些关于渲染到纹理的信息,但我不确定这是我想要的,因为我想渲染到一个字节数组来保存/分析图像数据。我很好奇正确的路径是什么。
  • 缓冲区是否最终出现在屏幕上,GPU 仍然需要渲染它。没有办法让离屏渲染不影响性能...
  • 我不是在谈论影响性能,我只是在谈论不向用户显示任何内容(即闪烁)

标签: opengl-es


【解决方案1】:

以下是解决方案,适合任何需要的人:

    // Create framebuffer
unsigned int canvasFrameBuffer;
glGenFramebuffers(1, &canvasFrameBuffer);
glBindFramebuffer(GL_RENDERBUFFER, canvasFrameBuffer);

// Attach renderbuffer
unsigned int canvasRenderBuffer;
glGenRenderbuffers(1, &canvasRenderBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, canvasRenderBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, canvasRenderBuffer);

    // Clear the target (optional)
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);

    // Draw whatever you want here

char *buffer = (char*)malloc(width * height * 3);
glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer);
SaveTGA("canvas.tga", buffer, width, height); // Your own function to save the image data to a file (in this case, a TGA)
free(buffer);

// unbind frame buffer
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDeleteRenderbuffers(1, &canvasRenderBuffer);
glDeleteFramebuffers(1, &canvasFrameBuffer);

【讨论】:

  • 如果宽度/高度大于 GL_MAX_RENDERBUFFER_SIZE,您能否告知您会怎么做?这样就无法创建所需大小的渲染缓冲区...
  • 我无法让它在 linux 上运行。什么是 BGL_RGBA4、ZT_CACHE 和 Z_MALLOC、SAVE_TGA、Z_FREE?
  • 对不起,这些是我构建的功能。我已经编辑了我的帖子,将它们替换为标准的等价物。
【解决方案2】:

您可以渲染到纹理,读取像素并使用该纹理绘制一个四边形(如果您想向用户展示)。它不应该闪烁,但会明显降低性能。

以 iOS 为例:

【讨论】:

  • 用一些我试图渲染到屏幕外纹理的代码更新了帖子。
  • 用stackoverflow上的答案更新了我的一些相关问题的答案。
  • 我没有看到对 glBindFramebuffer 的调用,是在 Draw 中吗?
  • Draw() 只包含基本的 OpenGL 绘图代码...绑定数组和 glDrawArrays 等。 OpenGL ES 2.0 没有 glReadBuffer...?我阅读了您的链接,其中一个发布了“解决方案”,但它看起来非常特定于 iOS。寻找仅限 GL 的东西。
  • 是的,我的错,你不需要 glReadBuffer,版本太多 :)
猜你喜欢
  • 2012-01-16
  • 1970-01-01
  • 1970-01-01
  • 2012-05-14
  • 2014-10-28
  • 2016-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多