gpt4 book ai didi

c++ - 如何将屏幕外渲染到 Linux 上的图像?

转载 作者:行者123 更新时间:2023-12-04 18:05:10 26 4
gpt4 key购买 nike

我正在尝试使用 egl 对图像进行离屏渲染。

我的代码没有产生任何错误。 egl 部分似乎是正确的,fbo 也很完整。但是当我使用 glReadPixels 读取像素时,我总是得到一个黑色图像(我用红色清除了整个场景,所以图像也应该是红色的)。

我不知道哪里出了问题。

此外,我注意到 glRenderbufferStorage 只能支持 16 位色深。 GL_RGBA8 被认为是此函数的无效参数。对于严肃的 opengl 应用程序,16 位是不是有点低?

我的环境是带有 mesa 和 intel 图形的 Ubuntu 14.10。

#include <QCoreApplication>
#include <QDebug>
#include <QImage>
#include <GLES2/gl2.h>
#include <EGL/egl.h>

int main(int argc, char *argv[])
{
#define CONTEXT_ES20

#ifdef CONTEXT_ES20
EGLint ai32ContextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE };
#endif

// Step 1 - Get the default display.
EGLDisplay eglDisplay = eglGetDisplay((EGLNativeDisplayType)0);

// Step 2 - Initialize EGL.
eglInitialize(eglDisplay, 0, 0);

#ifdef CONTEXT_ES20
// Step 3 - Make OpenGL ES the current API.
eglBindAPI(EGL_OPENGL_ES_API);

// Step 4 - Specify the required configuration attributes.
EGLint pi32ConfigAttribs[5];
pi32ConfigAttribs[0] = EGL_SURFACE_TYPE;
pi32ConfigAttribs[1] = EGL_WINDOW_BIT;
pi32ConfigAttribs[2] = EGL_RENDERABLE_TYPE;
pi32ConfigAttribs[3] = EGL_OPENGL_ES2_BIT;
pi32ConfigAttribs[4] = EGL_NONE;
#else
EGLint pi32ConfigAttribs[3];
pi32ConfigAttribs[0] = EGL_SURFACE_TYPE;
pi32ConfigAttribs[1] = EGL_WINDOW_BIT;
pi32ConfigAttribs[2] = EGL_NONE;
#endif

// Step 5 - Find a config that matches all requirements.
int iConfigs;
EGLConfig eglConfig;
eglChooseConfig(eglDisplay, pi32ConfigAttribs, &eglConfig, 1,
&iConfigs);

if (iConfigs != 1) {
printf("Error: eglChooseConfig(): config not found.\n");
exit(-1);
}

// Step 6 - Create a surface to draw to.
EGLSurface eglSurface;
eglSurface = eglCreateWindowSurface(eglDisplay, eglConfig,
(EGLNativeWindowType)NULL, NULL);

// Step 7 - Create a context.
EGLContext eglContext;
#ifdef CONTEXT_ES20
eglContext = eglCreateContext(eglDisplay, eglConfig, NULL,
ai32ContextAttribs);
#else
eglContext = eglCreateContext(eglDisplay, eglConfig, NULL, NULL);
#endif

// Step 8 - Bind the context to the current thread
eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);

GLuint fboId = 0;
GLuint renderBufferWidth = 1280;
GLuint renderBufferHeight = 720;

// create a framebuffer object
glGenFramebuffers(1, &fboId);
glBindFramebuffer(GL_FRAMEBUFFER, fboId);

// create a texture object
/* GLuint textureId;
glGenTextures(1, &textureId);
glBindTexture(GL_TEXTURE_2D, textureId);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
//GL_LINEAR_MIPMAP_LINEAR
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_HINT, GL_TRUE); // automatic mipmap
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, renderBufferWidth, renderBufferHeight, 0,
GL_RGB, GL_UNSIGNED_BYTE, 0);
glBindTexture(GL_TEXTURE_2D, 0);
// attach the texture to FBO color attachment point
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, textureId, 0);
*/
qDebug() << glGetError();
GLuint renderBuffer;
glGenRenderbuffers(1, &renderBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, renderBuffer);
qDebug() << glGetError();
glRenderbufferStorage(GL_RENDERBUFFER,
GL_RGB565,
renderBufferWidth,
renderBufferHeight);
qDebug() << glGetError();
glFramebufferRenderbuffer(GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0,
GL_RENDERBUFFER,
renderBuffer);

qDebug() << glGetError();
GLuint depthRenderbuffer;
glGenRenderbuffers(1, &depthRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, renderBufferWidth, renderBufferHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRenderbuffer);

// check FBO status
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if(status != GL_FRAMEBUFFER_COMPLETE) {
printf("Problem with OpenGL framebuffer after specifying color render buffer: \n%x\n", status);
} else {
printf("FBO creation succedded\n");
}

glClearColor(1.0,0.0,0.0,1.0);
glClear(GL_COLOR_BUFFER_BIT);

qDebug() << eglSwapBuffers( eglDisplay, eglSurface);
int size = 4 * renderBufferHeight * renderBufferWidth;
printf("print size");
printf("size %d", size);
qDebug() << size;

unsigned char *data2 = new unsigned char[size];

glReadPixels(0,0,renderBufferWidth,renderBufferHeight,GL_RGB, GL_RGB565, data2);

QImage image(data2, renderBufferWidth, renderBufferHeight,renderBufferWidth*2, QImage::Format_RGB16);

image.save("result.png");


qDebug() << "done";


QCoreApplication a(argc, argv);

return a.exec();
}

最佳答案

OpenGL ES 2.0 支持glReadPixels() 的格式/类型非常有限。不能保证支持您尝试使用的那些:

glReadPixels(0 ,0, renderBufferWidth, renderBufferHeight,
GL_RGB, GL_RGB565, data2);

仅支持两种格式/类型:

  • GL_RGBA/GL_UNSIGNED_BYTE
  • 依赖于实现的组合。

可以通过以下方式查询依赖于实现的组合的格式和类型:

GLint format = 0, type = 0;
glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &format);
glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &type);

这可以为您提供以下组合之一:

  • GL_RGB/GL_UNSIGNED_BYTE
  • GL_RGB/GL_UNSIGNED_SHORT_5_6_5
  • GL_RGBA/GL_UNSIGNED_SHORT_4_4_4_4
  • GL_RGBA/GL_UNSIGNED_SHORT_5_5_5_1
  • GL_ALPHA/GL_UNSIGNED_BYTE

因此,如果实现从上面的 glGetIntegerv() 调用中返回相应的值,那么您尝试使用的组合可能 得到实现的支持。但是,即使它受支持,您的 glReadPixels() 调用的参数中也存在一个微妙但重要的错误:GL_RGB565 is a value for a format,而第 6 个参数是一个类型。调用必须是:

glReadPixels(0 ,0, renderBufferWidth, renderBufferHeight,
GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data2);

关于c++ - 如何将屏幕外渲染到 Linux 上的图像?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28491665/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com