在类中渲染OpenGL对象

Render OpenGL object in a class?

本文关键字:OpenGL 对象      更新时间:2023-10-16

我正在尝试学习现代OpenGL,并为各种基元类型(如立方体、球体等)创建类。不过,我遇到了一个问题,即我的立方体类在其Draw()函数中没有渲染任何内容,但如果我将其全部移到main()函数中,它会正常工作。

以下是cube.cpp的代码:

#include "cube.h"
#include <iostream>
GLuint Cube::indexArr[36] = {
0, 1, 2, // front face
2, 3, 1,
4, 5, 6,
6, 7, 4,
7, 3, 0,
0, 4, 7,
6, 2, 1,
1, 5, 6,
0, 1, 5,
5, 4, 0,
3, 2, 6,
6, 7, 3
};
bool    Cube::cubeSetUp = false;
GLuint  Cube::cubeVBO = 0;
GLuint  Cube::cubeVAO = 0;
GLuint  Cube::cubeEBO = 0;
Cube::Cube()
{
if (!cubeSetUp)
SetUpCube();
//define the 8 vertices that make up a cube
objectVerts = new GLfloat[24] {
-0.5f, -0.5f, -0.5f, // front bottom left  0
0.5f, -0.5f, -0.5f, // front bottom right 1
0.5f,  0.5f, -0.5f, // front top right    2
-0.5f,  0.5f, -0.5f, // front top left     3
-0.5f, -0.5f, 0.5f, // back bottom left   4
0.5f, -0.5f, 0.5f, // back bottom right  5
0.5f,  0.5f, 0.5f, // back top right     6
-0.5f,  0.5f, 0.5f  // back top left      7
};
}
void Cube::Draw()
{
glBindVertexArray(cubeVAO);
//GLfloat modelMatrix[16];
//transform.affine.ConvertToOpenGLMatrix(modelMatrix);
//glUniformMatrix4fv(modelMatrixLoc, 1, GL_FALSE, modelMatrix);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);   
glBindVertexArray(0);
}

void Cube::SetUpCube()
{
cubeSetUp = true;
glGenVertexArrays(1, &cubeVAO);
glGenBuffers(1, &cubeVBO);
glGenBuffers(1, &cubeEBO);
glBindVertexArray(cubeVAO);
glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(objectVerts), objectVerts, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cubeEBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexArr), indexArr, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}

cube.h:的代码

#ifndef __CUBE__H_
#define __CUBE__H_
#include "scene_object.h"
class Cube : public SceneObject
{
public:
/***************
* Constructor *
***************/
Cube();
/***********************
* Overloaded Function *
***********************/
void Draw();
private:
static GLuint  indexArr[36];
static bool    cubeSetUp;
static GLuint  cubeVBO, cubeVAO, cubeEBO;
void SetUpCube();
};
#endif

我做错什么了吗?OpenGL是否不同意使用静态数组作为索引数组?我试着去掉元素缓冲区对象,只使用glDrawArrays(...),但它也不起作用。如果需要的话,我也可以提供main的代码。

此外,顶点着色器没有执行任何操作。它只接收顶点信息并将其提供给gl_Position

谢谢你的帮助。

main.cpp:的代码

#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <fstream>
#include <string>
#include "shader.h"
#include "cube.h"
#include "camera.h"
using namespace std;
int main(int argc, char* argv[])
{
if (argc != 3)
{
cout << "Incorrect number of arguments!" << endl;
cout << "Usage: [executable] vertexShader fragmentShader" << endl;
return -1;
}
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
GLFWwindow* window = glfwCreateWindow(800, 600, "Scene Description Language Generator", nullptr, nullptr);
if (window == nullptr)
{
std::cout << "Failed to create the GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK)
{
std::cout << "Failed to initialize GLEW" << std::endl;
return -1;
}
glEnable(GL_DEPTH_TEST);
int width, height;
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
Shader shader(argv[1], argv[2]);
Cube c;
GLuint modelMat = glGetUniformLocation(shader.GetProgram(), "model");
c.SetModelMatrixLoc(modelMat);
while (!glfwWindowShouldClose(window))
{
glfwPollEvents();
glClearColor(0.2f, 0.3f, 0.3f, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
shader.Use();
c.Draw();
glfwSwapBuffers(window);
}
glfwTerminate();
return 0;
}

编辑:添加了main.cpp和cube.h的代码,以防有价值。

至少有两件事出了问题。

首先,正如pleluron所指出的,在创建应用程序窗口和GL上下文之前,会调用多维数据集构造函数。在较旧的系统上,这通常会崩溃。在现代计算机上,窗口系统可能会创建默认的GL上下文,因此会为此创建多维数据集。然后,应用程序创建自己的窗口和上下文,多维数据集将成为孤立的。

创建OpenGL"对象"应该只在指定的方法中发生,只有在安全的情况下才能调用。在Qt中,这是视图setupGL方法,在MacOS Cocoa中,它是prepareOpenGL,而在其他系统中,它则是第一个窗口绘制。

正如BDL所指出的,第二个问题是sizeof(objectVerts)并没有做你认为它会做的事情。打印报表将显示给您。

第三个问题是您没有调用glGetError()。OpenGL在出错时不会抛出异常,而且通常不会崩溃。相反,它什么也不做。养成在每个重要函数或方法结束时调用glGetError()的习惯,以确保一切正常。如果确实发生了错误,请添加更多的glGetErrors()来缩小原因。