Objective c 将CVOpenGLESTextureCacheCreateTextureFromImage移植到普通OpenGL ES方法
我正在开发一个应用程序,它将来自相机的视频帧输入到OpenGL ES纹理中,以创建一些效果。该应用程序使用核心视频及其许多方便的方法来创建OpenGL纹理和缓存 现在我想使用静态图像而不是视频缓冲区,我正在寻找标准的OpenGL方法来代替核心视频中可用的方法 例如:Objective c 将CVOpenGLESTextureCacheCreateTextureFromImage移植到普通OpenGL ES方法,objective-c,ios,opengl-es,core-video,Objective C,Ios,Opengl Es,Core Video,我正在开发一个应用程序,它将来自相机的视频帧输入到OpenGL ES纹理中,以创建一些效果。该应用程序使用核心视频及其许多方便的方法来创建OpenGL纹理和缓存 现在我想使用静态图像而不是视频缓冲区,我正在寻找标准的OpenGL方法来代替核心视频中可用的方法 例如: CVOpenGLESTextureRef CVOpenGLESTextureCacheRef CVOpenGLESTextureCacheCreateTextureFromImage() CVOpenGLESTextureGetT
- CVOpenGLESTextureRef李>
- CVOpenGLESTextureCacheRef李>
- CVOpenGLESTextureCacheCreateTextureFromImage()李>
- CVOpenGLESTextureGetTarget()李>
- CVOpenGLESTextureGetName()李>
- CVOpenGLESTextureCacheFlush()李>
// Y-plane
glActiveTexture(GL_TEXTURE0);
err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, _videoTextureCache, pixelBuffer, NULL, GL_TEXTURE_2D, GL_RED_EXT, _textureWidth, _textureHeight, GL_RED_EXT, GL_UNSIGNED_BYTE, 0, &_lumaTexture);
glBindTexture(CVOpenGLESTextureGetTarget(_lumaTexture), CVOpenGLESTextureGetName(_lumaTexture));
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// UV-plane
glActiveTexture(GL_TEXTURE1);
err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, _videoTextureCache, pixelBuffer, NULL, GL_TEXTURE_2D, GL_RG_EXT, _textureWidth/2, _textureHeight/2, GL_RG_EXT, GL_UNSIGNED_BYTE, 1, &_chromaTexture);
glBindTexture(CVOpenGLESTextureGetTarget(_chromaTexture), CVOpenGLESTextureGetName(_chromaTexture));
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
所以我改成这样:
这是设置
glActiveTexture(GL_TEXTURE0);
glGenTextures(1, &_lumaImageTexture);
glBindTexture(GL_TEXTURE_2D, _lumaImageTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glActiveTexture(GL_TEXTURE1);
glGenTextures(1, &_chromaImageTexture);
glBindTexture(GL_TEXTURE_2D, _chromaImageTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
下面是我如何创建它们的
// Y-plane
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, _lumaImageTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _textureWidth, _textureHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, imageData);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// UV-plane
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, _chromaImageTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _textureWidth, _textureHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, imageData);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
我想问题出在glTexImage2D函数中的一个参数中。我尝试了不同的组合,得到了不同的结果。。。但从来都不是正确的方法:)所有这些方法所做的就是为您提供一个与CVPixelBuffer相对应的OpenGL ES纹理。在iOS 5.0中引入这些之前,我们必须手动从CVPixelBuffer中获取像素数据并将其上传到纹理。对于从另一个源提取的静态图像,您将使用相同的过程(除非您想使用一些GLKit便利类) 下面是我用来上传静态图像的代码。首先,需要将图像放入BGRA字节数组:
if (shouldRedrawUsingCoreGraphics)
{
// For resized image, redraw
imageData = (GLubyte *) calloc(1, (int)pixelSizeToUseForTexture.width * (int)pixelSizeToUseForTexture.height * 4);
CGColorSpaceRef genericRGBColorspace = CGColorSpaceCreateDeviceRGB();
CGContextRef imageContext = CGBitmapContextCreate(imageData, (int)pixelSizeToUseForTexture.width, (int)pixelSizeToUseForTexture.height, 8, (int)pixelSizeToUseForTexture.width * 4, genericRGBColorspace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
CGContextDrawImage(imageContext, CGRectMake(0.0, 0.0, pixelSizeToUseForTexture.width, pixelSizeToUseForTexture.height), newImageSource);
CGContextRelease(imageContext);
CGColorSpaceRelease(genericRGBColorspace);
}
else
{
// Access the raw image bytes directly
dataFromImageDataProvider = CGDataProviderCopyData(CGImageGetDataProvider(newImageSource));
imageData = (GLubyte *)CFDataGetBytePtr(dataFromImageDataProvider);
}
在上面的代码中,newImageSource
是一个CGImageRef。这显示了用于提取位图数据的两种不同路径,第一种路径在我运行的每个基准测试中都出人意料地快
一旦有了它,您只需将其上载到OpenGL ES纹理:
glBindTexture(GL_TEXTURE_2D, outputTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (int)pixelSizeToUseForTexture.width, (int)pixelSizeToUseForTexture.height, 0, GL_BGRA, GL_UNSIGNED_BYTE, imageData);
这假设您已经使用以下内容创建了outputTexture:
glActiveTexture(GL_TEXTURE0);
glGenTextures(1, &outputTexture);
glBindTexture(GL_TEXTURE_2D, outputTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// This is necessary for non-power-of-two textures
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
并且通过使用+setCurrentContext:
将正确的EAGLContext与当前线程关联
如果我可以提出一个建议,为什么不看看为您处理所有这些,以便做图像处理任务?这可能会为您节省一些精力。嗨,布拉德,我知道您的框架。。。真是太棒了!然而,我只是觉得对于这样简单的任务来说,开销太大了。我会试着按照你的建议去做,看看是否能先这样做。谢谢嘿,布拉德,谢谢!这是一种工作。。。我得到了纹理,唯一的问题是它是绿色的。这是因为纹理格式错误,并且没有包含每个通道所需的所有位吗?对不起,如果问题不是很精确。。。但我是一个完全不懂OpenGL的人。:)@Andrea-如果它是绿色的,但是图像仍然显示,并且没有填充一束对角线,那么输入图像的字节顺序可能有问题。它可能接受RGBA而不是BGRA,或ARGB或ABGR。我在位图上下文中使用的上述设置是专门为生成BGRA帧而选择的,用于稍后的纹理上载。请确保您没有使用其他上下文设置。我严格遵循了您的代码,但不幸的是它不起作用。我想我很清楚原因。请检查对我原始问题的编辑。。。我补充了更多细节。(我该怎么办?@yourname with yourname?@Andrea-是的,当然对于平面YUV来说,这不会像上面所描述的那样起作用。当你说“现在我想使用静态图像”时,我假设你是从UIImage源提取的,在那里你可以提取到BGRA图像缓冲区。你现在问的问题完全不同了。对于YUV平面源,需要将Y和UV纹理的
glTexImage2d()
参数替换为更新的第一个代码中显示的纹理缓存函数中的参数。请注意新的字节大小以及GL_RED_EXT
和GL_RG_EXT
纹理类型的使用。