light/modules/renderer/src/gl/vertex_layout.cpp
light7734 a88aa739b1
Some checks reported errors
continuous-integration/drone/push Build was killed
fix: build issues with NULL on some compilers
2025-07-16 11:31:58 +03:30

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