用于FBO渲染的OpenGL

用于FBO渲染的OpenGL

本文介绍了用于FBO渲染的OpenGL ES2.0屏幕外上下文的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用FBO进行屏幕外渲染(在没有任何WS的控制台环境中).我知道有必要创建一个OpenGL上下文,并且至少要为任何操作创建一个虚拟窗口,因此我进行了以下初始化:

I would like to do offscreen rendering (in console environment without any WS) with FBOs.I know that it is necessary to create an OpenGL context, and at least a dummy window for any operation, therefore I did the following initialization:

// 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 WORKS,但如果我将此调用传递给真正的X11window本机窗口处理程序,它将起作用(这种情况下,我可以读取有效的渲染图像也)

This type of initialization works on the target system, but if I draw something into the FBO, and after read it back (getReadPixels) always only get a black image.I have tried the same code above X11, where it (already) fails on eglCreateWindowSurface call with error: EGL_BAD_NATIVE_WINDOW WORKS, BUT it WORKS if I pass to this call a real X11window native window handler (This case I can read back the valid rendered image also)

请向我说明我需要使用哪种类型的表面进行FBO渲染?还是我做错了什么?

Please clarify me about what type of surface should I need to use for FBO rendering??or what do I do wrong??

其余的绘图代码: //初始化并启动opengl es shanders Shaders_Init();

The rest of the drawing code: //init and 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);

提前谢谢!!!!问候,格萨

THANKS in advance!!!!!Regards,Geza

推荐答案

解决方案如下(无错误处理):

The solution was the following (without error handling):

    #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);

这篇关于用于FBO渲染的OpenGL ES2.0屏幕外上下文的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-23 12:56