egl pbuffer offscreen渲染只能读回背景

时间:2015-03-06 05:27:11

标签: opengl-es glreadpixels egl off-screen

我想用pbuffer表面实现egl offscreen渲染。但我能读回的只是背景颜色。我画的东西是看不到的。

例如,如果我用蓝色清除屏幕,通过glReadPixel读回图像只是一个蓝色图像,没有其他的东西。

我的想法确实没用了

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

GLuint LoadShader(const char *shaderSrc, GLenum type)
{
    GLuint shader;
    GLint compiled;

    // Create the shader object
    shader = glCreateShader(type);
    if(shader == 0)
        return 0;
    // Load the shader source
    glShaderSource(shader, 1, &shaderSrc, NULL);

    // Compile the shader
    glCompileShader(shader);
    // Check the compile status
    glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);

    if(!compiled)
    {
        GLint infoLen = 0;
        glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);

        if(infoLen > 1)
        {
            char* infoLog = (char*)malloc(sizeof(char) * infoLen);
            glGetShaderInfoLog(shader, infoLen, NULL, infoLog);
            qDebug() << "Error compiling shader:" << infoLog;
            free(infoLog);
        }
        glDeleteShader(shader);
        return 0;
    }
    return shader;
}

int main(int argc, char *argv[])
{
    GLuint renderBufferWidth = 1920;
    GLuint renderBufferHeight = 1080;
    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[23];
    pi32ConfigAttribs[0] = EGL_SURFACE_TYPE;
    pi32ConfigAttribs[1] = EGL_PBUFFER_BIT;
    pi32ConfigAttribs[2] = EGL_RENDERABLE_TYPE;
    pi32ConfigAttribs[3] = EGL_OPENGL_ES2_BIT;
    pi32ConfigAttribs[4] = EGL_CONFORMANT;
    pi32ConfigAttribs[5] = EGL_OPENGL_ES2_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] = 5;
    pi32ConfigAttribs[12] = EGL_GREEN_SIZE;
    pi32ConfigAttribs[13] = 6;
    pi32ConfigAttribs[14] = EGL_BLUE_SIZE;
    pi32ConfigAttribs[15] = 5;
    pi32ConfigAttribs[16] = EGL_ALPHA_SIZE;
    pi32ConfigAttribs[17] = 0;
    pi32ConfigAttribs[18] = EGL_DEPTH_SIZE;
    pi32ConfigAttribs[19] = 16;
    pi32ConfigAttribs[20] = EGL_LEVEL;
    pi32ConfigAttribs[21] = 0;
    pi32ConfigAttribs[22] = 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);
    }

    EGLint pbufferAttribs[5];
    pbufferAttribs[0] = EGL_WIDTH;
    pbufferAttribs[1] = renderBufferWidth;
    pbufferAttribs[2] = EGL_HEIGHT;
    pbufferAttribs[3] = renderBufferHeight;
    pbufferAttribs[4] = EGL_NONE;

    // Step 6 - Create a surface to draw to.
    EGLSurface eglSurface;
    eglSurface = eglCreatePbufferSurface(eglDisplay, eglConfig, pbufferAttribs);

    if (eglSurface == EGL_NO_SURFACE)
    {
        qDebug() << "surface error";
        exit(1);
    }

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

    if (eglContext == EGL_NO_CONTEXT)
    {
        qDebug() << "context error";
        exit(1);
    }

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

    if (!result)
    {
        qDebug() << "make current error" << eglGetError();
    }
    GLuint programObject;

    { //init
        char* vShaderStr =
        "attribute vec4 vPosition; \n"
        "void main() \n"
        "{ \n"
        " gl_Position = vPosition; \n"
        "} \n";

        char* fShaderStr =
        "precision mediump float; \n"
        "void main() \n"
        "{ \n"
        " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); \n"
        "} \n";
        GLuint vertexShader;
        GLuint fragmentShader;
        GLint linked;

        // Load the vertex/fragment shaders
        vertexShader = LoadShader(vShaderStr, GL_VERTEX_SHADER);
        fragmentShader = LoadShader(fShaderStr, GL_FRAGMENT_SHADER);
        // Create the program object
        programObject = glCreateProgram();
        if(programObject == 0)
            return 0;
        glAttachShader(programObject, vertexShader);
        glAttachShader(programObject, fragmentShader);
        // Bind vPosition to attribute 0
        glBindAttribLocation(programObject, 0, "vPosition");
        // Link the program
        glLinkProgram(programObject);
        // Check the link status
        glGetProgramiv(programObject, GL_LINK_STATUS, &linked);
        if(!linked)
        {
            GLint infoLen = 0;
            glGetProgramiv(programObject, GL_INFO_LOG_LENGTH, &infoLen);

            if(infoLen > 1)
            {
                char* infoLog = (char*)malloc(sizeof(char) * infoLen);
                glGetProgramInfoLog(programObject, infoLen, NULL, infoLog);
                qDebug() <<"Error linking program:" << infoLog;
                free(infoLog);
            }
            glDeleteProgram(programObject);
        }
        glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
    }

    {//draw

        GLfloat vVertices[] = {0.0f, 1.5f, 0.0f,
                              -0.5f, -0.5f, 0.0f,
                               0.5f, -0.5f, 0.0f};

        // Set the viewport
        glViewport(0, 0, 1920, 1080);

        // Clear the color buffer
        glClear(GL_COLOR_BUFFER_BIT);
        // Use the program object
        glUseProgram(programObject);
        // Load the vertex data
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vVertices);
        glEnableVertexAttribArray(0);
        glDrawArrays(GL_TRIANGLES, 0, 3);
    }

    int size = 4 * renderBufferHeight * renderBufferWidth;
    unsigned char *data2 = new unsigned char[size];
    eglSwapBuffers( eglDisplay, eglSurface);
    glReadPixels(0,0,renderBufferWidth,renderBufferHeight,GL_RGBA, GL_UNSIGNED_BYTE, data2);
    qDebug() << glGetError() << eglGetError();

    QImage saveImage(data2, renderBufferWidth, renderBufferHeight, QImage::Format_RGBA8888_Premultiplied);
    saveImage.save("haha.png");
    QCoreApplication a(argc, argv);
    qDebug() << "done";
    return a.exec();
}

1 个答案:

答案 0 :(得分:0)

今天,我在装有NVIDIA显卡和专有驱动程序的机器上运行了相同的程序。

事实证明代码运行良好。

这可能是英特尔司机的错误。