1

我使用的是 iOS 6(如果您愿意的话,我也使用 7)和 GL ES 2.0。CAEAGLLayer 的想法是拥有一个基于着色器的动态过滤器链,用于处理其内容属性并显示最终结果。过滤器可以在链中的任何点添加/删除。

到目前为止,我想出了一个实现,但我想知道是否有更好的方法来解决它。我的实现大致是这样的:

  1. 具体过滤器继承自的基本过滤器类,为它们实现的任何过滤器/成像创建着色器程序(顶点/片段组合)。
  2. 实现过滤器链并添加过滤器的 CAEAGLLayer 子类。高级处理算法是:

     // 1 - Assume whenever the layer's content property is changed to an image, a copy of the image gets stored in a sourceImage property.
     // 2 - Assume changing the content property or adding / removing an image unit triggers this algorithm.
     // 3 - Assume the whole filter chain basically processes a quad with position and texture coordinates thru a VBO.
     // 4 - Assume all shader programs (by shader program I mean a vertex and fragment shader pair in a single program) have access to texture unit 0.
     // 5 - Assume P shader programs.
    
     load imageSource into a texture object bound to GL_TEXTURE2D and pointing to to GL_TEXTURE0
     attach bound texture object to GL_FRAMEBUFFER GL_COLOR_ATTACHMENT0 (so we are doing render-to-texture, which will be accessible to fragment shaders)
     for p = program identifier 0 up to P - 2:
        glUseProgram(p)
        glDrawArrays()
    
     attach GL_RENDERBUFFER to GL_FRAMEBUFFER GL_COLOR_ATTACHMENT0 (GL_RENDERBUFFER in turn has its storage set to the layer itself);
     p = program identifier P - 1 (last program in the chain)
     glUseProgram(p)
     glDrawArrays()
    
     present GL_RENDERBUFFER onscreen
    

到目前为止,这种方法似乎有效,但我想知道一些事情:

实现添加/删除过滤器的最佳方法:

添加和删​​除程序似乎是目前最合乎逻辑的方法。然而,这意味着每个插件一个程序,并在渲染时在所有这些程序之间切换。我想知道这些其他方法如何比较:

  1. 附加/分离着色器对并重新链接单个复合程序,而不是添加/删除程序。OpenGL ES 2.0 编程指南说你不能这样做。但是,由于桌面 GL 允许在一个程序中使用多个着色器对象,所以我很好奇如果 ES 支持它是否会是一种更好的方法。
  2. 将过滤器保持为文本格式(它们的代码在除 之外的函数中),而是在每次添加/删除过滤器时将main它们全部编译成一个整体着色器对(当然添加)。main

实现每个过滤器缓存的最佳方法:

现在,在链中的任何点添加/删除任意数量的过滤器都需要再次运行所有程序来渲染最终图像。但是,如果我能以某种方式缓存每个过滤器的输出,那就太好了。这样,删除、添加或绕过过滤器只需要在链中的插入/删除/绕过点运行过滤器。我可以想到一种天真的方法:在每个程序传递中,将不同的纹理对象绑定到帧缓冲区GL_TEXTURE0GL_COLOR_ATTACHMENT0帧缓冲区。通过这种方式,我可以保留每个过滤器的输出。但是,为每个过滤器创建新纹理、绑定和更改帧缓冲区附件似乎效率低下。

4

1 回答 1

1

关于过滤器输出缓存问题我没有太多要说的,但至于过滤器切换...... EXT_separate_shader_objects扩展旨在解决这个问题,并且它在运行 iOS 5.0 或更高版本的每台设备上都受支持。以下是简要概述:

  1. 有一个用于编译着色器程序的新便利 API,它还负责使它们“可分离”:

    _vertexProgram = glCreateShaderProgramvEXT(GL_VERTEX_SHADER, 1, &source);
    
  2. 程序管道对象管理您的程序状态并让您混合和匹配已编译的着色器:

    GLuint _ppo;
    glGenProgramPipelinesEXT(1, &_ppo);
    glBindProgramPipelineEXT(_ppo);
    glUseProgramStagesEXT(_ppo, GL_VERTEX_SHADER_BIT_EXT, _vertexProgram);
    glUseProgramStagesEXT(_ppo, GL_FRAGMENT_SHADER_BIT_EXT, _fragmentProgram);
    
  3. 混合和匹配着色器会使属性绑定变得很痛苦,因此您可以在着色器中指定(同样适用于变量):

    #extension GL_EXT_separate_shader_objects : enable
    layout(location = 0) attribute vec4 position;
    layout(location = 1) attribute vec3 normal;
    
  4. 为它们所属的着色器程序设置了制服:

    glProgramUniformMatrix3fvEXT(_vertexProgram, u_normalMatrix, 1, 0, _normalMatrix.m);
    
于 2013-09-11T22:57:25.527 回答