FBO:レンダリングされたテクスチャを描画するとき、テクスチャへのレンダリング

Mac OS XアプリケーションでOpenGLを使用して、 NSOpenGLView にテクスチャを描画しています。

アプリはムービープレーヤーです。ムービーフレームを CVOpenGLTextureRef (OpenGLテクスチャ)にデコードし、 GL_QUAD を使用してビューに直接描画します。すべて正常に動作します。

以下はコードの関連部分です。

// "image" is the CVOpenGLTextureRef containing the movie frame as texture
GLenum textureTarget = CVOpenGLTextureGetTarget(image);
GLuint textureName = CVOpenGLTextureGetName(image);

glEnable(textureTarget);
glBindTexture(textureTarget, textureName); 

glBegin(GL_QUADS);
// Draw the quads
//Note: textureTagret is NOT GL_TEXTURE_2D, therefore texture coordinates
//are NOT scaled to [0, 1] 

glTexCoord2f(0.0f, imageRect.size.height);
glVertex2f (0.0f, 0.0f);

glTexCoord2f(0.0f, 0.0f); 
glVertex2f (0.0f, windowRect.size.height); 

glTexCoord2f(imageRect.size.width, 0.0f);
glVertex2f (windowRect.size.width, windowRect.size.height);

glTexCoord2f(imageRect.size.width, imageRect.size.height);
glVertex2f (windowRect.size.width,0.0f); 

glEnd();
glDisable(textureTarget);
glFlush();

それはうまく動作し、私はウィンドウのサイズを変更することができるとテクスチャは、小さなウィンドウに正しくマップされます。

See here for different window size from full screen to 500x280 pixel: Without FBO

私は今、テクスチャをレンダリングするためにFBOを使用したいと思います。私は、ムービーフレームをオフスクリーンのFBO(テクスチャ)にレンダリングし、そのテクスチャをバインドして画面に描画するという非常に簡単な実装を開始しました。

ここにコードです:

// "image" is the CVOpenGLTextureRef containing the movie frame as texture
GLenum textureTarget = CVOpenGLTextureGetTarget(image);
GLuint textureName = CVOpenGLTextureGetName(image);

////////////////////////////////////////////////////////////////////
// the creation on the FBO is done only once on program start:

GLuint fboId;
GLuint textureId;
float targetWidth = 2048;
float targetHeight = 2048;

// create a texture object
glGenTextures(1, &textureId);
glBindTexture(textureTarget, textureId);
glTexParameterf(textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(textureTarget, GL_GENERATE_MIPMAP, GL_TRUE);//automatic mipmap
glTexImage2D(textureTarget, 0, GL_RGBA8, targetWidth, targetHeight, 0,
                 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glBindTexture(textureTarget, 0);

// create a framebuffer object
glGenFramebuffersEXT(1, &fboId);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboId);

// attach the texture to FBO color attachment point
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
                           textureTarget, textureId, 0);

// check FBO status
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
if(status != GL_FRAMEBUFFER_COMPLETE_EXT)
    return FALSE;

// switch back to window-system-provided framebuffer
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
///////////////////////////////////////////////////////////////////////////////

// Render to texture

glEnable(textureTarget);
glBindTexture(textureTarget, textureName);

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboId);
glClear(GL_COLOR_BUFFER_BIT);   

glBegin(GL_QUADS);
// Draw the quads

glTexCoord2f(0.0f, imageRect.size.height);
glVertex2f (0.0f, 0.0f);        

glTexCoord2f(0.0f, 0.0f); 
glVertex2f (0.0f,imageRect.size.height);

glTexCoord2f(imageRect.size.width, 0.0f);
glVertex2f (imageRect.size.width, imageRect.size.height);

glTexCoord2f(imageRect.size.width, imageRect.size.height);
glVertex2f (imageRect.size.width,0.0f);

glEnd();
glFlush();

// Bind newly rendered texture
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glClear(GL_COLOR_BUFFER_BIT);
glBindTexture(textureTarget, textureId);
glGenerateMipmapEXT(textureTarget);

// draw on-screen
glBegin(GL_QUADS);
// Draw the quads
//Note: textureTagret is NOT GL_TEXTURE_2D, therefore texture coordinates
//are NOT scaled to [0, 1] 

glTexCoord2f(0.0f, imageRect.size.height);
glVertex2f (0.0f, 0.0f);

glTexCoord2f(0.0f, 0.0f); 
glVertex2f (0.0f, windowRect.size.height); 

glTexCoord2f(imageRect.size.width, 0.0f);
glVertex2f (windowRect.size.width, windowRect.size.height);

glTexCoord2f(imageRect.size.width, imageRect.size.height);
glVertex2f (windowRect.size.width,0.0f); 

glEnd();
glDisable(textureTarget);
glFlush();

イメージ/テクスチャが上下が逆であるだけでなく、テクスチャマッピングも間違っているため、コードは正しく機能しません。これは、ウィンドウがフルスクリーンの場合にのみ正しく動作します。それ以外の場合は、実際には奇妙な動作をします。

See image below: With FBO

ご覧のように、テクスチャはウィンドウ内で正しくスケーリングされますが、フルスクリーンウィンドウサイズと実際のウィンドウサイズの差に比例して「クロップ」されます。

私は成功なしですべてを試しました。

OpenGLを使うのは初めてのことなので、何か不足していますか?私は狂っているよ..

2

1 答え

  //テクスチャにレンダリングする

glEnable(textureTarget);
glBindTexture(textureTarget、textureName);

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT、fboId);
glClear(GL_COLOR_BUFFER_BIT);
 

ここで、フレームバッファオブジェクトのビューポートと投影を設定しています。

  glBegin(GL_QUADS);
//クワッドを描く

glTexCoord2f(0.0f、imageRect.size.height);
g lVertex2f(0.0f、0.0f);

glTexCoord2f(0.0f、0.0f);
glVertex2f(0.0f、imageRect.size.height);

glTexCoord2f(imageRect.size.width、0.0f);
glVertex2f(imageRect.size.width、imageRect.size.height);

glTexCoord2f(imageRect.size.width、imageRect.size.height);
glVertex2f(imageRect.size.width、0.0f);

glEnd();
glFlush();
 
2
追加された
@ Andrea3000:まあ、それは逆さまに描くので、反転されています。画像の原点は、左下であり、右上ではなく、あなたが想定しているようです。ビューポートと投影の設定については、OpenGLの初心者に伝えていることは約80%です。ウィンドウのサイズ変更ハンドラではなく、描画関数で設定してください。 FBOを使用するとき、またはHUDなどを描画するときに問題になるので、ウィンドウのサイズ変更ハンドラはこのための悪い場所です。すべてのOpenGL操作(静的データアップロードを除く)は、描画関数に属します。
追加された 著者 datenwolf,
@ Andrea3000:最も起こりそうなことは、映画フレームが左上の原点を想定して格納されているということです。あなたはこれを裏返す必要があります。 TGAのような一部の画像フォーマットは、固定原点を持ちます。 PNGやBMPのようなものは、両方を可能にします。これを考慮する必要があります。 OpenGLは常に画像データを左下から開始すると想定しています。したがって、glTexImage2Dに供給する前に、テクスチャ座標を適切に反転するか、イメージデータの順序を変更してください。
追加された 著者 datenwolf,
@ Andrea3000:まさに。ムービーフレームのレンダリングは、それを直立位置に反転させますが、それ以上の処理ステップではこれを必要としないので、反転しないでください。
追加された 著者 datenwolf,
ああ、私は悪いです...あなたの答えはありがとうございます。私はウィンドウのサイズ変更時にのみビューポートと投影を設定していました。私は、FBOとバックバッファの2つの異なるビューポートと投影を指定する必要があることを認識しませんでした。これはテクスチャマッピングの問題を解決しますが、(明らかに)テクスチャはまだ上下逆さまです。私は glTexCoord2f glVertex2f の関連を変更することができますなぜ私はそれを必要としますか?バックバッファに直接描画すると、テクスチャは正しく向きが変わります。FBOに描画するときに何かを変更する必要がありますか?
追加された 著者 Andrea3000,
OpenGLについてのご意見ありがとうございます、私はそれらを念頭に置いています;-)フリップされた画像について:FBOとバックバッファは異なる座標系を持っていますか?バックバッファーに描画され、FBOに描画されたときに反転され、バックバッファーに描画されたときに、イメージがどのようにして正しいのか理解できないので、私はあなたに尋ねます。両方のケースで glTexCoord2f glVertex2f は同じです。
追加された 著者 Andrea3000,
さて、今、私はそれを得るでしょう、説明のためにあなたに感謝;-)あなたが何を意味するか理解していれば、これが起こります:私のムービーフレームは、左上隅に原点を持っています。 FBOにレンダリングすると、正しくレンダリングされますが(反転されません)、原点は左下に表示されます。ですから、今度は、複数のFBOにレンダリングしても原点が常に左下にくるので、テクスチャの座標を変更する必要があります。そうですか?レンダリングとテクスチャは正しいので、2番目の描画をバックバッファに変更する必要があります。
追加された 著者 Andrea3000,
ありがとうございました!あなたはとても役に立ちました;-)
追加された 著者 Andrea3000,