VAO被删除而不调用glDeleteVertexArrays()

时间:2017-09-29 19:26:47

标签: c++ opengl glfw

我刚刚开始学习OpenGL,我目前正在尝试应用我在小型游戏架构中获得的OpenGL知识,但我很难用Classes完成这项工作。我试图在屏幕上显示一个三角形,使用一个单独的类,如下所示: CubeModel.h

 #pragma once
 #include <vector>
 #include <glad\glad.h>

 class CubeModel
 {
 public:
     //x y and z are dimensions of the cube
     CubeModel();
     CubeModel( float x, float y, float z);
     ~CubeModel();

     void Bind();
     void Unbind();

private:

     unsigned int m_VAO, m_VBO;

     std::vector<float> m_vertices = {
        -0.5f, -0.5f, 0.0f,
         0.5f, -0.5f, 0.0f,
         0.0f,  0.5f, 0.0f
     };

     std::vector<float> m_vertices2 = {
        -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,
         0.5f, -0.5f, -0.5f,  1.0f, 0.0f,
         0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
         0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
        -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,

        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
         0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 1.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 1.0f,
        -0.5f,  0.5f,  0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,

        -0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
        -0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
        -0.5f,  0.5f,  0.5f,  1.0f, 0.0f,

         0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
         0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
         0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
         0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
         0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 0.0f,

        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
         0.5f, -0.5f, -0.5f,  1.0f, 1.0f,
         0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
         0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,

        -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,
         0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
        -0.5f,  0.5f,  0.5f,  0.0f, 0.0f,
        -0.5f,  0.5f, -0.5f,  0.0f, 1.0f
    };
};

CubeModel.cpp

#include "CubeModel.h"

CubeModel::CubeModel()
{
    CubeModel(1.0f, 1.0f, 1.0f);
}

CubeModel::CubeModel(float x, float y, float z)
{
    unsigned int VAO, VBO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);

    glBindVertexArray(VAO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertices[0]) * m_vertices.size(), 
    m_vertices.data(), GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

    glBindVertexArray(0);

    m_VAO = VAO;
    m_VBO = VBO;
}

CubeModel::~CubeModel()
{
    glDeleteVertexArrays(1, &m_VAO);
    glDeleteBuffers(1, &m_VBO);
}

void CubeModel::Bind()
{
    glBindVertexArray(m_VAO);
}

void CubeModel::Unbind()
{
    glBindVertexArray(0);
}

Game_State.h(使用CubeModel):

#pragma once
#include "Window.h"
#include "Shader.h"
#include "CubeModel.h"

#define TIMESTEP 1.0f/100.0f

class Game_State
{
public:
    Game_State();
    ~Game_State();

    int             Run();
    bool            IsDone();

private:
    void            HandleInput();
    void            Update(double deltatime);
    void            Render();

    Window          m_window;
    double          m_elapsedTime = 0;
    Shader          m_cubeShader;
    CubeModel       m_testCube;
};

Game_State.cpp:

#include "Game_State.h"

Game_State::Game_State()
    : m_window("Title to be determined...", glm::vec2(1920, 1080))
    , m_cubeShader("cubeshader.vs","cubeshader.fs")
{
}

Game_State::~Game_State()
{
}

int Game_State::Run()
{

    while (m_elapsedTime > TIMESTEP)
    {
        m_elapsedTime -= TIMESTEP;
        HandleInput();
        Update(m_elapsedTime);
    }

    Render();

    m_elapsedTime += glfwGetTime();
    glfwSetTime(0.0f);

    return 0;
}

void Game_State::Update(double deltatime)
{
    m_window.Update();
}

void Game_State::Render()
{

    m_window.BeginDraw(0.7f, 0.5f, 0.3f, 1.0f);

    m_cubeShader.use();

    m_testCube.Bind();
    glDrawArrays(GL_TRIANGLES, 0, 6);

    m_testCube.Unbind();

    m_window.EndDraw();

}

void Game_State::HandleInput()
{
    if (glfwGetKey(m_window.GetWindow(), GLFW_KEY_F11) == GLFW_PRESS)
    {
        m_window.ToggleFullscreen();
    }

    if (glfwGetKey(m_window.GetWindow(), GLFW_KEY_ESCAPE) == GLFW_PRESS)
    {
        m_window.CloseWindow();
    }
}

bool Game_State::IsDone() { return m_window.IsDone(); }

当我尝试调试代码时,一切正常,VAO和VBO都有ID,但是当我在单独的渲染函数中将其绘制到屏幕之前调用bind函数时,它会将ID绑定到ID 0调用bind()的时候m_VAO和m_VBO都被重置为0,这是什么原因?!?!我已经尝试在渲染函数中直接使用这个确切的代码,它可以工作,所以渲染很好看。 (我使用GLFW和GLAD) 提前致谢! :)

2 个答案:

答案 0 :(得分:4)

此:

CubeModel::CubeModel()
{
    CubeModel(1.0f, 1.0f, 1.0f);
}

错了。这会在构造函数中创建CubeModel 临时。这与delegating the constructor不同。如果这是你想要的,你必须使用正确的C ++ 11语法:

CubeModel::CubeModel() : CubeModel(1.0f, 1.0f, 1.0f)
{}

请注意,这可能不是您唯一的问题,因为您忽略了发布所有代码。

例如,CubeModel在技术上是可复制的,但不应该。您没有特别允许复制(从本质上讲,必须创建新的VAO和缓冲区,并从其他VAO /缓冲区复制数据)。因此,您需要删除复制操作,并编写适当的移动操作:

CubeModel(const CubeModel &) = delete;
CubeModel(CubeModel &&other) : m_VAO(other.m_VAO), m_VBO(other.m_VBO)
{
  other.m_VAO = 0;
  other.m_VBO = 0;
}

为移动分配操作做类似的事情。或者只是将其视为无法分配。

答案 1 :(得分:1)

在C ++中,你不能像在这里那样从另一个构造函数中调用构造函数:

CubeModel::CubeModel()
{
    CubeModel(1.0f, 1.0f, 1.0f);
}

这里实际发生的是你创建一个临时的,未命名的CubeModel,当剩下默认构造函数时,它会被删除。那是你的VAO被删除的时候。

如果您不想在两个函数中复制代码,则需要编写一个新方法并从两个构造函数中调用该方法。