Как преобразовать существующую текстуру OpenGL в металлическую текстуру
Я работаю над разработкой некоторых плагинов для FxPlug для Motion и FCP X. В конечном счете, я бы хотел, чтобы они рендерились в металле, так как Apple осуждает OpenGL.
В настоящее время я использую CoreImage, и, хотя я смог использовать функциональность CoreImage для обработки металла вне SDK FxPlug, FxPlug предоставляет мне только рамку в качестве текстуры OpenGL. Я попытался просто передать это в фильтр CoreImage, но в итоге получаю эту ошибку:
Cannot render image (with an input GL texture) using a metal-DG context.
После небольшого исследования я обнаружил, что я могу предположительно использовать CVPixelBuffers для совместного использования текстур между ними, но после некоторой попытки написать код, использующий этот метод, я пришел к выводу, что это было задумано как способ НАПИСАТЬ (например, создать с нуля) в общий буфер, но не конвертировать между ними. Хотя это может быть неправильно, я не могу найти способ заставить существующую текстуру GL существовать в CVPixelBuffer.
TL; DR: я нашел способы получить результирующую текстуру Metal или OpenGL из CVPixelBuffer, но я не могу найти способ создать CVPixelBuffer из существующей текстуры OpenGL. Мое сердце не настроено на этот метод, так как моя конечная цель - просто конвертировать из OpenGL в Metal, а затем обратно в OpenGL (в идеале, эффективным способом).
Кто-нибудь еще нашел способ работать с FxPlug с Metal? Есть ли хороший способ конвертировать текстуру OpenGL в Metal/CVPixelBuffer?
1 ответ
Я написал FxPlug, который использует текстуры OpenGL и текстуры металла. То, что вы ищете, это IOSurface
, Это текстуры, которые можно использовать с Metal или OpenGL, хотя они имеют некоторые ограничения. Таким образом, если у вас уже есть текстура Metal или OpenGL, вы должны скопировать ее в IOSurface
использовать его с другой системой.
Чтобы создать IOSurface
Вы можете использовать CVPixelBuffer
s (включая kCVPixelBufferIOSurfacePropertiesKey) или вы можете напрямую создать его, используя IOSurface
класс, определенный в <IOSurface/IOSurfaceObjC.h>
,
Как только у вас есть IOSurface
Вы можете скопировать свою текстуру OpenGL в нее, получив текстуру OpenGL из IOSurface
с помощью CGLTexImageIOSurface2D()
(определено в <OpenGL/CGLIOSurface.h>
). Затем вы берете эту текстуру и используете ее в качестве вспомогательной текстуры для FBO. Вы можете, например, нарисовать текстурированный квад в нем, используя ввод FxTexture
в качестве текстуры. Будь уверен в звонке glFlush()
когда сделано!
Далее возьмите IOSurface
и создать MTLTexture
от этого через -[MTLDevice newTextureWithDescriptor:ioSurface:plane:]
(описано здесь). Вы хотите создать выход IOSurface
привлечь, а также создать MTLTexture
от него. Сделайте ваш металлический рендеринг на выходе MTLTexture
, Далее возьмите вывод IOSurface
и создать из него текстуру OpenGL через CGLTexImageIOSurface2D()
, Теперь скопируйте эту текстуру OpenGL в выходной FxTexture, используя ее как основу FBO с текстурной поддержкой или любым другим методом, который вы предпочитаете.
Как вы можете видеть, недостатком этого является то, что для каждого рендера требуется 2 копии - 1 вход в IOSurface
и 1 выход IOSurface
в выходную текстуру приложение дает вам. Другим недостатком является то, что это, вероятно, спорный вопрос, поскольку Apple публично объявила о прекращении поддержки OpenGL и, вероятно, уже работает над решением на основе Metal. Это может быть дополнительная работа, чтобы сделать все это самостоятельно. (Хотя плюс в том, что вы можете использовать этот же код в других хост-приложениях, которые поддерживают только OpenGL.)