2015-12-03 188 views
1

我一直在尝试将近两周时间才能让VBOs在Qt环境中工作,但至今没有任何工作。我的目标是创建一个三角形网格作为一些地形的基础,就像在Lighthouse3D教程中一样。是我计划的相关部分如下:Qt Opengl VBO数据损坏

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(); 

运行这个程序后,我得到一些与此类似,虽然它经常改变: Weird Result

正如你可以从代码中看到的,我一直在使用这两种QOpenGLBuffer和原材料gl*命令创建和绘制我的VBO尝试,结果相似。 Google没有任何帮助,所以现在我转向你寻求帮助。我的VBOs出了什么问题,数据为什么会损坏?

注:

当我跑我在标准输出得到这个错误:

[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()崩溃我的程序。

+0

请问您能解释为什么downvoted? – Nikolai97

回答

3

当你发出命令:

shaderProgram->setAttributeBuffer("vertex", GL_FLOAT, 0, 3); 

你确实说,每3个浮标是被解释为1点的属性。因此,您需要拨打:

glDrawArrays(GL_TRIANGLES, 0, grid.size()/3); 

注意。在我看来,vbo.size()会为您提供进入vbo对象的字节数量,而不是缓冲区中元素的数量。

+0

谢谢你这么做,那是做的:D – Nikolai97

0

在Qt中,OpenGL操作仅在放入makeCurrent ... doneCurrent块或…GL方法中时才有效。既没有满足前提条件,也没有任何维护组织可以创建的OpenGL活动。

解决方案:将您的OpenGL初始化代码从构造函数移动到​​。

+0

哦,哇,原来如此简单:/奇怪的是,它正确地为一个单一的三角形...但是,谢谢你,我会试试这个:) – Nikolai97

+0

不,它仍然不能正常工作:/ – Nikolai97