OpenGL ES 2d рендеринг в изображение
Мне нужно написать OpenGL ES 2-мерный рендерер на iOS. Он должен нарисовать некоторые примитивы, такие как линии и многоугольники, в 2D-изображение (это будет рендеринг векторной карты). Каким способом лучше всего получить изображение из контекста OpenGL в этой задаче? Я имею в виду, я должен визуализировать эти примитивы в текстуру, а затем получить изображение из нее, или как? Также было бы хорошо, если бы кто-то давал примеры или учебные пособия, которые выглядят так, как мне нужно (2d GL рендеринг в изображение). Заранее спасибо!
1 ответ
Если вам нужно визуализировать сцену OpenGL ES 2-D, а затем извлечь изображение этой сцены для использования вне OpenGL ES, у вас есть два основных варианта.
Во-первых, просто визуализировать вашу сцену и использовать glReadPixels()
чтобы получить данные RGBA для сцены и поместить их в байтовый массив, как показано ниже:
GLubyte *rawImagePixels = (GLubyte *)malloc(totalBytesForImage);
glReadPixels(0, 0, (int)currentFBOSize.width, (int)currentFBOSize.height, GL_RGBA, GL_UNSIGNED_BYTE, rawImagePixels);
// Do something with the image
free(rawImagePixels);
Второй, и гораздо более быстрый, способ сделать это состоит в том, чтобы визуализировать вашу сцену в объектно-поддерживаемый объект кадрового буфера (FBO), где текстура была предоставлена кешами текстур iOS 5.0. Я описываю этот подход в этом ответе, хотя я не показываю код для доступа к необработанным данным.
Вы делаете следующее, чтобы настроить кеш текстуры и привязать текстуру FBO:
CVReturn err = CVOpenGLESTextureCacheCreate(kCFAllocatorDefault, NULL, (__bridge void *)[[GPUImageOpenGLESContext sharedImageProcessingOpenGLESContext] context], NULL, &rawDataTextureCache);
if (err)
{
NSAssert(NO, @"Error at CVOpenGLESTextureCacheCreate %d");
}
// Code originally sourced from http://allmybrain.com/2011/12/08/rendering-to-a-texture-with-ios-5-texture-cache-api/
CFDictionaryRef empty; // empty value for attr value.
CFMutableDictionaryRef attrs;
empty = CFDictionaryCreate(kCFAllocatorDefault, // our empty IOSurface properties dictionary
NULL,
NULL,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
attrs = CFDictionaryCreateMutable(kCFAllocatorDefault,
1,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
CFDictionarySetValue(attrs,
kCVPixelBufferIOSurfacePropertiesKey,
empty);
//CVPixelBufferPoolCreatePixelBuffer (NULL, [assetWriterPixelBufferInput pixelBufferPool], &renderTarget);
CVPixelBufferCreate(kCFAllocatorDefault,
(int)imageSize.width,
(int)imageSize.height,
kCVPixelFormatType_32BGRA,
attrs,
&renderTarget);
CVOpenGLESTextureRef renderTexture;
CVOpenGLESTextureCacheCreateTextureFromImage (kCFAllocatorDefault,
rawDataTextureCache, renderTarget,
NULL, // texture attributes
GL_TEXTURE_2D,
GL_RGBA, // opengl format
(int)imageSize.width,
(int)imageSize.height,
GL_BGRA, // native iOS format
GL_UNSIGNED_BYTE,
0,
&renderTexture);
CFRelease(attrs);
CFRelease(empty);
glBindTexture(CVOpenGLESTextureGetTarget(renderTexture), CVOpenGLESTextureGetName(renderTexture));
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, CVOpenGLESTextureGetName(renderTexture), 0);
а затем вы можете просто читать непосредственно из байтов, которые поддерживают эту текстуру (в формате BGRA, а не RGBA glReadPixels()
) используя что-то вроде:
CVPixelBufferLockBaseAddress(renderTarget, 0);
_rawBytesForImage = (GLubyte *)CVPixelBufferGetBaseAddress(renderTarget);
// Do something with the bytes
CVPixelBufferUnlockBaseAddress(renderTarget, 0);
Однако, если вы просто хотите повторно использовать изображение в OpenGL ES, вам просто нужно визуализировать вашу сцену в FBO на текстурной основе, а затем использовать эту текстуру на втором уровне рендеринга.
Я показываю пример рендеринга в текстуру, а затем выполняю некоторую обработку на ней, в образце приложения CubeExample в моей среде с открытым исходным кодом GPUImage, если вы хотите увидеть это в действии.