Qt Opengl VBO 数据损坏
Posted
技术标签:
【中文标题】Qt Opengl VBO 数据损坏【英文标题】:Qt Opengl VBO data corrupted 【发布时间】:2015-12-03 17:49:49 【问题描述】:到现在为止,我已经尝试了将近两个星期来让 VBO 在 Qt 环境中工作,但到目前为止没有任何效果。我的目标是创建一个三角形网格以用作某些地形的基础,就像在 Lighthouse3D 教程中一样。我的程序的相关部分如下:
GameWindow.h
class GameWindow : public QOpenGLWidget, protected QOpenGLFunctions_3_3_Core
Q_OBJECT
public:
GameWindow(QWidget *parent = 0);
~GameWindow();
protected:
virtual void initializeGL() override;
virtual void resizeGL(int width, int height) override;
virtual void paintGL() override;
QGLShaderProgram *shaderProgram;
private:
int frame;
std::vector<GLfloat> grid;
QOpenGLBuffer vbo;
GLuint vboId;
QVector3D position;
;
GameWindow.cpp
GameWindow::GameWindow(QWidget *parent) :
QOpenGLWidget(parent),
position(QVector3D(0, 5, -5)),
vbo(QOpenGLBuffer(QOpenGLBuffer::VertexBuffer))
GameWindow::~GameWindow()
void GameWindow::initializeGL()
QOpenGLWidget::initializeGL();
initializeOpenGLFunctions();
shaderProgram = new QGLShaderProgram(QGLContext::currentContext());
QGLShader vertex(QGLShader::Vertex);
vertex.compileSourceFile(QDir(":/shaders").absoluteFilePath("basic.vert"));
shaderProgram->addShader(&vertex);
QGLShader fragment(QGLShader::Fragment);
fragment.compileSourceFile(QDir(":/shaders").absoluteFilePath("basic.frag"));
shaderProgram->addShader(&fragment);
shaderProgram->link();
QImage image;
image.load("C:\\test.png");
int width = image.width(); //=10
int height = image.height(); //=10
for (int i = 0; i < height-1; i++)
for (int j = 0; j < width-1; j++)
grid.push_back(GLfloat(j));
grid.push_back(GLfloat(0.0f));
grid.push_back(GLfloat(i));
grid.push_back(GLfloat(j));
grid.push_back(GLfloat(0.0f));
grid.push_back(GLfloat(i+1));
grid.push_back(GLfloat(j+1));
grid.push_back(GLfloat(0.0f));
grid.push_back(GLfloat(i+1));
grid.push_back(GLfloat(j+1));
grid.push_back(GLfloat(0.0f));
grid.push_back(GLfloat(i+1));
grid.push_back(GLfloat(j+1));
grid.push_back(GLfloat(0.0f));
grid.push_back(GLfloat(i));
grid.push_back(GLfloat(j));
grid.push_back(GLfloat(0.0f));
grid.push_back(GLfloat(i));
vbo.create();
vbo.bind();
vbo.allocate(grid.size()*sizeof(GLfloat));
vbo.write(0, grid.data(), grid.size()*sizeof(GLfloat));
vbo.release();
/*
glGenBuffers(1, &vboId);
glBindBuffer(GL_ARRAY_BUFFER, vboId);
glBufferData(GL_ARRAY_BUFFER, grid.size() * sizeof(GLfloat), grid.data(), GL_STATIC_DRAW);
//*/
std::cout << std::boolalpha << (glGetError() == GL_NO_ERROR) << std::endl;
void GameWindow::resizeGL(int width, int height)
QOpenGLWidget::resizeGL(width, height);
void GameWindow::paintGL()
shaderProgram->bind();
QMatrix4x4 projection;
projection.perspective(45, qreal(width())/qreal(height() > 0 ? height() : 1), 0.1f, 100.0f);
QMatrix4x4 view;
view.lookAt(position, QVector3D(0, 0, 0), QVector3D(0, 1, 0));
QMatrix4x4 model;
model.translate(-0.5f, 0, 0);
QMatrix4x4 mvp;
mvp = projection * view * model;
shaderProgram->setUniformValue("matrix", mvp);
glClear(GL_COLOR_BUFFER_BIT);
vbo.bind();
shaderProgram->enableAttributeArray("vertex");
shaderProgram->setAttributeBuffer("vertex", GL_FLOAT, 0, 3);
glDrawArrays(GL_TRIANGLES, 0, vbo.size());
shaderProgram->disableAttributeArray("vertex");
/*
glBindBuffer(GL_ARRAY_BUFFER, vboId);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3, 0);
glDrawArrays(GL_TRIANGLES, 0, grid.size());
glDisableVertexAttribArray(0);
*/
shaderProgram->release();
update();
着色器
//Vertex Shader
attribute vec3 vertex;
uniform mat4 matrix;
varying vec3 pos;
void main(void)
gl_Position = matrix * vec4(vertex, 1);
pos = vertex;
//Fragment Shader
void main(void)
gl_FragColor.rgb = pos;
最后我像这样打开窗口:
QSurfaceFormat format;
format.setVersion(3, 3);
format.setProfile(QSurfaceFormat::CoreProfile);
format.setSamples(4);
QSurfaceFormat::setDefaultFormat(format);
GameWindow *w = new GameWindow();
w->show();
运行这个程序后,我得到了类似的东西,虽然它经常改变:
从代码中可以看出,我尝试使用QOpenGLBuffer
和原始gl*
命令创建和绘制我的VBO,结果相似。谷歌没有任何帮助,所以现在我向你寻求帮助。我的 VBO 出了什么问题,为什么数据损坏了?
注意:
当我运行时,我在标准输出中收到此错误:
[opengl\qopenglframebufferobject.cpp line 565] OpenGL Error: 1286
QOpenGLFramebufferObject: Unsupported framebuffer format.
QOpenGLFramebufferObject: Unsupported framebuffer format.
[opengl\qopenglframebufferobject.cpp line 720] OpenGL Error: 1280
但我不知道这是否与它有关。
注2:
尝试使用 vbo.read()
会使我的程序崩溃。
【问题讨论】:
您能解释一下您投反对票的原因吗? 【参考方案1】:当你发出这个命令时:
shaderProgram->setAttributeBuffer("vertex", GL_FLOAT, 0, 3);
您确实是在说每 3 个浮点数将被解释为 1 个属性。因此,要绘制,您需要调用:
glDrawArrays(GL_TRIANGLES, 0, grid.size()/3);
注意。在我看来, vbo.size() 为您提供了进入 vbo 对象的字节数,而不是进入缓冲区的元素数量
【讨论】:
非常感谢,成功了:D【参考方案2】:在 Qt 中,OpenGL 操作仅在放置在 makeCurrent
... doneCurrent
块内或 …GL
方法内时才有效。如果两个前提条件都不满足,则没有可创建 VBO 的 OpenGL 活动。
解决方案:将 OpenGL 初始化代码从构造函数移至 initializeGL
。
【讨论】:
哦,哇,原来如此简单:/奇怪的是它对单个三角形工作正常......但谢谢你,我会试试这个:)以上是关于Qt Opengl VBO 数据损坏的主要内容,如果未能解决你的问题,请参考以下文章
QT_OPENGL-------- 3.ElementArraryBuffer