为了使得复杂的问题简单化,以便之后解决更加复杂的着色器,渲染器等问题,需要把顶点缓冲区和索引缓冲区抽象为类;
这样做可以提高代码的可读性,同时便于调试(类似于嵌入式的库函数文件);
目前可以抽象的类别有顶点缓冲区,索引缓冲区,顶点数组和着色器四个部分(目前还没使用纹理);
整体来说就是一个渲染器;
顶点缓冲区
float positions[] = {
-0.5f , -0.5f,
0.5f , -0.5f,
0.5f , 0.5f,
-0.5f , 0.5f
};
//-----顶点缓冲区------
unsigned int buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, 4 * 2 * sizeof(float),positions,GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);
索引缓冲区
glGenBuffers(1, &ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6*sizeof(unsigned int), indices, GL_STATIC_DRAW);
首先创建一个渲染器的头文件和CPP文件用以将所有类统一起来,这些步骤与嵌入式相似,但有所区别(因为cpp文件有类)
Render.h
#pragma once
#include <Gl/glew.h>
#include <GLFW/glfw3.h>
#define ASSERT(x) if(!x) __debugbreak();
#define GLCall(x) GLClearError();\
x;\
ASSERT(GLLogError(#x,__FILE__,__LINE__))//这里的后续不需要加封号,#x代表着转化成字符串,之后为所有单独的gl方程添加上这个宏
//获取错误类型,这种方式有点笨
void GLClearError();
bool GLLogError(const char* function, const char* file, int line);
Render.cpp
#include "Render.h"
#include <iostream>
void GLClearError()
{
while (glGetError() != GL_NO_ERROR);
}
bool GLLogError(const char* function, const char* file, int line)
{
while (GLenum error = glGetError())
{
std::cout << "[OpenGL_Error](" << error << ")" << function << " " << file << ":" << line << std::endl;
return false;
}
return true;
}
创建好之后,分别创建顶点缓冲区和索引缓冲区的cpp文件和头文件,暂时类里面只包含构造函数,析构函数和绑定与解除绑定的函数
VertexBuffer.h
#pragma once
class VertexBuffer
{
private:
unsigned int m_RendererID;
public:
VertexBuffer(const void* data, unsigned int size);
~VertexBuffer();
void Bind();
void Unbind();
};
VertexBuffer.cpp
#include "VertexBuffer.h"
#include "Render.h"
VertexBuffer::VertexBuffer(const void* data, unsigned int size)
{
GLCall(glGenBuffers(1, &m_RendererID));
GLCall(glBindBuffer(GL_ARRAY_BUFFER, m_RendererID));
GLCall(glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW));
}
VertexBuffer::~VertexBuffer()
{
GLCall(glDeleteBuffers(1, &m_RendererID));
}
void VertexBuffer::Bind()
{
GLCall(glBindBuffer(GL_ARRAY_BUFFER, m_RendererID));
}
void VertexBuffer::Unbind()
{
GLCall(glBindBuffer(GL_ARRAY_BUFFER, 0));
}
IndexBuffer.h 相比于顶点缓冲区,我需要一个顶点的数量 以及获取返回数量的函数
#pragma once
class IndexBuffer
{
private:
unsigned int m_RendererID;
unsigned int m_Count;
public:
IndexBuffer(const unsigned int* data, unsigned int count);
~IndexBuffer();
void Bind() const;
void Unbind() const;
inline unsigned int GetCount() const { return m_Count; }
};
IndexBuffer.cpp
#include "IndexBuffer.h"
#include "Render.h"
IndexBuffer::IndexBuffer(const unsigned int* data, unsigned int count)
:m_Count(count)
{
ASSERT(sizeof(unsigned int) == sizeof(GLuint));
GLCall(glGenBuffers(1, &m_RendererID));
GLCall(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_RendererID));
GLCall(glBufferData(GL_ELEMENT_ARRAY_BUFFER, count * sizeof(unsigned int), data, GL_STATIC_DRAW));
}
IndexBuffer::~IndexBuffer()
{
GLCall(glDeleteBuffers(1, &m_RendererID));
}
void IndexBuffer::Bind() const
{
GLCall(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_RendererID));
}
void IndexBuffer::Unbind() const
{
GLCall(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
}
全部文件构建好之后,在主文件开头申明头文件,就可以使用这些类来创建和绑定缓冲区了