Opengl GL_QUADS会产生错误0x506
Opengl GL_QUADS produces error 0x506
我在OpenGL中有一些代码可以将YUV图像渲染到OpenGL视口上。该程序在 nvidia 卡上运行时运行没有问题,但在英特尔 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();
之后status
的价值是什么:
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
如果该值不是GL_FRAMEBUFFER_COMPLETE
,OpenGL在尝试从FBO读取时可能会窒息。
glCheckFramebufferStatus 文档描述了它可以返回的其他(错误(值,以及导致它们的原因。
特别感兴趣的可能是:
如果当前绑定的帧缓冲未完成,则 尝试使用帧缓冲进行写入或 读数。这意味着渲染命令(glDrawArrays 和 glDrawElements(以及读取帧缓冲的命令 (glReadPixels, glCopyTexImage2D, and glCopyTexSubImage2D(将 如果调用时生成错误GL_INVALID_FRAMEBUFFER_OPERATION 帧缓冲未完成。
(强调我的(
根据您的评论进行编辑:
套用文档GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
并非所有帧缓冲连接点都已完成帧缓冲连接。这意味着正在发生以下情况之一:
- 至少一个附加了渲染缓冲区或纹理的附着点的附着对象不再存在,或者附加的图像宽度或高度为零,
- 颜色附着点附加了不可呈现的颜色图像。颜色呈现格式包括GL_RGBA4、GL_RGB5_A1和GL_RGB565。
- 深度连接点附加了不可深度渲染的图像。GL_DEPTH_COMPONENT16是唯一可深度渲染的格式。
- 模具连接点附加了不可模板渲染的图像。GL_STENCIL_INDEX8是唯一的模具可呈现格式。
我们可以排除最后 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 维基:
当任何附件"不完整"时,您会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,看看是否可行。
glGetError 错误代码"粘"并且不会自动清除。如果程序开始时生成 OpenGL 错误,并且稍后检查错误代码 1000 次 opengl 调用,则错误仍然存在。
因此,如果您想了解真正发生的事情,请在每次 OpenGL 调用后检查错误,或者在循环中调用 glGetError,直到返回所有错误代码(如 OpenGL 文档所建议的那样(。
我解决了这个问题。这是一个扩展问题,使渲染缓冲区对象消失。我基本上改变了这个
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的回答帮助找到了问题的确切点。
确切地说,什么命令会引发错误?尝试将GL_QUADS
替换为 GL_TRIANGLE_FAN
。
- 警告处理为错误这里有什么问题
- "error: no matching function for call to"构造函数错误
- boost::进程间消息队列引发错误
- C++,OpenCV,尝试显示图像时"OpenCV(4.3.0) Error: Assertion failed (size.width>0 && size.height>0)"此错误
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- QT在错误的班级中寻找空位
- vector.resize()中的分配错误
- 代码在main()中运行,但在函数中出现错误
- 释放错误后堆使用
- (C++)分析树以计算返回错误值的简单算术表达式
- Project Euler问题4的错误解决方案
- 我的字符计数代码计算错误.为什么
- 从"int*"强制转换为"unsigned int"会丢失精度错误
- 尝试导入pybind-opencv模块时出现libgtk错误
- CMake项目Boost库错误:Boost/config/compiler/gcc.hpp:165:10:致命错误:cs
- 在某些循环内使用vector.push_back时出现分段错误
- MSVC多行宏编译器错误
- 静态数据成员的问题-修复链接错误会导致编译器错误
- 为什么在运行时没有向我们提供有关分段错误的更多信息?
- Opengl GL_QUADS会产生错误0x506