用GAPID窥探OpenGL数据结构

作者: 奔向火星005 | 来源:发表于2018-12-15 14:50 被阅读140次

    个人感觉,OpenGL最让人蛋疼的是,不开源!只有接口文档,却很少能详细讲解底层机制的文章出现。并且接口的设计和使用让初学者感到很费解,就算你一直在用它,经常看文档,很多地方仍然是知其然而不知其所以然。最近玩了一下一个很牛逼的工具--Graphics API Debugger,可以看到安卓上OpenGL的对象结构和状态变化,对理解OpenGL底层实现非常有帮助!

    GAPID图如下:


    左边是OpenGL命令,中间是framebuffer的预览图,右边是OpenGL的状态,我们主要看左边和右边。点击左边的某条命令,右边的state栏下的内容就会起相应的变化。

    Objects

    OpenGL中资源基本上都是以Objects(对象)形式管理的,如framebuffer buffer object(FBO), vertext buffer object(VBO)等, 可以理解为C++对象。在GAPID的右边栏下,我们可以看到有Objects项,下面就有OpenGL中所有的对象。主要研究下以下几个:

    //Objects
    GeneratedNames;  
    Buffers;               
    Framebuffers;        
    Renderbuffers;     
    TextureUnits;
    Textures;
    VertexArrays;
    

    GeneratedNames

    点击GeneratedNames项的三角形,展开如下:


    GeneratedNames实际上就是用OpenGL命令glGen~生成的名称,如看下glGenBuffer的官方API解释:

    glGenBuffers returns n buffer object names in buffers. There is no guarantee that the names form a contiguous set of integers; however, it is guaranteed that none of the returned names was in use immediately before the call to glGenBuffers.

    No buffer objects are associated with the returned buffer object names until they are first bound by calling [glBindBuffer]。

    由上可知,glGenBuffers返回n个buffer object names,注意调用glGenBuffers并不会生成buffer objects(你可以GAPID中观察,仅点击glGenBuffers命令,Objects下的Buffers数组不会增加新的元素)。

    glGenBuffer对应的就是GeneratedNames下的Buffers,你可以把它理解为一个数组,当你调用一次glGenBuffer生成一个新的name时,Buffers将新增加一个元素,如下图:


    1是返回的name的id。其他如glGenTexture, glGenFramebuffers等也同理,当你调用后,会在GeneratedNames下的Textures,Framebuffers数组中看到新添加的元素的id。

    Buffers

    接着看Objects下的Buffers,Buffers从名字看它像是一块内存数据,其实不是,它只是一个Object,但可以推测,它一定有某个成员变量的指针指向一块内存地址。

    上面也提到,glGenBuffer只是返回name,并不会生成buffer object,要生成buffer object需要调用glBindBuffer接口。我们在GAPID中点击一个glBindBuffer命令,会看到Buffers下多了一个元素,如下图:


    从图中我们也可以看到Buffer对象的数据结构,其中有id,还有刚说的Data指针,指向真正的存储数据的内存,现在它还是nil,这是因为glBindBuffer只是创建了Buffer对象,并不会为它分配内存,而分配内存需要调用glBufferData接口。在GAPID中点击一条glBufferData命令,可以看到Buffer对象的Data有了数据,如下图:


    Texture

    Texture等objects和Buffer类似,不再赘述。

    Framebuffer

    Framebuffer可以说是OpenGL中最重要的一个对象了。对于它的描述可以参看前面的文章《OpenGL文档翻译:FBO》。简而言之,你可以把它当做是一次渲染的目的地,Framebuffer对象中有多个ColorAttachments,一个DepthAttachments和一个StencilAttachments,渲染的最后步骤就是把颜色内容存到绑在ColorAttachments上的texture或renderbuffer上,把深度内容存到DepthAttachments绑定的...上,把模板内容存到StencilAttachments绑定的...上。

    在GAPID中执行glGenFramebuffers和glBindFramebuffer命令后,可以看到右边的Objects下的Framebuffers数组新增一个元素1(注意id0在OpenGL中都是保留的),如下图:


    我们可以看到一个famebuffer对象有ColorAttachments,DepthAttachments和StencilAttachments成员,可以把他们看成是数组,只是DepthAttachments和StencilAttachments的元素只有一个,而ColorAttachments可以有多个元素。

    我们把一个texture绑定到ColorAttachments上看看会发生什么,调用glFramebufferTexture2D命令,如下图:


    可以看到,把一个texture绑定到GL_COLOR_ATTACHMENT0上后,右边的ColorAttachments的0元素的Type变成了GL_TEXTURE,对比没有绑定任何texture的1元素,它的Type为GL_NONE.

    TextureUnits

    相关文章

      网友评论

        本文标题:用GAPID窥探OpenGL数据结构

        本文链接:https://www.haomeiwen.com/subject/evzohqtx.html