使用c ++

时间:2016-02-13 08:33:38

标签: c++ opengl graphics visual-studio-2015 vao

我正在学习openGL,我正在尝试做一些非常简单的事情。我有一个名为Model的图形对象,它包含一个顶点的GLfloats向量,并具有绘图功能。除此之外,我有一个addVertex函数,它接受3个浮点数和一个绘制函数,它绑定对象的VAO,然后在绘制后解除绑定。我没有问题渲染其中一个对象并为其添加点,但是我不能同时绘制多个这些对象而没有程序崩溃,而且Visual Studio告诉我“Frame not in module”这对我没有帮助。此外,只能创建我创建的最后一个Model对象,它之前的任何对象都会使程序崩溃。

这是Model对象的代码:

#include "Model.h"
#include <iostream>
#include <string>



Model::Model() {

    drawMode = 0;


    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO); 
    glGenBuffers(1, &EBO);

    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, NULL, NULL, GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, NULL, NULL, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
    glEnableVertexAttribArray(0);
    glBindVertexArray(0);
}

Model::~Model() {
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    glDeleteBuffers(1, &EBO);
}

void Model::addVertex(GLfloat x, GLfloat y, GLfloat z) {
    vertices.push_back(x);
    vertices.push_back(y);
    vertices.push_back(z);
    update();
}

void Model::addIndex(int i, int j, int k) {
    indices.push_back(i);
    indices.push_back(j);
    indices.push_back(k);


}
void Model::setShader(GLuint& shader) {
    shaderProgram = &shader;
}



void Model::clearModel() {
    vertices.clear();
    indices.clear();
}

int Model::sizeOfVertices() {
    return sizeof(GLfloat)*vertices.size();
}
int Model::sizeOfIndices() {
    return sizeof(GLuint)*(indices.size());
}

void Model::draw() {
    glUseProgram(*shaderProgram);
    GLuint transformLoc = glGetUniformLocation(*shaderProgram, "model");
    glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(model));


    glBindVertexArray(VAO);
    switch (drawMode) {
    case 0: glDrawArrays(GL_POINTS, 0, vertices.size() / 3);
        break;
    case 1: glDrawArrays(GL_LINE_STRIP, 0, vertices.size() / 3);
        break;
    case 2: glDrawArrays(GL_TRIANGLES, 0, vertices.size() / 3);
        break;
    case 3: glDrawArrays(GL_TRIANGLE_STRIP, 0, vertices.size() / 3);
        break;
    default: break;
    }

    glBindVertexArray(0); 

}

void Model::setDrawMode(int type) {
    drawMode = type;
}


void Model::move(glm::vec3 translation) {
    model = glm::translate(model, translation);
}
void Model::rotate(float degrees,glm::vec3 axis) {
    model = glm::rotate(model, degrees,axis);
}

void Model::update() {
    glBindVertexArray(0);
    glBindVertexArray(VAO);

    glBufferData(GL_ARRAY_BUFFER, NULL, NULL, GL_STATIC_DRAW);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, NULL, NULL, GL_STATIC_DRAW);

    glBufferData(GL_ARRAY_BUFFER, sizeOfVertices(), &vertices[0], GL_STATIC_DRAW);


    glEnableVertexAttribArray(0);
    glBindVertexArray(0);

}

Model类中包含一个EBO,但我还没有使用它,因为我想找出问题。

Model.h:

#pragma once

#include <vector>;
#include <glew.h>;

#include "glm.hpp"
#include "gtc/matrix_transform.hpp"
#include "gtc/type_ptr.hpp"
#include "gtc/constants.hpp"

class Model {
public:
    int drawMode;
    GLuint VAO;
    GLuint VBO;
    GLuint EBO;
    GLuint *shaderProgram;
    std::vector<GLfloat> vertices;
    std::vector<GLuint> indices;

    glm::mat4 model;

    Model();
    ~Model();

    void addVertex(GLfloat, GLfloat, GLfloat);
    void addIndex(int, int, int);

    void setShader(GLuint&);

    void clearModel();

    int sizeOfVertices();
    int sizeOfIndices();

    void draw();
    void setDrawMode(int);

    void move(glm::vec3);
    void rotate(float, glm::vec3);

    void update();
};

主要课程:

#include <iostream>
#include <string>
#include <fstream>


#include <vector>

#include "Callbacks.h"
#include "Shader.h"
#include "GlState.h"
#include "Model.h"

#include <glew.h>
#include <glfw3.h>
#include "glm.hpp"
#include "gtc/matrix_transform.hpp"
#include "gtc/type_ptr.hpp"
#include "gtc/constants.hpp"



Model *model;
Model *model2;
Model *model3;

void mainLoop(GLFWwindow* window) {
    glfwPollEvents();
//RENDER UNDER HERE
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glPointSize(5);


        Callbacks::update(model3);
        model3->draw();
        model2->draw();
        model->draw();



    glfwSwapBuffers(window);

}


int main() {
    GLFWwindow* window = GlState::Initialize(800,600);
    GLuint shaderProgram = Shader::makeProgram("vertex.vs", "fragment1.fs");
    GLuint shaderProgram2 = Shader::makeProgram("vertex.vs", "fragment2.fs");
    model = new Model();
    model2 = new Model();
    model3 = new Model();


    model->setShader(shaderProgram);
    model2->setShader(shaderProgram);
    model3->setShader(shaderProgram2);


    while (!glfwWindowShouldClose(window))
    {

        mainLoop(window);

    }

    delete(model);
    delete(model2);
    delete(model3);
    glfwTerminate();
    return 0;
}

我还将包含Callbacks的重要部分,它由update(Model * m)调用

void Callbacks::checkMouse(Model* m) {
    if (leftMousePressed) {
        if (tics == 0) {
            m->addVertex(2*(mouseXCurrent-0.5), 2*(0.5-mouseYCurrent), 0.0f);

        }
    tics++;
    }
}

我还没有设置相机,所以它在默认的正交视图中。

由于我只能在最后一个模型对象中添加点而不会崩溃(在本例中为model3),我认为它必须与这些模型的启动方式有关,但我无法弄清楚是什么!这让我疯了。

这是一个崩溃的例子:

在main中的代码段之后:

    model->setShader(shaderProgram);
    model2->setShader(shaderProgram);
    model3->setShader(shaderProgram2);

如果您输入     模型 - &GT; addVertex(0.1F,0.2F,0.0F); 要么     model2-&GT; addVertex(0.1F,0.2F,0.0F);

程序会崩溃,但是

model3->addVertex(0.1f,0.2f,0.0f);

没有问题

2 个答案:

答案 0 :(得分:0)

代码将崩溃,因为您正在访问缓冲区之外的数据。在构造函数中,您创建大小为NULL的缓冲区:

glBufferData(GL_ARRAY_BUFFER, NULL, NULL, GL_STATIC_DRAW)

请注意,指针类型NULL对于该调用的size参数完全无效,但这不是问题。

当您调用addVertex方法时,您会将数据附加到std::vector,但不会附加到VBO 。 Yo永远不会调用实际将数据传输到缓冲区的update方法,因此您的属性指针仍指向0大小的缓冲区,当从中绘制多于0个顶点时,您只是处于未定义的行为土地。

答案 1 :(得分:0)

所以我发现了问题所在。在更新方法中,我会绑定VAO,问题是我认为这也绑定了VBO进行编辑,这显然从未发生过。所以当我打电话时

glBufferData(GL_ARRAY_BUFFER, sizeOfVertices(), &vertices[0], GL_STATIC_DRAW);

我以为我正在修改VAO中的VBO,但实际上我正在修改最后的VBO界限。 VBO绑定的最后一次是在构造函数中,所以这就是为什么我只能修改最后创建的Model对象,而其他的会崩溃,因为我会绑定他们的VAO并尝试修改另一个Model&#39; s VBO。

至少我认为这是问题所在,因为我现在没有错误,因为我正在调用

    glBindBuffer(GL_ARRAY_BUFFER, VBO);

在我修改它之前。