2012-08-06 91 views
0

我在OpenGLES 2.0中简单的平面上映射iPhone摄像头输出时遇到了问题。出于某种原因,通过CVOpenGLESTextureCacheCreateTextureFromImage生成的OpenGL纹理被翻转并旋转。如何旋转iPhone摄像头输出OpenGLES纹理

这里是我的情况:我做了一个波前.OBJ装载机解析这个简单的平面物体:

v -0.5 -0.5 0 
v 0.5 -0.5 0 
v -0.5 0.5 0 
v 0.5 0.5 0 

vt 0 0 0 
vt 1 0 0 
vt 0 1 0 
vt 1 1 0 

f 4/4 3/3 1/1 
f 2/2 4/4 1/1 

至于我担心我的纹理映射的工作原理是它必须如此。我通过将一个简单的PNG图像映射到飞机上来验证这一点。它显示正确。 (仅用于记录:我在iPhone坐标系中加载图像,翻转图像像素以匹配OpenGL的左上角纹理坐标系并映射所有内容)。结果:工作!

所以,在我的代码周围洗牌并将相机像素缓冲区送入我的纹理单元后,出现了一些问题(或者这可能意味着行为,我应该以某种方式反击?只要它不是CPU重码)。

这是我的代码:它的一些灵感来源于Brad Larson的ColorTracking示例和Apple的GLCameraRipple示例。

代码捕获输出:

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection 
{ 
    CVImageBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 
    [self.delegate processNewCameraFrame:pixelBuffer]; 
} 

通过图像缓冲后,周围的裁判在这里结束了:

- (void)updateCameraFrame:(CVImageBufferRef)pCameraFrame 
{ 
    if(cameraTextureMaterial) 
    { 
     cameraTextureMaterial->updateWithCameraFrame(pCameraFrame); 
    } 
} 

CamerTextureMaterial:

void CameraTextureMaterial::updateWithCameraFrame(CVImageBufferRef pixelBuffer) 
{ 
    if(!_videoTextureCache) 
    { 
     cout << "No video texture cache" << endl; 
     return; 
    } 

    cleanup(); 

    CVReturn err; 
    size_t width = CVPixelBufferGetWidth(pixelBuffer); 
    size_t height = CVPixelBufferGetHeight(pixelBuffer); 

    glActiveTexture(GL_TEXTURE0); 

    err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, 
                 _videoTextureCache, 
                 pixelBuffer, 
                 NULL, 
                 GL_TEXTURE_2D, 
                 GL_RGBA, 
                 width, 
                 height, 
                 GL_BGRA, 
                 GL_UNSIGNED_BYTE, 
                 0, 
                 &_lumaTexture); 
    if (err) 
    { 
     cout << "Error at CVOpenGLESTextureCacheCreateTextureFromImage" << endl; 
    } 

    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); 
} 

我不包括初始化并清理纹理缓存,因为这对我的纹理方向问题无关紧要。

关于如何获得正确的纹理方向的任何建议?

回答

0

解决这个问题,实际上是通过选择你的纹理很容易明智的坐标。我旋转,翻转和裁剪相机纹理,通过将其映射到下面的坐标并将正交场景呈现为一个新的纹理,然后将其用于我的场景中。

坐标我用:

void CameraClipPlaneObject3D::init() 
{ 
    // Create plane object 
    vertices = shared_ptr<Vertex3DVector>(new Vertex3DVector()); 
    vertices->push_back(Vertex3D(1, -1, 0)); 
    vertices->push_back(Vertex3D(1, 1, 0)); 
    vertices->push_back(Vertex3D(-1, 1, 0)); 
    vertices->push_back(Vertex3D(-1, -1, 0)); 

    // Create texture coords 
    textureCoords = shared_ptr<Texture2DVector>(new Texture2DVector()); 
    textureCoords->push_back(Texture2D(0.875, 0)); 
    textureCoords->push_back(Texture2D(0.125, 0)); 
    textureCoords->push_back(Texture2D(0.125, 1)); 
    textureCoords->push_back(Texture2D(0.875, 1)); 

    // Create indices 
    indices = shared_ptr<IndexVector>(new IndexVector()); 
    indices->push_back(0); 
    indices->push_back(1); 
    indices->push_back(2); 
    indices->push_back(2); 
    indices->push_back(3); 
    indices->push_back(0); 
} 

下面是如何使飞机上一个新的纹理:

  1. 首先创建一个纹理像你平日里(不要忘了纹理过滤)
  2. 然后像通常那样创建一个帧缓冲区
  3. 将纹理colorbuffer附加到此新帧缓冲区的颜色附件中:
  4. 在渲染循环中,绑定到这个新的帧缓冲区并渲染场景。

一些示例代码:

void TextureRenderTarget::init() 
{ 
    // Create texture to render to 
    texture = new RenderTexture(width, height, GL_LINEAR, GL_LINEAR); 

    // Create framebuffer and attach texture to framebuffer 
    framebuffer = new Framebuffer(width, height); 
    framebuffer->attachTexture(texture); 
} 

附加代码:

void Framebuffer::attachTexture(Texture *texture) const 
{ 
    glBindFramebuffer(GL_FRAMEBUFFER, handle); 
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture->getHandle(), 0); 
} 
2

老实说,我没有看到使用OBJ这种简单几何的好处。最后我们只是谈论2个三角形:),这些三角形很容易在代码中实时创建。

除了这个“化妆品”的评论,OpenGL的默认工作在非翻转图像纹理。很可能你从相机链接的纹理默认翻转(这取决于格式的互联网数据组织,而不是你打开图片时看到的内容)。

一个快速和肮脏的解决方案是使用下面的技巧:

glMatrixMode(GL_TEXTURE); 
glLoadIdentity(); 
glScalef(1.0f, -1.0f, 1.0f); 
glMatrixMode(GL_MODELVIEW); 

这应该做的伎俩为您节省吨计算能力。

干杯 莫里吉奥

+0

谢谢您的回答。飞机.obj文件只是为了让我的问题简短。实际的形状是一个更复杂的半球状物体。我也在寻找OpenGL 2.0解决方案。 – polyclick 2012-08-07 10:02:59

+0

我认为你有2个选择。 第一:您实时翻转图像。这是非常昂贵的,有时可能会成为演出的一个问题。 其次:您翻转四边形纹理的坐标。 – 2012-08-07 10:11:54

+0

我正在尝试将相机输入渲染到新纹理并将该纹理应用到对象。如果解决问题,我会告诉你;) – polyclick 2012-08-07 10:23:15