pbuffer vs fbo in egl-offscreen-rendering
Ich bin sehr verwirrt, egl pbuffer Oberfläche. Meiner Meinung nach, ein pbuffer Oberfläche ist eine Plattform-unabhängige Oberfläche, so wie die windows-Oberfläche oder mit der pixmap-Oberfläche. Dinge gezeichnet, die Oberfläche, obwohl nicht sichtbar, sollte in der Lage sein, wieder zu Lesen.
die Antwort auf diese Frage scheint zu bestätigen, dass mein Verständnis:
Unterschied von eglCreatePbufferSurface und eglCreatePixmapSurface mit OpenGL ES(EGL)
aber mein experiment zeigt, dass brauche ich zum erstellen eines fbo buffer zusätzlich zu pbuffer Oberfläche.
dieser code scheint zu funktionieren für mich, es schafft einen pbuffer Oberfläche und dann ein fbo.
#include <GLES2/gl2.h>
#include <EGL/egl.h>
int main(int argc, char *argv[])
{
EGLint ai32ContextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE };
//Step 1 - Get the default display.
EGLDisplay eglDisplay = eglGetDisplay((EGLNativeDisplayType)0);
//Step 2 - Initialize EGL.
eglInitialize(eglDisplay, 0, 0);
//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;
//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 = eglCreatePbufferSurface(eglDisplay, eglConfig, NULL);
//Step 7 - Create a context.
EGLContext eglContext;
eglContext = eglCreateContext(eglDisplay, eglConfig, NULL, ai32ContextAttribs);
//Step 8 - Bind the context to the current thread
eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);
GLuint fboId = 0;
GLuint renderBufferWidth = 1920;
GLuint renderBufferHeight = 1080;
//Step 9 - create a framebuffer object
glGenFramebuffers(1, &fboId);
glBindFramebuffer(GL_FRAMEBUFFER, fboId);
GLuint renderBuffer;
glGenRenderbuffers(1, &renderBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, renderBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB565, renderBufferWidth, renderBufferHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderBuffer);
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);
//Step 10 - 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");
}
int size = 4 * renderBufferHeight * renderBufferWidth;
unsigned char *data2 = new unsigned char[size];
//Step 11 - clear the screen in Red and read it back
glClearColor(1.0,0.0,0.0,1.0);
glClear(GL_COLOR_BUFFER_BIT);
eglSwapBuffers( eglDisplay, eglSurface);
glReadPixels(0,0,renderBufferWidth,renderBufferHeight,GL_RGBA, GL_UNSIGNED_BYTE, data2);
... save data2 to image ...
}
Allerdings, wenn ich entfernen Sie die fbo, und versuchen zu zeichnen, um den pbuffer direkt, sehe ich ein "segmentation fault" sofort nach dem Aufruf von glClear () - Funktion:
#include <GLES2/gl2.h>
#include <EGL/egl.h>
int main(int argc, char *argv[])
{
EGLint ai32ContextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE };
//Step 1 - Get the default display.
EGLDisplay eglDisplay = eglGetDisplay((EGLNativeDisplayType)0);
//Step 2 - Initialize EGL.
eglInitialize(eglDisplay, 0, 0);
//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;
//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 = eglCreatePbufferSurface(eglDisplay, eglConfig, NULL);
//Step 7 - Create a context.
EGLContext eglContext;
eglContext = eglCreateContext(eglDisplay, eglConfig, NULL, ai32ContextAttribs);
//Step 8 - Bind the context to the current thread
eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);
int size = 4 * renderBufferHeight * renderBufferWidth;
unsigned char *data2 = new unsigned char[size];
//Step 11 - clear the screen in Red and read it back
glClearColor(1.0,0.0,0.0,1.0);
glClear(GL_COLOR_BUFFER_BIT);
eglSwapBuffers( eglDisplay, eglSurface);
glReadPixels(0,0,renderBufferWidth,renderBufferHeight,GL_RGBA, GL_UNSIGNED_BYTE, data2);
... save data2 to image ...
}
Meine Umgebung ist ubuntu 14 mit intel graphics/mesa.
Wissen Sie, warum ich sah die "segmentation fault"? (Ich habe in der eglcontext, das scheint zu sein, erfolgreich erstellt.) Können Sie bestätigen, dass die fbo ist gebraucht mit pbuffer Oberfläche?
EDIT: wie bereits von Reto, mein problem ist, weil der fehlende Attribute.
nach Einstellung werden diese Attribute, ich war in der Lage, Dinge zu machen die Arbeit mit opengl es 2 Kontext. Aber ich habe noch Probleme mit dem desktop opengl-Kontext.
Lesen, anstatt wieder ein rotes Bild, mit dem desktop opengl-Kontext, könnte ich nur ein transparentes Bild. hier ist meine aktuelle code:
#include <QCoreApplication>
#include <QDebug>
#include <QImage>
#include <GL/gl.h>
#include <EGL/egl.h>
#include <QElapsedTimer>
int main(int argc, char *argv[])
{
//Step 1 - Get the default display.
EGLDisplay eglDisplay = eglGetDisplay((EGLNativeDisplayType)0);
//Step 2 - Initialize EGL.
eglInitialize(eglDisplay, 0, 0);
//Step 3 - Make OpenGL ES the current API.
eglBindAPI(EGL_OPENGL_API);
//Step 4 - Specify the required configuration attributes.
EGLint pi32ConfigAttribs[5];
pi32ConfigAttribs[0] = EGL_SURFACE_TYPE;
pi32ConfigAttribs[1] = EGL_PBUFFER_BIT;
pi32ConfigAttribs[2] = EGL_RENDERABLE_TYPE;
pi32ConfigAttribs[3] = EGL_OPENGL_BIT;
pi32ConfigAttribs[4] = EGL_CONFORMANT;
pi32ConfigAttribs[5] = EGL_OPENGL_BIT;
pi32ConfigAttribs[6] = EGL_COLOR_BUFFER_TYPE;
pi32ConfigAttribs[7] = EGL_RGB_BUFFER;
pi32ConfigAttribs[8] = EGL_LUMINANCE_SIZE;
pi32ConfigAttribs[9] = 0;
pi32ConfigAttribs[10] = EGL_RED_SIZE;
pi32ConfigAttribs[11] = 8;
pi32ConfigAttribs[12] = EGL_GREEN_SIZE;
pi32ConfigAttribs[13] = 8;
pi32ConfigAttribs[14] = EGL_BLUE_SIZE;
pi32ConfigAttribs[15] = 8;
pi32ConfigAttribs[16] = EGL_ALPHA_SIZE;
pi32ConfigAttribs[17] = 8;
pi32ConfigAttribs[18] = EGL_DEPTH_SIZE;
pi32ConfigAttribs[19] = 8;
pi32ConfigAttribs[20] = EGL_LEVEL;
pi32ConfigAttribs[21] = 0;
pi32ConfigAttribs[22] = EGL_BUFFER_SIZE;
pi32ConfigAttribs[23] = 24;
pi32ConfigAttribs[24] = EGL_NONE;
//Step 5 - Find a config that matches all requirements.
int iConfigs;
EGLConfig eglConfig;
eglChooseConfig(eglDisplay, pi32ConfigAttribs, &eglConfig, 1, &iConfigs);
qDebug() << "egl error" << eglGetError();
if (iConfigs != 1)
{
printf("Error: eglChooseConfig(): config not found.\n");
exit(-1);
}
EGLint pbufferAttribs[5];
pbufferAttribs[0] = EGL_WIDTH;
pbufferAttribs[1] = 1920;
pbufferAttribs[2] = EGL_HEIGHT;
pbufferAttribs[3] = 1080;
pbufferAttribs[4] = EGL_NONE;
//Step 6 - Create a surface to draw to.
EGLSurface eglSurface;
eglSurface = eglCreatePbufferSurface(eglDisplay, eglConfig, pbufferAttribs);
qDebug() << "egl error" << eglGetError();
if (eglSurface == EGL_NO_SURFACE)
{
qDebug() << "surface issue";
}
//Step 7 - Create a context.
EGLContext eglContext;
eglContext = eglCreateContext(eglDisplay, eglConfig, NULL, NULL);
qDebug() << "egl error" << eglGetError();
if (eglContext == EGL_NO_CONTEXT)
{
qDebug() << "context issue";
}
//Step 8 - Bind the context to the current thread
bool result = eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);
if (!result)
{
qDebug() << "make current error" << eglGetError();
}
qDebug() << "egl error" << eglGetError();
GLuint renderBufferWidth = 1920;
GLuint renderBufferHeight = 1080;
QElapsedTimer benchmarkTimer;
int size = 4 * renderBufferHeight * renderBufferWidth;
unsigned char *data2 = new unsigned char[size];
int i = 0;
benchmarkTimer.start();
while(i<1000)
{
glClearColor(1.0,0.0,0.0,1.0);
glClear(GL_COLOR_BUFFER_BIT);
eglSwapBuffers( eglDisplay, eglSurface);
glReadPixels(0,0,renderBufferWidth,renderBufferHeight,GL_RGBA, GL_UNSIGNED_BYTE, data2);
++i;
}
qDebug() << "fps" << 1000.0*1000.0/benchmarkTimer.elapsed();
QImage saveImage(data2, renderBufferWidth, renderBufferHeight, QImage::Format_RGBA8888_Premultiplied);
saveImage.save("haha.png");
QCoreApplication a(argc, argv);
qDebug() << "done";
return a.exec();
}
- Warum nicht Sie überprüfen die
eglMakeCurrent()
Rückgabewert? - Ich überprüft und auch kontrolliert, eglGetError(), sieht alles gut aus. Ich wusste nicht, fügen Sie Sie hier als prägnant.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Gibt es ein paar Probleme in diesem code:
Den
EGL_SURFACE_TYPE
angegeben in der config-Parametern ist falsch:Zu machen, um ein PBuffer, diese muss mit dem matching-Wert:
Ist keine Größe angegeben, für den PBuffer. Während die Mann Seite deutet darauf hin, dass es legal zu erstellen PBuffer, ohne Angabe einer Größe, die Standardeinstellungen für Breite und Höhe 0 sind. Ich kann mir nicht vorstellen, dass etwas gutes passieren wird, wenn Sie versuchen zu machen, um eine Oberfläche der Größe 0 mal 0. Um eine Größe festzulegen:
Meine Antwort auf diese Frage hat die vollständige code zur Erstellung eines Kontext-und PBuffer Oberfläche für zwei verschiedene Versionen von EGL: GLES10.glGetIntegerv gibt 0 zurück, in Lollipop nur. Der code verwendet die Java-bindings, aber es sollte sich leicht anpassen lassen.
Warum Sie das tun, eglSwapBuffers vor glReadPixels?
Vermutlich eglSwapBuffers hat keine Auswirkungen auf PBufferSurface (da ist es nicht double-buffer-Oberfläche), aber wenn es ist, dass Sie versuchen würde zu Lesen, die Pixel undefiniert Puffer, mit unbestimmten Ergebnis..