我在ubuntu 18.4的qt5中使用了opengl,我想加载一个简单的多维数据集(存储在.obj文件中)并进行渲染。我在这里http://www.opengl-tutorial.org/beginners-tutorials/tutorial-7-model-loading/遵循了该教程,但是最后我得到了一个黑色的窗口。这是我的代码,非常感谢:
myopengl.hpp
class MyOpenGL : public QOpenGLWidget, protected QOpenGLFunctions
{
public:
MyOpenGL(const QString& obj_file);
protected:
virtual void initializeGL() Q_DECL_OVERRIDE;
virtual void paintGL() Q_DECL_OVERRIDE;
virtual void resizeGL(int width, int height) Q_DECL_OVERRIDE;
void CheckGLerror();
private:
std::vector< glm::vec3 > vertices;
std::vector< glm::vec2 > uvs;
std::vector< glm::vec3 > normals;
/* Render data */
GLuint VAO, VBO, EBO;
};
myopengl.cpp
MyOpenGL ::MyOpenGL (const QString& obj_file) :
VAO(0),
VBO(0),
EBO(0)
{
std::vector< unsigned int > vertex_indices, uv_indices, normal_indices;
std::vector< glm::vec3 > temp_vertices;
std::vector< glm::vec2 > temp_uvs;
std::vector< glm::vec3 > temp_normals;
//parse obj file
QFile file(obj_file);
file.open(QFile::ReadOnly | QFile::Text);
QTextStream in(&file);
while(!in.atEnd()) {
QString line = in.readLine();
QStringList list = line.replace(",","").split(' ', QString::SkipEmptyParts);
if (list.size() >= 3) {
if (list.at(0) == "v") { //veertex
bool ok1, ok2, ok3;
float v1 = list.at(1).toFloat(&ok1);
float v2 = list.at(2).toFloat(&ok2);
float v3 = list.at(3).toFloat(&ok3);
if (ok1 && ok2 && ok3) {
glm::vec3 vertex;
vertex.x = v1;
vertex.y = v2;
vertex.z = v3;
temp_vertices.push_back(vertex);
}
} else if (list.at(0) == "vn") {
bool ok1, ok2, ok3;
float v1 = list.at(1).toFloat(&ok1);
float v2 = list.at(2).toFloat(&ok2);
float v3 = list.at(3).toFloat(&ok3);
if (ok1 && ok2 && ok3) {
glm::vec3 normal;
normal.x = v1;
normal.y = v2;
normal.z = v3;
temp_normals.push_back(normal);
}
} else if (list.at(0) == "vt") {
bool ok1, ok2;
float v1 = list.at(1).toFloat(&ok1);
float v2 = list.at(2).toFloat(&ok2);
if (ok1 && ok2) {
glm::vec2 uv;
uv.x = v1;
uv.y = v2;
temp_uvs.push_back(uv);
}
} else if (list.at(0) == "f") {
bool f_ok1, f_ok2, f_ok3;
bool t_ok1, t_ok2, t_ok3;
bool n_ok1, n_ok2, n_ok3;
unsigned int v_index1, v_index2, v_index3;
unsigned int t_index1, t_index2, t_index3;
unsigned int n_index1, n_index2, n_index3;
QStringList f_list = list.at(1).split('/');
if (f_list.size() >= 3) {
v_index1 = f_list.at(0).toUInt(&f_ok1);
if (f_ok1) {
v_index1 -= 1;
}
t_index1 = f_list.at(1).toUInt(&t_ok1);
if (t_ok1) {
t_index1 -= 1;
}
n_index1 = f_list.at(2).toUInt(&n_ok1);
if (n_ok1) {
n_index1 -= 1;
}
}
f_list = list.at(2).split('/');
if (f_list.size() >= 3) {
v_index2 = f_list.at(0).toUInt(&f_ok2);
if (f_ok2) {
v_index2 -= 1;
}
t_index2 = f_list.at(1).toUInt(&t_ok2);
if (t_ok2) {
t_index2 -= 1;
}
n_index2 = f_list.at(2).toUInt(&n_ok2);
if (n_ok2) {
n_index2 -= 1;
}
}
f_list = list.at(3).split('/');
if (f_list.size() >= 3) {
v_index3 = f_list.at(0).toUInt(&f_ok3);
if (f_ok3) {
v_index3 -= 1;
}
t_index3 = f_list.at(1).toUInt(&t_ok3);
if (t_ok3) {
t_index3 -= 1;
}
n_index3 = f_list.at(2).toUInt(&n_ok3);
if (n_ok3) {
n_index3 -= 1;
}
}
if (f_ok1 && f_ok2 && f_ok3 && n_ok1 && n_ok2 && n_ok3
&& t_ok1 && t_ok2 && t_ok3) {
vertex_indices.push_back(v_index1);
vertex_indices.push_back(v_index2);
vertex_indices.push_back(v_index3);
uv_indices.push_back(t_index1);
uv_indices.push_back(t_index2);
uv_indices.push_back(t_index3);
normal_indices.push_back(n_index1);
normal_indices.push_back(n_index2);
normal_indices.push_back(n_index3);
}
}
}
}
file.close();
for (unsigned int i = 0; i < vertex_indices.size(); ++i) {
glm::vec3 vertex = temp_vertices.at(vertex_indices.at(i));
vertices.push_back(vertex);
}
for (unsigned int i = 0; i < uv_indices.size(); ++i) {
glm::vec2 uv = temp_uvs.at(uv_indices.at(i));
uvs.push_back(uv);
}
for (unsigned int i = 0; i < normal_indices.size(); ++i) {
glm::vec3 normal = temp_normals.at(normal_indices.at(i));
normals.push_back(normal);
}
}
void MyOpenGL::initializeGL()
{
initializeOpenGLFunctions();
glClearColor(0.0,0.0,0.0,1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glEnable(GL_LIGHT0);
glewExperimental = GL_TRUE;
GLenum status = glewInit();
if (status != GLEW_OK)
{
glfwTerminate();
std::system("pause");
return;
}
glGenVertexArrays(1, &this->VAO);
glBindVertexArray(this->VAO);
glGenBuffers(1, &this->VBO);
glBindBuffer(GL_ARRAY_BUFFER, this->VBO);
glBufferData(GL_ARRAY_BUFFER, this->vertices.size() * sizeof(glm::vec3), &this->vertices[0], GL_STATIC_DRAW);
glBindVertexArray(0);
}
void MyOpenGL::resizeGL(int width, int height)
{
glViewport(0,0,width,height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-width/2,width/2,-height/2,height/2,-1,1);
glMatrixMode(GL_MODELVIEW);
}
void MyOpenGL::paintGL()
{
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, this->VBO);
glDrawArrays(GL_TRIANGLES, 0, vertices.size());
glDisableVertexAttribArray(0);
}
答案 0 :(得分:0)
您必须通过glVertexAttribPointer
定义一组通用顶点属性数据。
请注意,vertex buffer object只是顶点数据的数据存储。但是您必须指定如何“使用”它们。顶点属性的规范和状态存储在vertex array object中。要绘制网格时,绑定顶点数组对象就足够了:
规范:
glBindVertexArray(this->VAO);
glBindBuffer(GL_ARRAY_BUFFER, this->VBO);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
绘制:
glBindVertexArray(this->VAO);
glDrawArrays(GL_TRIANGLES, 0, vertices.size());
glBindVertexArray(0);
扩展名:
使用顶点着色器和片段着色器是否必要?我没有用它们作为电流。
如果没有着色器,则必须分别使用Fixed Function Pipeline和glVertexPointer
使用glEnableClientState( GL_VERTEX_ARRAY )
并定义固定的函数属性。
但是,由于仅使用一个属性,即属性索引为0的顶点坐标,因此仍可以通过glVertexAttribPointer
和glEnableVertexAttribArray
定义属性。
参见What are the Attribute locations for fixed function pipeline in OpenGL 4.0++ core profile?
请注意,在这种情况下,您必须使用compatibility OpenGL Context。