0

OpenGLES2.0の単純な平面にiPhoneカメラの出力をマッピングするのに問題があります。何らかの理由で、を介して生成されたOpenGLテクスチャCVOpenGLESTextureCacheCreateTextureFromImageが反転および回転されます。

これが私の状況です。この単純な平面オブジェクトを解析するWavefront.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の重いコードではありません)。

これが私のコードです。その一部は、BradLarsonの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);
}

テクスチャの向きの問題には関係ないため、テクスチャキャッシュの初期化とクリーンアップを除外しています。

テクスチャの正しい向きを取得する方法について何か提案はありますか?

4

2 に答える 2

2

正直なところ、このような単純なジオメトリにOBJを使用することのメリットはわかりません。最後に、2つの三角形について話しているだけです:)コードでその場で作成するのは非常に簡単です。

この「見栄えのする」コメントとは別に、OpenGLはデフォルトで、テクスチャリング用のフリップされていない画像で機能します。ほとんどの場合、カメラからリンクするテクスチャはデフォルトで反転しています(これは、画像を開いたときに表示されるものではなく、フォーマットのインターネットデータ構成に大きく依存します)。

迅速で汚い解決策の1つは、以下のトリックを使用することです。

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

これはあなたのためのトリックを行い、大量の計算能力を節約するはずです。

乾杯マウリツィオ

于 2012-08-07T09:50:00.607 に答える
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. テクスチャカラーバッファをこの新しいフレームバッファのカラーアタッチメントにアタッチします。
  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);
}
于 2012-09-28T13:04:34.720 に答える