Opengl ES之PBO

Posted FlyerGo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Opengl ES之PBO相关的知识,希望对你有一定的参考价值。

叨叨一句几句

关于Opengl的系列已经有较长的一段时间没有更新了,然而这个系列还远没有到完毕地步,后续至少还有关于Opengl矩阵变换、YUV与RGB互转、Opengl水印贴图、Opengl转场动画等主题文章。

断更的主要原因如果给自己找个借口的话可以说是工作比价忙,如果说的比较现实一点就是自己懒且没啥动力,毕竟写技术博客文章是一件时间成本投入很大,而收益产出极小的一件事情…

进入正题…

了解过Opengl的童鞋们都知道,在Opengl中存在这个各种O,例如VAO、VBO、FBO等,而出现各种各样的O一般都是因为考虑到性能的原因。

今天我们要介绍的主角PBO,它和之前我们介绍VBO很像,了解完PBO之后童鞋们可以对比一下PBO与VBO的差异点。

下面从两个方面介绍PBO,什么是PBO以及如何使用PBO。

更多关于音视频、FFmpeg、Opengl、C++的原创文章请关注微信公众号:思想觉悟

什么是PBO

PBO(Pixel Buffer Object像素缓冲对象)。在了解什么是PBO之前,我们先来了解一下为什么会出现PBO这么一个东西?

所谓存在即合理,用发展的眼光看问题,PBO的出现肯定是为了替代某种东西,或者是为了解决某个问题。

在使用Opengl的时候经常需要在GPU和CPU之间传递数据,例如在使用Opengl将YUV数据转换成RGB数据时就需要先将YUV数据上传到GPU,一般使用函数glTexImage2D,处理完毕后再将RGB结果数据读取到CPU,
这时使用函数glReadPixels即可

有没有人有 PBO + SDL2.0 + OpenGL 的例子

【中文标题】有没有人有 PBO + SDL2.0 + OpenGL 的例子【英文标题】:does anyone have an example of PBO + SDL2.0 + OpenGL 【发布时间】:2013-11-14 11:58:57 【问题描述】:

有人有 PBO(像素缓冲区对象)+ SDL2.0(简单 DirectMedia 层)+ OpenGL 的工作示例吗?

原因是通过 GLGetPixels 获得异步 GPU -> CPU 下载,从而获得性能提升。

这是我的尝试。 use_pbo = false 或 true 根本没有测量差异。而且我之前在同一台机器上使用过带有 GLUT 的 PBO,所以我知道我的硬件支持它。

我看了很多 http://www.songho.ca/opengl/gl_pbo.html 教程,但没有发现我做错了什么。

bool use_pbo = true; //remember to wait a bit for fps to pick up speed

if(SDL_Init(SDL_INIT_EVENTS) != 0) throw "SDL_Init";

SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

sdl_window = SDL_CreateWindow("", 10, 20, window_width, window_height, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);

sdl_gl_context = SDL_GL_CreateContext(sdl_window);
SDL_GL_MakeCurrent(sdl_window, sdl_gl_context);

vertical_sync(false);


    glGenBuffers(2, pbos);
    glBindBuffer(GL_PIXEL_PACK_BUFFER, pbos[0]);
    glBufferData(GL_PIXEL_PACK_BUFFER, pbo_width*pbo_height*4, 0, GL_STREAM_READ);

    glBindBuffer(GL_PIXEL_PACK_BUFFER, pbos[1]);
    glBufferData(GL_PIXEL_PACK_BUFFER, pbo_width*pbo_height*4, 0, GL_STREAM_READ);

    glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);


//render to default frame buffer

    glDrawBuffer(GL_BACK);

    glClearColor(0.1, 0.2, 0.3, 0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glEnable(GL_BLEND);
    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

    glUseProgram(simple_shader);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, transparent_texture);

    glBegin(GL_TRIANGLE_STRIP);
    //textcoord, color, position
    glVertexAttrib2f(2, 0, 1); glVertexAttrib4f(1, 1, 0, 0, 1); glVertexAttrib2f(0, -1, -1); //bottom left
    glVertexAttrib2f(2, 1, 1); glVertexAttrib4f(1, 0, 1, 0, 1); glVertexAttrib2f(0, +1, -1); //bottom right
    glVertexAttrib2f(2, 0, 0); glVertexAttrib4f(1, 0, 0, 1, 1); glVertexAttrib2f(0, -1, +1); //top left
    glVertexAttrib2f(2, 1, 0); glVertexAttrib4f(1, 1, 1, 0, 1); glVertexAttrib2f(0, +1, +1); //top right
    glEnd();

    glBindTexture(GL_TEXTURE_2D, 0);

    glUseProgram(0);

    glDisable(GL_BLEND);

    while(true)
    
        if(use_pbo)
        
            glBindBuffer(GL_PIXEL_PACK_BUFFER, pbos[1]);
            GLvoid* map_buffer_data = glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);

            if(map_buffer_data)
            
                //glRasterPos2i(-1, -1); //default, left bottom
                glRasterPos2i(0, -1);
                glDrawPixels(pbo_width, pbo_height, GL_BGRA, GL_UNSIGNED_BYTE, map_buffer_data);
                glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
            

            glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
        
        else
               
            glRasterPos2i(0, -1); //right bottom
            glDrawPixels(pbo_width, pbo_height, GL_BGRA, GL_UNSIGNED_BYTE, t.c);
        
    


SDL_GL_SwapWindow(sdl_window);

//cycle buffers

    GLuint t = pbos[1];
    pbos[1] = pbos[0];
    pbos[0] = t;

【问题讨论】:

【参考方案1】:

尝试将 PBO 绑定到您的纹理

GL_PIXEL_UNPACK_BUFFER 用于将像素数据传递到 OpenGL GL_PIXEL_PACK_BUFFER 用于从 OpenGL 检索像素数据

你也应该用glTexImage2D定义纹理图像

如果非零命名缓冲区对象绑定到 GL_PIXEL_UNPACK_BUFFER 目标 (请参阅 glBindBuffer)而纹理图像是 指定时,数据被视为缓冲区对象数据存储中的字节偏移量。

【讨论】:

以上是关于Opengl ES之PBO的主要内容,如果未能解决你的问题,请参考以下文章

Android OpenGL ES 学习 –渲染YUV视频以及视频抖音特效

Android OpenGL ES 学习 –渲染YUV视频以及视频抖音特效

支持 PBO 的高级 OpenGL 库

一看就懂的OpenGL ES教程——仿抖音滤镜的各种奇技淫巧

一看就懂的OpenGL ES教程——仿抖音滤镜的各种奇技淫巧

[转]OpenGL 使用 PBO 高速复制屏幕图像到内存或者纹理中