【发布时间】:2016-02-13 08:33:38
【问题描述】:
我正在学习 openGL,我正在尝试做一些非常简单的事情。我有一个名为 Model 的图形对象,它包含一个用于顶点的 GLfloats 向量并具有一个绘图功能。除此之外,我还有一个 addVertex 函数,它接收 3 个浮点数和一个绘制函数,它绑定对象的 VAO,然后在绘制后解除绑定。我可以毫无问题地渲染其中一个对象并向其添加点,但是我不能同时绘制多个对象而不会导致程序崩溃并且 Visual Studio 告诉我“框架不在模块中”,这没有帮助.此外,只能渲染我创建的最后一个模型对象,任何在它之前出现的对象都会使程序崩溃。
这是模型对象的代码:
#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,但我还没有使用它,因为我想隔离问题。
模型.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;
}
我还将包括回调的重要部分,由 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++;
}
}
我还没有设置相机,所以它是默认的正交视图。
由于我只能在不崩溃的情况下向最后一个模型对象添加点(在本例中为模型 3),我认为这一定与这些模型的启动方式有关,但我不知道是什么!快把我逼疯了。
这是一个崩溃的例子:
在main中的代码段之后:
model->setShader(shaderProgram);
model2->setShader(shaderProgram);
model3->setShader(shaderProgram2);
如果你输入 模型->addVertex(0.1f,0.2f,0.0f); 或者 model2->addVertex(0.1f,0.2f,0.0f);
但是程序会崩溃
model3->addVertex(0.1f,0.2f,0.0f);
没有问题
【问题讨论】:
-
到目前为止我找不到一些错误。但我注意到的一件事是,您使用 vertices.size() 函数来计算要为 glDrawArrays 调用绘制的顶点数。但是,如果您在不更新缓冲区数据的情况下更改顶点的某些数据,这可能会变得很危险,因为您可能会尝试绘制不存在的顶点。
标签: c++ opengl graphics visual-studio-2015 vao