我使用的是 iOS 6(如果您愿意的话,我也使用 7)和 GL ES 2.0。CAEAGLLayer 的想法是拥有一个基于着色器的动态过滤器链,用于处理其内容属性并显示最终结果。过滤器可以在链中的任何点添加/删除。
到目前为止,我想出了一个实现,但我想知道是否有更好的方法来解决它。我的实现大致是这样的:
- 具体过滤器继承自的基本过滤器类,为它们实现的任何过滤器/成像创建着色器程序(顶点/片段组合)。
实现过滤器链并添加过滤器的 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
到目前为止,这种方法似乎有效,但我想知道一些事情:
实现添加/删除过滤器的最佳方法:
添加和删除程序似乎是目前最合乎逻辑的方法。然而,这意味着每个插件一个程序,并在渲染时在所有这些程序之间切换。我想知道这些其他方法如何比较:
- 附加/分离着色器对并重新链接单个复合程序,而不是添加/删除程序。OpenGL ES 2.0 编程指南说你不能这样做。但是,由于桌面 GL 允许在一个程序中使用多个着色器对象,所以我很好奇如果 ES 支持它是否会是一种更好的方法。
- 将过滤器保持为文本格式(它们的代码在除 之外的函数中),而是在每次添加/删除过滤器时将
main
它们全部编译成一个整体着色器对(当然添加)。main
实现每个过滤器缓存的最佳方法:
现在,在链中的任何点添加/删除任意数量的过滤器都需要再次运行所有程序来渲染最终图像。但是,如果我能以某种方式缓存每个过滤器的输出,那就太好了。这样,删除、添加或绕过过滤器只需要在链中的插入/删除/绕过点运行过滤器。我可以想到一种天真的方法:在每个程序传递中,将不同的纹理对象绑定到帧缓冲区GL_TEXTURE0
和GL_COLOR_ATTACHMENT0
帧缓冲区。通过这种方式,我可以保留每个过滤器的输出。但是,为每个过滤器创建新纹理、绑定和更改帧缓冲区附件似乎效率低下。