6

YUV イメージを OpenGL ビューポートにレンダリングするコードが OpenGL にいくつかあります。このプログラムは、nvidia カードで実行する場合は問題なく動作しますが、悲しいことにターゲット マシンである Intel HD 3000 で実行するとエラーが発生します。エラーが生成されたポイントは、コード内でマークされています。

シェーダープログラムは

// Vertex Shader
#version 120
void main() {
  gl_TexCoord[0] = gl_MultiTexCoord0;
  gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}

// fragment shader
#version 120
uniform sampler2D texY;
uniform sampler2D texU;
uniform sampler2D texV;
void main() {
  vec4 color;
  float y = texture2D(texY, gl_TexCoord[0].st).r;
  float u = texture2D(texU, gl_TexCoord[0].st).r;
  float v = texture2D(texV, gl_TexCoord[0].st).r;
  color.r = (1.164 * (y - 0.0625)) + (1.596 * (v - 0.5));
  color.g = (1.164 * (y - 0.0625)) - (0.391 * (u - 0.5)) - (0.813 * (v - 0.5));
  color.b = (1.164 * (y - 0.0625)) + (2.018 * (u - 0.5));
  color.a = 1.0;
  gl_FragColor = color;
};

次に、次のようにプログラムを実行します。

GLuint textures[3];
glGenTextures(3, textures);

glBindTexture(GL_TEXTURE_2D, textures[YTEX]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

glBindTexture(GL_TEXTURE_2D, textures[UTEX]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

glBindTexture(GL_TEXTURE_2D, textures[VTEX]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

glBindTexture(GL_TEXTURE_2D, 0);

GLsizei size = width * height;

GLvoid *y = yuv_buffer;
GLvoid *u = (GLubyte *)y + size;
GLvoid *v = (GLubyte *)u + (size >> 2);

glUseProgram(program_id);

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textures[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, GL_LUMINANCE,
            GL_UNSIGNED_BYTE, y);
glUniform1i(glGetUniformLocation(program_id, "texY"), 0);

glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, textures[1]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width >> 1, height >> 1, 0,
            GL_LUMINANCE, GL_UNSIGNED_BYTE, u);
glUniform1i(glGetUniformLocation(program_id, "texU"), 1);

glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, textures[2]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width >> 1, height >> 1, 0,
            GL_LUMINANCE, GL_UNSIGNED_BYTE, u);
glUniform1i(glGetUniformLocation(program_id, "texV"), 2);

glBegin(GL_QUADS);
glTexCoord2f(texLeft, texTop);
glVertex2i(left, top);
glTexCoord2f(texLeft, texBottom);
glVertex2i(left, bottom);
glTexCoord2f(texRight, texBottom);
glVertex2i(right, bottom);
glTexCoord2f(texRight, texTop);
glVertex2i(right, top);
glEnd();

// glError() returns 0x506 here

glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0);

glUseProgram(0);

フレームバッファでエラーが発生したため、更新しましたが、次のように使用されていることがわかりました。プログラムがインスタンス化されると、フレームバッファは次のように作成されます。

glViewport(0, 0, (GLint)width, (GLint)height);

glGenFramebuffers(1, &fbo_id);
glGenTextures(1, &fbo_texture);
glGenRenderbuffers(1, &rbo_id);

glBindTexture(GL_TEXTURE_2D, fbo_texture);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0,
            GL_RGBA, GL_UNSIGNED_BYTE, 0);
glBindTexture(GL_TEXTURE_2D, 0);

glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rbo_id);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, width, height);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_id);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
                          GL_TEXTURE_2D, fbo_texture, 0);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
                            GL_RENDERBUFFER_EXT, rbo_id);

GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);

glPushAttrib(GL_TEXTURE_BIT);

glBindTexture(GL_TEXTURE_2D, m_frameTexture->texture());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

glPopAttrib();

YUV 画像は、この fbo でレンダリングすることによって組み立てられたタイルに接合されます。フレームが開始するたびに、これが実行されます。

glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
glDrawBuffer(GL_BACK);

glViewport(0, 0, (GLint)width, (GLint)height);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, (double)width, 0.0, (double)height, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glBindFramebuffer(GL_FRAMEBUFFER_EXT, fbo_id);

次に、上記のコードが実行され、すべてのタイルが一緒に組み立てられた後

glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
glPushAttrib(GL_VIEWPORT_BIT | GL_TEXTURE_BIT | GL_ENABLE_BIT);
glViewport(0, 0, width, height);

glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);

glMatrixMode(GL_PROJECTION);
glPushMatrix();

glLoadIdentity();
glOrtho(0.0, (double)width, 0.0, (double)height, -1.0, 1.0);

glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();

glEnable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);

glBindTexture(GL_TEXTURE_2D, fbo_texture);

glBegin(GL_QUADS);
glTexCoord2i(0, 0);
glVertex2f(renderLeft, renderTop);
glTexCoord2i(0, 1);
glVertex2f(renderLeft, renderTop + renderHeight);
glTexCoord2i(1, 1);
glVertex2f(renderLeft + renderWidth, renderTop + renderHeight);
glTexCoord2i(1, 0);
glVertex2f(renderLeft + renderWidth, renderTop);
glEnd();

glPopMatrix();

glMatrixMode(GL_PROJECTION);
glPopMatrix();
glPopAttrib();
4

4 に答える 4

7

後の値は何ですかstatus:

GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);

値が 以外の場合GL_FRAMEBUFFER_COMPLETE、OpenGL が FBO から読み取ろうとすると、おそらくチョークします。

glCheckFramebufferStatus ドキュメントには、返される可能性のあるその他の (エラー) 値とその原因が記載されています。

特に興味深いのは次のとおりです。

現在バインドされているフレームバッファが完全なフレームバッファでない場合、フレームバッファを書き込みまたは読み取りに使用しようとするとエラーになります。これは、レンダリング コマンド(glDrawArrays および glDrawElements) と、フレーム バッファーを読み取るコマンド (glReadPixels、glCopyTexImage2D、および glCopyTexSubImage2D)が、フレーム バッファーが完全なフレーム バッファーではないときに呼び出されると、エラー GL_INVALID_FRAMEBUFFER_OPERATION を生成することを意味します。

(私のものを強調)

あなたのコメントに基づいて編集:

GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT に関するドキュメントを言い換えると:

すべてのフレーム バッファ アタッチメント ポイントが完全にフレーム バッファ アタッチされているわけではありません。これは、次のいずれかが発生していることを意味します。

  • レンダーバッファまたはテクスチャがアタッチされた少なくとも 1 つのアタッチ ポイントに、アタッチされたオブジェクトが存在しないか、幅または高さがゼロのイメージがアタッチされています。
  • カラー アタッチメント ポイントには、カラー レンダリングできないイメージがアタッチされています。カラー レンダリング可能な形式には、GL_RGBA4、GL_RGB5_A1、および GL_RGB565 があります。
  • 深度アタッチメント ポイントには、深度をレンダリングできないイメージがアタッチされています。GL_DEPTH_COMPONENT16 は、深度レンダリング可能な唯一の形式です。
  • ステンシルのアタッチ ポイントには、ステンシルでレンダリングできないイメージがアタッチされています。GL_STENCIL_INDEX8 は、ステンシル レンダリング可能な唯一の形式です。

深さまたはステンシル アタッチメントを使用していないように見えるため、最後の 2 つの箇条書きを除外できます。これにより、調べる必要がある 2 つの呼び出しが残ります。

glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, fbo_texture, 0);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, rbo_id);

FBO に関する opengl.org wikiから:

添付ファイルのいずれかが「不完全」な場合、GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT を取得します。完全性の基準は次のとおりです。

  • 画像のソース オブジェクトはまだ存在し、アタッチされたのと同じ型を持ちます。
  • 画像の幅と高さがゼロではありません。
  • 3D または配列テクスチャ アタッチメントのレイヤーは、テクスチャの深さよりも小さいです。
  • 画像の形式は、上で定義したように、接続ポイントの要件と一致する必要があります。カラー添付ファイルなどのカラーレンダリング可能な形式。

ウィキはGL_COLOR_ATTACHMENTi について次のように述べています。

これらのアタッチ ポイントには、カラー レンダリング可能な形式の画像のみをバインドできます。すべての圧縮イメージ形式はカラーレンダリング可能ではないため、FBO に関連付けることはできません。

fbo_texture と rbo_id がまだ有効であること、およびそれらの高さ/幅が 0 でないことを再確認してください。最後に、fbo_texture の形式である可能性があります。GL_RGBA8 に設定しましたが、有効なオプションにはGL_RGBA4、GL_RGB5_A1、および GL_RGB565 が含まれているとドキュメントに記載されています。それが他のすべてのフォーマット(GL_RGBA8など)を除外するかどうかはわかりません。ウィキは、圧縮されていない形式が機能することを示唆しているようです。GL_RGBA4 に切り替えてみて、うまくいくかどうかを確認してください。

于 2012-05-10T13:22:19.903 に答える
1

私は問題を解決しました。レンダリングバッファオブジェクトが消えるのは拡張機能の問題でした。基本的にこれを変更しました

glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rbo_id);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, width, height);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_id);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
                          GL_TEXTURE_2D, fbo_texture, 0);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
                            GL_RENDERBUFFER_EXT, rbo_id);

GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);

このため

glBindRenderbuffer(GL_RENDERBUFFER, rbo_id);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
glBindRenderbuffer(GL_RENDERBUFFER, 0);

glBindFramebuffer(GL_FRAMEBUFFER, fbo_id);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
                          GL_TURE_2D, fbo_texture, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
                            GL_RENDERBUFFER, rbo_id);

GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);

そしてそれはうまくいきました。私はまだ問題が正確に何であったか疑問に思います、しかし今のところ私は結果に満足しています。問題の正確なポイントを特定するのに役立った@lukeに特に感謝します。

于 2012-05-11T11:12:45.393 に答える
1

glGetErrorエラー コードは「固着」し、自動的にクリアされません。プログラムの最初に何かが OpenGL エラーを生成し、後でエラー コード 1000 の opengl 呼び出しをチェックした場合、エラーはまだここにあります。

したがって、実際に何が起こっているのかを理解したい場合は、OpenGL 呼び出しのたびにエラーをチェックするか、すべてのエラー コードが返されるまでループ内でglGetErrorを呼び出します (OpenGL のドキュメントが示唆するように)。

于 2012-05-10T12:56:58.157 に答える
0

正確には、どのコマンドでエラーが発生しますか? に置き換えGL_QUADSてみてくださいGL_TRIANGLE_FAN

于 2012-05-10T12:11:33.730 に答える