2015-12-03 184 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