147 lines
4.1 KiB
C++
147 lines
4.1 KiB
C++
#include <debug/assertions.hpp>
|
|
#include <glad/gl.h>
|
|
#include <renderer/gl/buffers.hpp>
|
|
#include <renderer/gl/vertex_layout.hpp>
|
|
|
|
namespace lt {
|
|
|
|
glVertexLayout::glVertexLayout(
|
|
const Ref<VertexBuffer> &buffer,
|
|
const std::vector<std::pair<std::string, VertexElementType>> &elements
|
|
)
|
|
: m_array_id()
|
|
{
|
|
// check
|
|
ensure(
|
|
std::dynamic_pointer_cast<glVertexBuffer>(buffer),
|
|
"Failed to cast 'VertexBuffer' to 'glVertexBuffer'"
|
|
);
|
|
ensure(!elements.empty(), "'elements' is empty");
|
|
|
|
// local
|
|
auto elementsDesc = std::vector<glVertexElementDesc> {};
|
|
elementsDesc.reserve(elements.size());
|
|
auto stride = 0u;
|
|
|
|
// extract elements desc
|
|
for (const auto &element : elements)
|
|
{
|
|
elementsDesc.push_back(get_element_desc(element.second, stride));
|
|
stride += elementsDesc.back().typeSize * elementsDesc.back().count;
|
|
}
|
|
|
|
// create vertex array
|
|
glCreateVertexArrays(1, &m_array_id);
|
|
|
|
// bind buffer and array
|
|
buffer->bind();
|
|
bind();
|
|
|
|
// enable vertex attributes
|
|
auto index = 0u;
|
|
for (const auto &elementDesc : elementsDesc)
|
|
{
|
|
glVertexAttribPointer(
|
|
index,
|
|
elementDesc.count,
|
|
elementDesc.type,
|
|
GL_FALSE,
|
|
stride,
|
|
(const void *)elementDesc.offset
|
|
);
|
|
glEnableVertexAttribArray(index++);
|
|
}
|
|
}
|
|
|
|
glVertexLayout::~glVertexLayout()
|
|
{
|
|
glDeleteVertexArrays(1, &m_array_id);
|
|
}
|
|
|
|
void glVertexLayout::bind()
|
|
{
|
|
glBindVertexArray(m_array_id);
|
|
}
|
|
|
|
void glVertexLayout::un_bind()
|
|
{
|
|
glBindVertexArray({});
|
|
}
|
|
|
|
auto glVertexLayout::get_element_desc(VertexElementType type, unsigned int offset)
|
|
-> glVertexElementDesc
|
|
{
|
|
switch (type)
|
|
{
|
|
/* byte */
|
|
case lt::VertexElementType::Byte1:
|
|
return { .type = GL_BYTE, .count = 1u, .typeSize = sizeof(GLbyte), .offset = offset };
|
|
case lt::VertexElementType::Byte2:
|
|
return { .type = GL_BYTE, .count = 1u, .typeSize = sizeof(GLbyte), .offset = offset };
|
|
case lt::VertexElementType::Byte4:
|
|
return { .type = GL_BYTE, .count = 1u, .typeSize = sizeof(GLbyte), .offset = offset };
|
|
|
|
/* ubyte */
|
|
case lt::VertexElementType::UByte1:
|
|
return { .type = GL_UNSIGNED_BYTE,
|
|
.count = 1u,
|
|
.typeSize = sizeof(GLubyte),
|
|
.offset = offset };
|
|
case lt::VertexElementType::UByte2:
|
|
return { .type = GL_UNSIGNED_BYTE,
|
|
.count = 2u,
|
|
.typeSize = sizeof(GLubyte),
|
|
.offset = offset };
|
|
case lt::VertexElementType::UByte4:
|
|
return { .type = GL_UNSIGNED_BYTE,
|
|
.count = 4u,
|
|
.typeSize = sizeof(GLubyte),
|
|
.offset = offset };
|
|
|
|
/* int */
|
|
case VertexElementType::Int1:
|
|
return { .type = GL_INT, .count = 1u, .typeSize = sizeof(GLint), .offset = offset };
|
|
case VertexElementType::Int2:
|
|
return { .type = GL_INT, .count = 2u, .typeSize = sizeof(GLint), .offset = offset };
|
|
case VertexElementType::Int3:
|
|
return { .type = GL_INT, .count = 3u, .typeSize = sizeof(GLint), .offset = offset };
|
|
case VertexElementType::Int4:
|
|
return { .type = GL_INT, .count = 4u, .typeSize = sizeof(GLint), .offset = offset };
|
|
|
|
/* uint */
|
|
case VertexElementType::UInt1:
|
|
return { .type = GL_UNSIGNED_INT,
|
|
.count = 1u,
|
|
.typeSize = sizeof(GLuint),
|
|
.offset = offset };
|
|
case VertexElementType::UInt2:
|
|
return { .type = GL_UNSIGNED_INT,
|
|
.count = 2u,
|
|
.typeSize = sizeof(GLuint),
|
|
.offset = offset };
|
|
case VertexElementType::UInt3:
|
|
return { .type = GL_UNSIGNED_INT,
|
|
.count = 3u,
|
|
.typeSize = sizeof(GLuint),
|
|
.offset = offset };
|
|
case VertexElementType::UInt4:
|
|
return { .type = GL_UNSIGNED_INT,
|
|
.count = 4u,
|
|
.typeSize = sizeof(GLuint),
|
|
.offset = offset };
|
|
|
|
/* float */
|
|
case VertexElementType::Float1:
|
|
return { .type = GL_FLOAT, .count = 1u, .typeSize = sizeof(GLfloat), .offset = offset };
|
|
case VertexElementType::Float2:
|
|
return { .type = GL_FLOAT, .count = 2u, .typeSize = sizeof(GLfloat), .offset = offset };
|
|
case VertexElementType::Float3:
|
|
return { .type = GL_FLOAT, .count = 3u, .typeSize = sizeof(GLfloat), .offset = offset };
|
|
case VertexElementType::Float4:
|
|
return { .type = GL_FLOAT, .count = 4u, .typeSize = sizeof(GLfloat), .offset = offset };
|
|
|
|
default: ensure(false, "Invalid 'VertexElementType'"); return {};
|
|
}
|
|
}
|
|
|
|
} // namespace lt
|