c++ - 在类中渲染 OpenGL 对象?

标签 c++ opengl

我正在尝试学习现代 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(...),但它也没有用。如果需要,我也可以提供主要代码。

此外,顶点着色器没有做任何事情。它只是接收顶点信息并将其提供给 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中是 View setupGL方法,在MacOS Cocoa中是prepareOpenGL,其他系统是第一个窗口绘制。

第二个问题,正如 BDL 所指出的,是 sizeof(objectVerts) 并没有按照您的想法去做。一份打印声明将显示给您。

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

关于c++ - 在类中渲染 OpenGL 对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41626421/

相关文章:

C++11 关于 *begin(a)

c++ - 绑定(bind)成员函数的正确方法?

c++ - 在 OpenGL 中连续暂停

c - 海龟用 openGl 绘制分形

c++ - 在递归下降解析器中使用第一集

c++ - boost::asio::async_write 混合来自两条消息的数据(错误)

c++ - 哪些 C 结构出现在 std 命名空间中?

c++ - OpenGL/C++ - 如何填充鼠标单击点周围的区域?

c++ - 四元数旋转opengl

c++ - OpenGL - 让着色器编译时出现问题