146 lines
		
	
	
	
		
			4.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			146 lines
		
	
	
	
		
			4.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include <lt_debug/assertions.hpp>
 | |
| #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
 |