我正在学习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);
没有问题
答案 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);
在我修改它之前。