2013-09-18 1 views
1

Я хочу отображать изображение yuv на устройстве iOS. Я предполагаю, что это может быть достигнуто с помощью openGL. (На самом деле, мне нужно сделать несколько таких изображений подряд)Рисование изображения YUV с использованием GLKit openGL - iOS

Я понимаю, что GLKit - это абстракция, созданная iOS, в которой есть GLKView, который будет иметь и обрабатывать буфер визуализации. В настоящее время я пытаюсь использовать GLKViewController, и обновление фрейма выполняется с желаемыми fps. Это я согласен с использованием вызова функции glClear.

Теперь задача заключается в рендеринг изображения на вид.

Существует класс GLKBaseEffect, который будет иметь основные шейдеры. Я не могу понять, какие свойства установить, поэтому я просто создаю его и вызываю prepareToDraw перед каждым рендерингом.

Существует класс для обработки текстур, GLKTextureLoader, но мне кажется, что он работает только с изображениями кварца, т. Е. Плоскость yuv420 не может быть загружена в текстуру с использованием этого класса.

// create the texture 
GLuint texture; 
glGenTextures(1, &texture); 
glBindTexture(GL_TEXTURE_2D, texture); 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, [imageNSData bytes]); 
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); 

Я использую этот код для создания текстуры и привязки его, но я действительно не знаю, что я здесь делаю. И что бы это ни было, на экране не появляется изображение, и я не знаю, что делать дальше.

Я не создал никаких шейдеров, предполагая, что у baseEffect будет что-то.

И это https://developer.apple.com/library/ios/documentation/3DDrawing/Conceptual/OpenGLES_ProgrammingGuide/WorkingwithEAGLContexts/WorkingwithEAGLContexts.html#//apple_ref/doc/uid/TP40008793-CH103-SW8 говорит мне, что мне придется использовать EAGLayer для визуализации изображений на экране.

Могу ли я использовать GLKit для рендеринга изображений? Если ДА, у нас есть какой-либо пример кода или учебник, который не использовал бы класс GLKTextureLoader (я не мог найти его)? Если нет, есть ли аналогичный учебник для рендеринга с использованием EAGLLayer (об этом я до сих пор не изучал)?

ответ

4

Похоже, вы действительно спрашиваете о нескольких различных темах здесь:

  • Как рисовать с GLKView против CAEAGLLayer
  • Как GLKBaseEffect и GLKTextureLoader вписывается в OpenGL ES рисования вообще
  • Как для рисования текстуры, если у вас есть один
  • Как визуализировать данные изображения YUV

Попробую обратиться каждый, в свою очередь ...


GLKView просто отлично для любого OpenGL ES рисования вы хотите сделать - это делает все, что старше документации вы связаны с ли (настройка framebuffers, CAEAGLLayer и т. д.) для вас, поэтому вам не нужно писать этот код. Внутри метода рисования GLKView (drawRect: или glkView:drawInRect:, в зависимости от того, рисуете ли вы подкласс или делегат), вы пишете тот же код чертежа OpenGL ES, который вы бы использовали для CAEAGLLayer (или любой другой системы).


Вы можете использовать GLKView, GLKTextureLoader и GLKBaseEffect независимо друг от друга. Если вы хотите написать свой собственный код чертежа и использовать свои собственные шейдеры, вы можете нарисовать GLKView без использования GLKBaseEffect. (Вы можете даже смешивать и сопоставлять GLKBaseEffect и свои собственные вещи, как вы видите, когда вы создаете новый проект Xcode с шаблоном игры OpenGL.) Аналогично, GLKTextureLoader загружает данные изображения и выплевывает name, которые вам понадобятся для привязки к рисунку , и вы можете использовать это независимо от того, рисуете ли вы его с помощью GLKBaseEffect.


После того, как вы получите текстуру, будь то через GLKTextureLoader или чтение/декодирование данных самостоятельно и обеспечивая его glTexImage2D, есть три основных этапа рисования с ним:

  1. Bind имя текстуры с glBindTexture.
  2. почерпните геометрию быть текстурированной (с использованием glDrawArrays, glDrawElements или аналогичным)
  3. У фрагмента шейдера, который смотрит вверх тексели и выводят цвета.

Если вы просто хотите нарисовать изображение, которое заполняет ваш вид, просто нарисуйте квадрат (два треугольника). Вот код, я использую, чтобы создать вершину объект массива с одним квад, когда я хочу сделать полноэкранный режим:

typedef struct __attribute__((packed)) { 
    GLKVector3 position; 
    GLKVector2 texcoord; 
} Vertex; 

static Vertex vertexData[] = { 
    {{-1.0f, 1.0f, -1.0f}, {0.0f, 0.0f}}, 
    {{-1.0f, -1.0f, -1.0f}, {0.0f, 1.0f}}, 
    {{ 1.0f, 1.0f, -1.0f}, {1.0f, 0.0f}}, 
    {{ 1.0f, -1.0f, -1.0f}, {1.0f, 1.0f}}, 
}; 

glGenVertexArraysOES(1, &_vertexArray); 
glBindVertexArrayOES(_vertexArray); 

glGenBuffers(1, &_vertexBuffer); 
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); 
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW); 

glEnableVertexAttribArray(GLKVertexAttribPosition); 
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid *)offsetof(Vertex, position)); 
glEnableVertexAttribArray(GLKVertexAttribTexCoord0); 
glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid *)offsetof(Vertex, texcoord)); 
glBindVertexArrayOES(0); 

Затем, чтобы сделать это:

glBindVertexArrayOES(_vertexArray); 
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 

Это просто геометрия волочения части. Объедините это с GLKBaseEffect, чье свойство transform является преобразованием идентичности по умолчанию, а его свойство texture2d0 настроено с помощью name текстуры, загруженной через , или другими способами - и вы получите рекламный щит с заполнением с вашей текстурой на нем.

И, наконец, часть YUV ... для которой я буду в основном плутать. Где вы получаете данные текстуры YUV? Если это с камеры устройства, вы должны посмотреть на CVOpenGLESTexture/CVOpenGLESTextureCache, как указано this answer. Независимо от того, вы должны иметь возможность обрабатывать текстуры YUV, используя расширение APPLE_rgb_422, как описано в this answer. Вы также можете заглянуть в this answer для некоторой помощи в написании фрагментарных шейдеров для обработки YUV в RGB на лету.

+0

Спасибо за ответ, это отличная помощь. О части yuv, действительно ли нам нужно преобразовать ее в данные rgb, прежде чем отправлять ее для рендеринга? Не существует ли метода, с помощью которого мы можем просто передать буфер yuv в openGL framework, и он обрабатывает само преобразование? И что я получаю, мне нужно создать прямоугольник с использованием вершинного шейдера сначала, а затем изображение будет отображено в этой области, правильно ли? – neeraj

+1

Все пиксельные данные должны быть RGB в конечном итоге - экран является устройством RGB! Насколько мне известно, нет способа получить преобразование YUV в RGB, выполненное для вас в текстуре OpenGL, но ваш шейдер фрагментов может сделать преобразование в последний возможный момент, как показано в ['GLCameraRipple'] (https://developer.apple.com/library/ios/samplecode/GLCameraRipple/Introduction/Intro.html) пример кода. – rickster

+0

да. Это то, что я только что скачал. Думаю, теперь я пойму этот подход, спасибо за помощь. – neeraj