如何将现有的OpenGL纹理转换为金属纹理

时间:2018-12-18 08:42:06

标签: opengl metal core-image cvpixelbuffer

我正在开发一些用于Motion和FCP X的FxPlug插件。最终,我想让它们在Metal中渲染,因为苹果将弃用OpenGL。

我当前正在使用CoreImage,虽然我已经能够使用CoreImage功能在FxPlug SDK之外进行金属处理,但FxPlug仅向我提供了作为OpenGL纹理的帧。我尝试将其传递到CoreImage过滤器中,但最终遇到此错误:

Cannot render image (with an input GL texture) using a metal-DG context.

经过一段research之后,我发现我可以使用CVPixelBuffers在两者之间共享纹理,但是在尝试使用这种方法编写代码一段时间之后,我开始相信旨在作为一种方法(例如,从头开始创建)写入共享缓冲区,但不能在它们之间进行转换。尽管这可能是不正确的,但我找不到找到将现有GL纹理存在于CVPixelBuffer中的方法。

TL; DR:我已经找到了从CVPixelBuffer中获得金属或OpenGL纹理的方法,但是我找不到从现有OpenGL纹理中创建CVPixelBuffer的方法。我的内心并不喜欢这种方法,因为我的最终目标是简单地从OpenGL转换为Metal,然后再转换回OpenGL(理想情况下以一种有效的方式)。

是否还有其他人找到了将FxPlug与Metal结合使用的方法?是否有从OpenGL纹理转换为Metal / CVPixelBuffer的好方法?

1 个答案:

答案 0 :(得分:1)

我编写了同时使用OpenGL纹理和Metal纹理的FxPlug。您要寻找的是IOSurface。它们是可以与Metal或OpenGL一起使用的纹理,尽管它们有一些限制。这样,如果您已经具有“金属”或OpenGL纹理,则必须将其复制到IOSurface中才能在其他系统上使用。

要创建IOSurface,您可以使用CVPixelBuffer(包括kCVPixelBufferIOSurfacePropertiesKey),也可以使用{{1 }}。

一旦有了IOSurface,就可以通过<IOSurface/IOSurfaceObjC.h>(在IOSurface中定义)从IOSurface获取OpenGL纹理,从而将OpenGL纹理复制到其中。然后,您可以获取该纹理并将其用作FBO的背景纹理。例如,您可以使用输入CGLTexImageIOSurface2D()作为纹理在其中绘制纹理四边形。完成后,请确保致电<OpenGL/CGLIOSurface.h>

接下来,使用FxTexture并通过glFlush()IOSurface创建MTLTexture(描述为here)。您将要创建一个输出-[MTLDevice newTextureWithDescriptor:ioSurface:plane:]并从中创建一个IOSurface。将您的Metal渲染到输出MTLTexture中。接下来,获取输出MTLTexture,并通过IOSurface从中创建一个OpenGL纹理。现在,通过将OpenGL纹理用作纹理支持的FBO的后盾或您喜欢的任何其他方法,将其复制到输出FxTexture中。

如您所见,这样做的缺点是每个渲染都需要2个副本-1个输入CGLTexImageIOSurface2D()的输入和1个输出IOSurface输入应用程序给您的输出纹理的副本。另一个不利之处是,这可能是没有实际意义的,因为苹果公司公开宣布他们将停止对OpenGL的支持,他们可能已经在开发基于Metal的解决方案。自己动手做可能是额外的工作。 (尽管好处是您可以在仅支持OpenGL的其他主机应用程序中使用相同的代码。)