我正在开发一个应用程序,该应用程序将来自相机的视频帧馈送到OpenGL ES纹理中以创建一些效果。该应用程序使用Core Video及其许多方便的方法来创建OpenGL纹理和缓存。
现在我想使用静态图像而不是视频缓冲区,我正在寻找标准的OpenGL方法来代替Core video中可用的方法。
例如:
- CVOpenGLESTextureRef
- CVOpenGLESTextureCacheRef
- CVOpenGLESTextureCacheCreateTextureFromImage()
- CVOpenGLESTextureGetTarget()
- CVOpenGLESTextureGetName()
- CVOpenGLESTextureCacheFlush()
我可以使用哪些标准的OpenGL类型和方法来代替上面的代码,从普通图像加载和创建纹理?
感谢
*编辑*
按照布拉德的建议,我取得了一些进展。。。但是仍然不能正常工作。我认为问题在于着色器期望两个独立的纹理能够正常工作。一个用于Y平面,一个用于UV平面。
这是用来设置的代码
// 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);
这假设您已经使用以下内容创建了outputText:
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);
并且通过使用CCD_ 2将正确的EAGLContext与当前线程相关联。
如果我可以提出一个建议,为什么不看看我的开源框架,它为您处理所有这些,以便执行图像处理任务?这可能会为你节省一些精力。