2012-09-30 43 views
7

我想用FBO做離線渲染(在沒有任何WS的控制檯環境中)。 我知道,有必要建立一個OpenGL上下文,並至少在任何操作的虛擬窗口,所以我做了以下的初始化:FBO渲染的OpenGL ES2.0離屏上下文

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

// Step 2 - Initialize EGL. 
EGLint iMajorVersion, iMinorVersion; 
if (!eglInitialize(eglDisplay, &iMajorVersion, &iMinorVersion)) 
{ 
    printf("Error: eglInitialize() failed.\n"); 
    goto cleanup; 
} 

// Step 3 - Make OpenGL ES the current API. 
eglBindAPI(EGL_OPENGL_ES_API); 
if (!TestEGLError("eglBindAPI")) 
{ 
    goto cleanup; 
} 

// 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; 
if (!eglChooseConfig(eglDisplay, pi32ConfigAttribs, &eglConfig, 1, &iConfigs) || (iConfigs != 1)) 
{ 
    printf("Error: eglChooseConfig() failed.\n"); 
    goto cleanup; 
} 

// Step 6 - Create a surface to draw to. 
EGLSurface eglSurface; 
eglSurface = eglCreateWindowSurface(eglDisplay, eglConfig, (EGLNativeWindowType)NULL, NULL); 
if (!TestEGLError("eglCreateWindowSurface")) goto cleanup; 

// Step 7 - Create a context. 
eglContext = eglCreateContext(eglDisplay, eglConfig, NULL, ai32ContextAttribs); 
if (!TestEGLError("eglCreateContext")) goto cleanup; 

// Step 8 - Bind the context to the current thread 
eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext); 
if (!TestEGLError("eglMakeCurrent")) goto cleanup; 

這種類型的初始化工作在目標系統上,但如果我在FBO中繪製一些東西,讀完後(getReadPixels)總是隻能得到黑色的圖像。 我已經嘗試了上面X11的相同的代碼,它已經失敗eglCreateWindowSurface調用錯誤:EGL_BAD_NATIVE_WINDOW工作,但它工作,如果我傳遞給這個調用一個真正的X11window本地窗口處理程序(這種情況下,我可以回讀有效呈現圖像也)

請澄清我需要什麼類型的表面應用於FBO渲染? 或我做錯了什麼?

其餘的繪圖代碼: // init和start opengl es shanders Shaders_Init();

{ 
    // 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); 

    // 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"); 
    } 
} 





// Sets the clear color. 
// The colours are passed per channel (red,green,blue,alpha) as float values from 0.0 to 1.0 
glClearColor(0.6f, 0.8f, 1.0f, 1.0f); // clear blue 

// We're going to draw a triangle to the screen so create a vertex buffer object for our triangle 
{ 
    // Interleaved vertex data 
    GLfloat afVertices[] = { -0.4f,-0.4f,0.0f, // Position 
          0.4f ,-0.4f,0.0f, 
          0.0f ,0.4f ,0.0f}; 
    // Generate the vertex buffer object (VBO) 
    glGenBuffers(1, &ui32Vbo); 

    // Bind the VBO so we can fill it with data 
    glBindBuffer(GL_ARRAY_BUFFER, ui32Vbo); 

    // Set the buffer's data 
    unsigned int uiSize = 3 * (sizeof(GLfloat) * 3); // Calc afVertices size (3 vertices * stride (3 GLfloats per vertex)) 
    glBufferData(GL_ARRAY_BUFFER, uiSize, afVertices, GL_STATIC_DRAW); 
} 

// Draw a triangle 
{ 
    glClear(GL_COLOR_BUFFER_BIT); 
    if (!TestEGLError("glClear")) goto cleanup; 



    // First gets the location of that variable in the shader using its name 
    int i32Location = glGetUniformLocation(uiProgramObject, "myPMVMatrix"); 

    // Then passes the matrix to that variable 
    glUniformMatrix4fv(i32Location, 1, GL_FALSE, pfIdentity); 

    /* 
     Enable the custom vertex attribute at index VERTEX_ARRAY. 
     We previously binded that index to the variable in our shader "vec4 MyVertex;" 
    */ 
    glEnableVertexAttribArray(VERTEX_ARRAY); 

    // Sets the vertex data to this attribute index 
    glVertexAttribPointer(VERTEX_ARRAY, 3, GL_FLOAT, GL_FALSE, 0, 0); 

    /* 
     Draws a non-indexed triangle array from the pointers previously given. 
     This function allows the use of other primitive types : triangle strips, lines, ... 
     For indexed geometry, use the function glDrawElements() with an index list. 
    */ 
    glDrawArrays(GL_TRIANGLES, 0, 3); 
    if (!TestEGLError("glDrawArrays")) goto cleanup; 

     // get the image data 
     long imageSize = x * y * 3; 
     unsigned char *data = new unsigned char[imageSize]; 
     glReadPixels(0,0,x,y,GL_RGB,GL_UNSIGNED_BYTE,data); 

在此先感謝!!!!! 問候, 格扎

回答

2

將溶液以下(不含錯誤處理):

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

// Step 1 - Get the default display. 
    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; 
    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. 
    #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); 
+0

其中eglSurface和eglContext之間的一個應該被首先創建? – chengpei

+1

你能解釋你的第一個實現有什麼問題嗎?我看不出有什麼區別。 –