OpenglES Framebuffer Object learning summary and method of reading its ColorAttachment

  1. The Framebuffer Object itself has no actual memory, it can be understood as a memory manager (manager) . The memory it manages is the attachments bound to the Framebuffer Object—color attachments, depth attachment, stencil attachment, such as texture, renderbufer object. The binding accessory has the actual memory.
    A better diagram is as follows1 :

Insert picture description here

  1. It should be emphasized that a subtext given in the above picture is: color attachments can only be bound to textture object, depth attachment and stencil attachment can only be bound to renderbuffer object.
    This subtext is wrong. Color attachments, depth attachment, and stencil attachment can be bound to both texture object and renderbuffer object. Use
    in GraphicBuffer: the method of creating GraphicBuffer directly through GraphicBuffer handle and directly rendering to GraphicBuffer introduces how to bind renderbuffer object to color attachments

  2. The default Framebuffer Object of OpenGL ES (ID is 0), its color attachments, depth attachment, stencil attachment are created by openg es itself, and its color attachments support double buffering mechanism ( the color attachments are created by GraphicBuffer from Surface::dequeue of , specifically Texture or renderBuffer, this can not be determined), and its size is equal to the size of EGLSurface.

  3. When you create a FrameBuffer Object by yourself, the size of the attached attachment is arbitrary, even larger than the size of EGLSurface , and you can adjust the size of glViewport to adjust the range of rendering. OpenGL es rendering operations will directly affect the attached accessories.

  4. Framebuffer Object has certain requirements for the format of color attachments, depth attachment and stencil attachment.
    The formats currently supported by color attachments are:

    Internal Format Red Bits Green Bits Blue Bits Alpha Bits
    GL_R8 8
    GL_R8UI ui8
    GL_R8I i8
    GL_R16UI ui16
    GL_R16I I16
    GL_R32UI ui32
    GL_R32I i32
    GL_RG8 8 8
    GL_RG8UI ui8 ui8
    GL_RG8I i8 i8
    GL_RG16UI ui16 ui16
    GL_RG16I I16 I16
    GL_RG32UI ui32 ui32
    GL_RG32I i32 i32
    GL_RGB8 8 8 8
    GL_RGB565 5 6 5
    GL_RGBA8 8 8 8 8
    GL_SRGB8_ALPHA8 8 8 8 8
    GL_RGB5_A1 5 5 5 1
    GL_RGBA4 4 4 4 4
    GL_RGB10_A2 10 10 10 2
    GL_RGBA8UI ui8 ui8 ui8 ui8
    GL_RGBA8I i8 i8 i8 i8
    GL_RGB10_A2UI ui10 ui10 ui10 UI2
    GL_RGBA16UI ui16 ui16 ui16 ui16
    GL_RGBA16I I16 I16 I16 I16
    GL_RGBA32UI ui32 ui32 ui32 ui32
    GL_RGBA32I i32 i32 i32 i32

depth attachment, stencil attachment supports the following formats:

Internal Format Depth Bits Stencil Bits
GL_DEPTH_COMPONENT16 16
GL_DEPTH_COMPONENT24 24
GL_DEPTH_COMPONENT32F f32
GL_DEPTH24_STENCIL8 24 8
GL_DEPTH32F_STENCIL8 f32 8
GL_STENCIL_INDEX8 8
  1. opengl es rendering drawn by the region is void glViewport(GLint x, GLint y, GLsizei w, GLsizei h)to specify.
    Coordinates (x, y) correspond to (-1, -1) of NDC coordinates.
    Coordinates (x+w, y+h) correspond to (1, 1) of NDC coordinates.
    The range set by glViewport is arbitrary, even larger than the size of the FrameBuffer Object binding attachment ( when binding the default FrameBuffer Object, it can be larger than EGLSurface; when binding a custom FrameBuffer Object, it can be larger than The size of the attached attachments is even larger. For example, when the color attachments is texture, it can be larger than the size of the texture), but only the effective range (the part where the FrameBuffer Object binding attachment and the viewport overlap) can be rendered .

  2. Method of reading color attachments 2


void readFrameBufferColorAttachment0()
{
    
    
    GLuint framebuffer = 0;
    glGenFramebuffers ( 1, &framebuffer );
    GLint defaultFramebuffer = 0;
    glGetIntegerv ( GL_FRAMEBUFFER_BINDING, &defaultFramebuffer );
    glBindFramebuffer ( GL_FRAMEBUFFER, framebuffer );
    //绑定textureId到GL_COLOR_ATTACHMENT0
    glFramebufferTexture2D ( GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 
                            textureId, 0 );
   //设置读取GL_COLOR_ATTACHMENT0上绑定的textureId内容
    glReadBuffer ( GL_COLOR_ATTACHMENT0 );
    GLint readType, readFormat;
    //每个像素占用多少字节
    unsigned int bytesPerPixel = 0;
    GLubyte *pixels;
    glGetIntegerv ( GL_IMPLEMENTATION_COLOR_READ_FORMAT, &readFormat );
    glGetIntegerv ( GL_IMPLEMENTATION_COLOR_READ_TYPE, &readType );
    //可以查找第5小节中的表格获取该值
    if(readFormat==GL_RGBA8){
    
    
        bytesPerPixel = 4}
    pixels = ( GLubyte* ) malloc( width * height * bytesPerPixel );
    //dump parameters to file_*.txt
    char buf[256];
    memset(buf, 0, sizeof(buf));
    snprintf(buf, sizeof(buf), "/sdcard/dump/file%dX%d.txt",width ,height );
    FILE* fp   = fopen (buf, "w+");
    fprintf(fp, "width %d,height %d",width ,height );
    fclose(fp);
    //dump raw data to frame_*.raw
    dumpImage(pixels,0,width ,height,bytesPerPixel  )
    glReadPixels ( 0, 0, width, height, readFormat, readType, pixels );
    glBindFramebuffer ( GL_FRAMEBUFFER, defaultFramebuffer );
    glDeleteFramebuffers(1,framebuffer);
}
void dumpImage(unsigned char* imagedata,
        uint32_t frameid, uint32_t width, uint32_t height, uint32_t bytesPerPixel) 
{
    
    
    char buf[256];
    memset(buf, 0, sizeof(buf));
    snprintf(buf, sizeof(buf), "/sdcard/dump/frame_%dX%d_%d.raw",
             width,height,frameid);

    uint32_t ImageSize = width*height*bytesPerPixel;

#if 1
    FILE* fp = fopen(buf, "w");
    __android_log_print(ANDROID_LOG_ERROR, "dumpImage", "fp=%p,[wxhxb]=[%d,%d,%d]",fp,width,height,bytesPerPixel);

    if (fp)
    {
    
    
        fwrite(imagedata, ImageSize, 1, fp);
        fclose(fp);
    }
#else
    int file_fd = open(buf, O_RDWR | O_CREAT, 0644);
    __android_log_print(ANDROID_LOG_ERROR, "dumpImage", "file_fd=%d,[wxhxb]=[%d,%d,%d]",file_fd,width,height,bytesPerPixel);

    if (file_fd >= 0)
    {
    
    
        ssize_t written_image    = write(file_fd, imagedata, ImageSize);
        close(file_fd);
    }
#endif
}
  1. eglSwapBuffers (EGLDisplay dpy, EGLSurface surface) exchanges the front and back rendering buffers of the surface. It will return the GraphicBuffer being used
    through Surface::queueBuffer and then retrieve a new frame of GraphicBuffer through Surface::dequeueBuffer.
    If the currently used Framebuffer 0 is used, the colorAttachments binding is the RenderBuffer or texture formed by the GraphicBuffer from Surface::dequeueBuffer. Then OpenglES just renders the drawing to this GraphicBuffer. Through the queueBuffer, the rendering result will be submitted to Surface for display (the premise is that the Surfac corresponds to the Layer in SurfaceFlinger, if it is not, it will not be displayed). If the current Framebuffer is not 0, then the OpenglES rendering and drawing are on the Attachments bound to the Framebuffer, and no subsequent operations are performed on the GraphicBuffer. eglSwapBuffers only interacts with the front and back rendering buffers of the lower surface. At this time, the Surface will display a black screen.

  1. Picture from http://www.cppblog.com/init/archive/2012/02/16/165778.aspx ↩︎

  2. Reference article glReadPixels reads video memory data and saves the image ↩︎

Guess you like

Origin blog.csdn.net/u010116586/article/details/104485515