1

我正在开发一个应用程序,它将来自相机的视频帧输入到 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 函数中的参数之一。我尝试了不同结果的不同组合......但从来没有正确的组合:)

4

1 回答 1

2

所有这些方法所做的就是为您提供与 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);

并且正确的 EAGLContext 使用 . 与当前线程相关联+setCurrentContext:

如果我可以提出建议,为什么不看看我的开源框架,它为您处理所有这些以执行图像处理任务?它可能会为您节省一些精力。

于 2012-08-20T15:44:57.957 回答