6

所以我已经设置了 CVPixelBuffer,并在 iOS 上成功地将它们绑定到 OpenGL FBO。但是现在尝试在 OSX 上做同样的事情让我陷入了困境。

来自 CVOpenGLTextureCacheCreateTextureFromImage 的纹理返回为 GL_TEXTURE_RECTANGLE 而不是 GL_TEXTURE_2D 目标。

我找到了 kCVOpenGLBufferTarget 键,但它似乎应该与 CVOpenGLBufferCreate 而不是 CVPixelBufferCreate 一起使用。

甚至有可能在 OSX 上使用 CVPixelBufferCreate 获得 GL_TEXTURE_2D 目标纹理,如果可以的话怎么做?

FWIW CV PBO 设置列表:

NSDictionary *bufferAttributes = @{ (__bridge NSString *)kCVPixelBufferPixelFormatTypeKey : @(kCVPixelFormatType_32BGRA), (__bridge NSString *)kCVPixelBufferWidthKey : @(size.width), (__bridge NSString *)kCVPixelBufferHeightKey : @(size.height), (__bridge NSString *)kCVPixelBufferIOSurfacePropertiesKey : @{ } };

if (pool)
{
    error = CVPixelBufferPoolCreatePixelBuffer(kCFAllocatorDefault, pool, &renderTarget);
}
else
{
    error = CVPixelBufferCreate(kCFAllocatorDefault, (NSUInteger)size.width, (NSUInteger)size.height, kCVPixelFormatType_32BGRA, (__bridge CFDictionaryRef)bufferAttributes, &renderTarget);
}

ZAssert(!error, @"Couldn't create pixel buffer");

error = CVOpenGLTextureCacheCreate(kCFAllocatorDefault, NULL, [[NSOpenGLContext context] CGLContextObj], [[NSOpenGLContext format] CGLPixelFormatObj], NULL, &textureCache);
ZAssert(!error, @"Could not create texture cache.");

error = CVOpenGLTextureCacheCreateTextureFromImage(kCFAllocatorDefault, textureCache, renderTarget, NULL, &renderTexture);
ZAssert(!error, @"Couldn't create a texture from cache.");

GLuint reference = CVOpenGLTextureGetName(renderTexture);
GLenum target = CVOpenGLTextureGetTarget(renderTexture);

更新:我已经能够成功使用生成的 GL_TEXTURE_RECTANGLE 纹理。但是,这会导致着色器在 iOS 和 OSX 之间的兼容性方面出现很多问题。无论如何,我宁愿继续使用归一化纹理坐标。

如果无法以这种方式直接从 CVPixelBuffer 获取 GL_TEXTURE_2D 纹理,是否可以创建一个 CVOpenGLBuffer 并附加一个 CVPixelBuffer 来提取像素数据?

4

2 回答 2

2

刚刚遇到这个,即使它很旧,我也会回答它,以防其他人遇到它。

iOS 使用 OpenGL ES(最初是 2.0,然后是 3.0)。OS X 使用常规的旧(非 ES)OpenGL,可选择核心配置文件(仅限 3.0+)或兼容性配置文件(最高 3.2)。

这里的区别在于OpenGL(非ES)是很久以前设计的,当时对纹理大小有很多限制。随着卡片解除了这些限制,添加了扩展,包括 GL_TEXTURE_RECTANGLE。现在,任何 GPU 支持任何大小的纹理都没什么大不了的,但出于 API 兼容性的原因,它们无法真正修复 OpenGL。由于OpenGL ES 在技术上是一个并行但独立的API,它是最近才设计的,他们能够从一开始就纠正这个问题(即他们永远不必担心破坏旧的东西)。所以对于 OpenGL ES,他们从来没有定义过 GL_TEXTURE_RECTANGLE,他们只是定义了 GL_TEXTURE_2D 没有大小限制。

Short answer - OS X uses Desktop OpenGL, which for legacy compatibility reasons still treats rectangle textures separately, while iOS uses OpenGL ES, which places no size restrictions on GL_TEXTURE_2D, and so never offered a GL_TEXTURE_RECTANGLE at all. Thus, on OS X, CoreVideo produces GL_TEXTURE_RECTANGLE objects, because GL_TEXTURE_2D would waste a lot of memory, while on iOS, it produces GL_TEXTURE_2D objects because GL_TEXTURE_RECTANGLE doesn't exist, nor is it necessary.

It's an unfortunate incompatibility between OpenGL and OpenGL ES, but it is what it is and there's nothing to be done but code around it. Or, now, you can (and probably should consider) moving on to Metal.

于 2017-03-07T20:01:07.253 回答
1

因为这似乎一直悬而未决并且是我最近处理的事情:不,GL_TEXTURE_RECTANGLE似乎是唯一的用例。要获得一个GL_TEXTURE_2D,你将不得不渲染到纹理。

于 2015-09-28T18:30:31.907 回答