2012-08-06 85 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