之前已经学习了单个shader的buffer和layout绑定,如果需要对多个vertex buffer进行绑定,则需要声明一个类的容器。
unsigned int ibo; // index buffer object
GLCall(glGenBuffers(1, &ibo));
GLCall(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo));
GLCall(glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(unsigned int), indices, GL_STATIC_DRAW)); // indices 里有六个元素,必须是 unsigned 的
//stride 实际上是一个点(比如说一个2维点是两个顶点组成,所以在这里是两个 float 类型长度)
// vertex array 给 buffer 指定 layout
unsigned int vao;//vertex array object;
GLCall(glGenVertexArrays(1, &vao));
GLCall(glBindVertexArray(vao));
首先要创建一个VertexArray类用来实现绑定buffer和layout的功能,应该包含绑定操作bind和以下代码的实现
GLCall(glEnableVertexAttribArray(0));
/* 执行此句的时候,0表示bind buffer和vao*/
GLCall(glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0));
即: (const代表修饰的函数内数值不会被改变)
m_RendererID:返回的用于标识VertexBuffer的ID
#pragma once
#include "VertexBuffer.h"
#include "VertexBufferLayout.h"
//make vertex butter and layout work
class VertexArray
{
private:
unsigned int m_RendererID;
public:
VertexArray();
~VertexArray();
void AddBuffer(const VertexBuffer& vb, const VertexBufferLayout& layout);
void Bind() const;
void UnBind() const;
};
为了方便并提高可读性,将变量写成结构体(声明顺序应与函数调用参数顺序一致)
type: vertex buffer 标识符类型
count:每个属性包含顶点个数,比如说一个position数值中,每两个顶点表明一个二维点,则count是2
normalized:是否使用归一化
struct VertexBufferElement
{
unsigned int type;
unsigned int count;//个数
unsigned char normalized;
static unsigned int GetSizeOfType(unsigned int type)
{
switch (type)
{
case GL_FLOAT: return 4;
case GL_UNSIGNED_INT: return 4;
case GL_UNSIGNED_BYTE: return 1;
}
ASSERT(false);
return 0;
}
};
m_Element:VertexBufferElement类型的vector容器
m_Stride:每个属性包含多长的数据,是一个index
class VertexBufferLayout
{
private:
std::vector<VertexBufferElement> m_Elements;
unsigned int m_Stride;
public:
VertexBufferLayout()
: m_Stride(0){}
template<typename T>
void Push(unsigned int count)
{
static_assert(false);
}
template<>
void Push<float>(unsigned int count)
{
m_Elements.push_back({ GL_FLOAT, count, GL_FALSE });
m_Stride += count * VertexBufferElement::GetSizeOfType(GL_FLOAT);
}
template<>
void Push<int>(unsigned int count)
{
m_Elements.push_back({ GL_UNSIGNED_INT, count, GL_FALSE });
m_Stride += count * VertexBufferElement::GetSizeOfType(GL_UNSIGNED_INT);
}
template<>
void Push<unsigned char>(unsigned int count)
{
m_Elements.push_back({ GL_UNSIGNED_BYTE, count, GL_TRUE });
m_Stride += count * VertexBufferElement::GetSizeOfType(GL_UNSIGNED_BYTE);
}
inline const std::vector<VertexBufferElement>& GetElements() const { return m_Elements; }
inline unsigned int GetStride() const { return m_Stride; }
};
模板Templatehttps://blog.csdn.net/qq_34878429/article/details/106919711
VertexArray.cpp进行Implement
对于主函数
VertexArray va;
VertexBuffer vb(positions, 4 * 2 * sizeof(float));
VertexBufferLayout layout;
layout.Push<float>(2); //GLCall(glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, size of(float) * 2, 0));
va.AddBuffer(vb, layout);
这样就可以实现多个buffer分别和layout绑定了