6

私は現在、カメラ入力を取り、それを OpenGL テクスチャに変換し、それを 3D オブジェクト (現在は簡単にするために透視投影の平面) にマップする iPhone 用のカメラ アプリに取り組んでいます。カメラ入力をこの 3D 平面にマッピングした後、この 3D シーンをテクスチャにレンダリングします。このテクスチャは、正投影空間の平面の新しいテクスチャとして使用されます (フラグメント シェーダーで追加のフィルターを適用するため)。

すべてを正投影に保つ限り、レンダリング テクスチャの解像度はかなり高くなります。しかし、飛行機を透視投影に入れた瞬間から、レンダリング テクスチャの解像度が非常に低くなります。

比較:

解像度比較

ご覧のとおり、最後の画像は他の 2 つに比べて解像度が非常に低くなっています。だから私は何か間違ったことをしていると思います。

私は現在、どのフレーム バッファでもマルチサンプリングを使用していません。正射投影シーンが完全に機能するため、問題を解決するためにマルチサンプリングが必要かどうかは疑問です。

私がレンダリングするテクスチャは 2048x2048 です (最終的には iPhone のカメラ ロールに画像として出力されます)。

関連すると思われるソースコードの一部を次に示します。

画面に出力されるフレームバッファを作成するコード:

// Color renderbuffer
glGenRenderbuffers(1, &colorRenderBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, colorRenderBuffer);
[context renderbufferStorage:GL_RENDERBUFFER 
                 fromDrawable:(CAEAGLLayer*)glView.layer];

// Depth renderbuffer
glGenRenderbuffers(1, &depthRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);

// Framebuffer
glGenFramebuffers(1, &defaultFrameBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, defaultFrameBuffer);

// Associate renderbuffers with framebuffer
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 
      GL_RENDERBUFFER, colorRenderBuffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, 
      GL_RENDERBUFFER, depthRenderbuffer);

TextureRenderTarget クラス:

void TextureRenderTarget::init()
{
    // Color renderbuffer
    glGenRenderbuffers(1, &colorRenderBuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, colorRenderBuffer);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB8_OES, 
           width, height);

    // Depth renderbuffer
    glGenRenderbuffers(1, &depthRenderbuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 
           width, height);

    // Framebuffer
    glGenFramebuffers(1, &framebuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);

    // Associate renderbuffers with framebuffer
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 
          GL_RENDERBUFFER, colorRenderBuffer);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, 
          GL_RENDERBUFFER, depthRenderbuffer);

    // Texture and associate with framebuffer
    texture = new RenderTexture(width, height);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 
          GL_TEXTURE_2D, texture->getHandle(), 0);

    // Check for errors
    checkStatus();
}

void TextureRenderTarget::bind() const
{
    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, colorRenderBuffer);
}



void TextureRenderTarget::unbind() const
{
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glBindRenderbuffer(GL_RENDERBUFFER, 0);
}

最後に、レンダー テクスチャを作成してピクセルで塗りつぶす方法のスニペットを示します。

void Texture::generate()
{
    // Create texture to render into
    glActiveTexture(unit);
    glGenTextures(1, &handle);
    glBindTexture(GL_TEXTURE_2D, handle);

    // Configure texture
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_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);
}

void Texture::setPixels(const GLvoid* pixels)
{
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, 
         GL_UNSIGNED_BYTE, pixels);
    updateMipMaps();
}

void Texture::updateMipMaps() const
{
    glBindTexture(GL_TEXTURE_2D, handle);
    glGenerateMipmap(GL_TEXTURE_2D);
}

void Texture::bind(GLenum unit)
{
    this->unit = unit;

    if(unit != -1)
    {
        glActiveTexture(unit);
        glBindTexture(GL_TEXTURE_2D, handle);
    }
    else
    {
        cout << "Texture::bind -> Couldn't activate unit -1" << endl;
    }
}

void Texture::unbind()
{
    glBindTexture(GL_TEXTURE_2D, 0);    
}
4

3 に答える 3

6

パースペクティブ プロジェクションでは、テクスチャ マッピングは正確ではないと思います。

カメラロールの画像をチェッカー(セルサイズ1pxのチェス盤)に置き換えていただけませんか?次に、直交投影と透視投影でレンダリングされたチェッカーを比較します。グリッドはぼやけてはいけません。そうである場合、問題は射影行列にあります。テクセルからピクセルへの直接マッピングにはある程度のバイアスが必要です。

デバイスをお持ちの場合OpenGL frame captureは、XCode の機能を使用してレンダリングの手順を確認できます。画像がいつぼやけるかを正確に確認できます。

ミップマッピングに関しては、オンザフライで作成されたテクスチャに使用するのは良くありません。

于 2012-09-11T08:54:45.237 に答える
5

ぼやけは、平面が画面座標の半分のピクセルに配置されていることが原因である可能性があります。正投影から透視変換に移行すると平面の位置が変わるため、平面は 2 つの変換間で同じ画面座標に配置されない可能性があります。

UIImageView をフレームの原点 (0.0,0.0) から標準解像度ディスプレイでは (0.5,0.5) に、Retina ディスプレイでは (0.25,0.25) に移動すると、同様のぼやけが発生します。

テクスチャが非常に高解像度であるという事実は、実際にサンプリングされるピクセル数が制限されているため、この場合には役に立たない可能性があります。

画面の x、y 座標で平面を少し動かしてみて、ぼやけが消えるかどうかを確認してください。

于 2012-09-11T21:30:18.483 に答える
2

レンダリングプロセスの最初のステップと2番目のステップをマージすることで、最終的に問題を解決しました。

カメラのテクスチャをトリミングして反転し、新しいテクスチャにレンダリングするために使用される最初のステップ。次に、この新しくレンダリングされたテクスチャが3D平面にマッピングされ、結果が新しいテクスチャにレンダリングされます。

3D平面のテクスチャ座標を変更して、これら2つの手順をマージし、元のカメラテクスチャをこの平面に直接使用できるようにしました。

レンダリングされた2つのテクスチャ間でこの品質の低下を引き起こした正確な理由はわかりませんが、将来のヒントとして、テクスチャにレンダリングせず、その結果をテクスチャへの新しいレンダリングに再利用します。これらすべてをマージすると、パフォーマンスが向上し、カラーシフトの問題も回避されます。

于 2012-09-28T12:44:02.593 に答える