diff --git a/assets/glsl/simple.frag b/assets/glsl/simple.frag index 9c82fcc..4765eb3 100644 --- a/assets/glsl/simple.frag +++ b/assets/glsl/simple.frag @@ -2,9 +2,10 @@ layout(location = 0) out vec4 color; -in vec3 position; +in vec3 p_position; +in vec4 p_color; void main() { - color = vec4(position * 0.5f + 0.5f, 1.0f); + color = p_color; } diff --git a/assets/glsl/simple.vert b/assets/glsl/simple.vert index da47089..80fbcf2 100644 --- a/assets/glsl/simple.vert +++ b/assets/glsl/simple.vert @@ -1,11 +1,14 @@ #version 450 core layout(location = 0) in vec3 a_position; +layout(location = 1) in vec4 a_color; -out vec3 position; +out vec3 p_position; +out vec4 p_color; void main() { - position = a_position; + p_position = a_position; + p_color = a_color; gl_Position = vec4(a_position, 1.0f); } diff --git a/inferno/src/inferno/render/buffer.cpp b/inferno/src/inferno/render/buffer.cpp index c820e24..dd69008 100644 --- a/inferno/src/inferno/render/buffer.cpp +++ b/inferno/src/inferno/render/buffer.cpp @@ -1,9 +1,116 @@ #include +#include "inferno/core.h" +#include "inferno/log.h" #include "inferno/render/buffer.h" namespace Inferno { +// ----------------------------------------- + + BufferElement::BufferElement(BufferElementType type, std::string name, bool normalized) : + m_type(type), + m_name(name), + m_size(BufferElement::getTypeSize(type)), + m_offset(0), + m_normalized(normalized) + { + } + + uint32_t BufferElement::getTypeSize() const + { + return BufferElement::getTypeSize(m_type); + } + + uint32_t BufferElement::getTypeCount() const + { + return BufferElement::getTypeCount(m_type); + } + + uint32_t BufferElement::getTypeGL() const + { + return BufferElement::getTypeGL(m_type); + } + + uint32_t BufferElement::getTypeSize(const BufferElementType type) + { + switch (type) { + case BufferElementType::None: return 0; + case BufferElementType::Int: return sizeof(int32_t); + case BufferElementType::Int2: return sizeof(int32_t) * 2; + case BufferElementType::Int3: return sizeof(int32_t) * 3; + case BufferElementType::Int4: return sizeof(int32_t) * 4; + case BufferElementType::Mat3: return sizeof(float) * 3 * 3; + case BufferElementType::Mat4: return sizeof(float) * 4 * 4; + case BufferElementType::Vec: return sizeof(float); + case BufferElementType::Vec2: return sizeof(float) * 2; + case BufferElementType::Vec3: return sizeof(float) * 3; + case BufferElementType::Vec4: return sizeof(float) * 4; + }; + + NF_CORE_ASSERT(false, "BufferElement unknown BufferElementType size!"); + return 0; + } + + uint32_t BufferElement::getTypeCount(const BufferElementType type) + { + switch (type) { + case BufferElementType::None: return 0; + case BufferElementType::Int: return 1; + case BufferElementType::Int2: return 2; + case BufferElementType::Int3: return 3; + case BufferElementType::Int4: return 4; + case BufferElementType::Mat3: return 3 * 3; + case BufferElementType::Mat4: return 4 * 4; + case BufferElementType::Vec: return 1; + case BufferElementType::Vec2: return 2; + case BufferElementType::Vec3: return 3; + case BufferElementType::Vec4: return 4; + }; + + NF_CORE_ASSERT(false, "BufferElement unknown BufferElementType count!"); + return 0; + } + + uint32_t BufferElement::getTypeGL(const BufferElementType type) + { + switch (type) { + case BufferElementType::None: return GL_NONE; + case BufferElementType::Int: return GL_INT; + case BufferElementType::Int2: return GL_INT; + case BufferElementType::Int3: return GL_INT; + case BufferElementType::Int4: return GL_INT; + case BufferElementType::Mat3: return GL_FLOAT; + case BufferElementType::Mat4: return GL_FLOAT; + case BufferElementType::Vec: return GL_FLOAT; + case BufferElementType::Vec2: return GL_FLOAT; + case BufferElementType::Vec3: return GL_FLOAT; + case BufferElementType::Vec4: return GL_FLOAT; + }; + + NF_CORE_ASSERT(false, "BufferElement unknown BufferElementType GL!"); + return 0; + } + +// ----------------------------------------- + + BufferLayout::BufferLayout(const std::initializer_list &elements) : + m_elements(elements), m_stride(0) + { + this->calculateOffsetsAndStride(); + } + + void BufferLayout::calculateOffsetsAndStride() + { + m_stride = 0; + for (auto &element : m_elements) { + element.setOffset(m_stride); + m_stride += element.getSize(); + } + } + +// ----------------------------------------- + VertexBuffer::VertexBuffer(float* vertices, size_t size) { glCreateBuffers(1, &m_id); @@ -11,6 +118,8 @@ namespace Inferno { // Upload data to the GPU glBufferData(GL_ARRAY_BUFFER, size, vertices, GL_STATIC_DRAW); + + this->unbind(); } VertexBuffer::~VertexBuffer() @@ -38,6 +147,8 @@ namespace Inferno { // Upload data to the GPU glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, indices, GL_STATIC_DRAW); + + this->unbind(); } IndexBuffer::~IndexBuffer() @@ -55,4 +166,61 @@ namespace Inferno { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } +// ----------------------------------------- + + VertexArray::VertexArray() + { + glCreateVertexArrays(1, &m_id); + } + + VertexArray::~VertexArray() + { + glDeleteVertexArrays(1, &m_id); + } + + void VertexArray::bind() const + { + glBindVertexArray(m_id); + } + + void VertexArray::unbind() const + { + glBindVertexArray(0); + } + + void VertexArray::addVertexBuffer(const std::shared_ptr &vertexBuffer) + { + this->bind(); + vertexBuffer->bind(); + + uint32_t index = 0; + for (const auto &element : vertexBuffer->getLayout()) { + glEnableVertexAttribArray(index); + glVertexAttribPointer( + index, + element.getTypeCount(), + element.getTypeGL(), + element.getNormalized() ? GL_TRUE : GL_FALSE, + vertexBuffer->getLayout().getStride(), + (const void*)element.getOffset()); + + index++; + } + m_vertexBuffers.push_back(vertexBuffer); + + this->unbind(); + vertexBuffer->unbind(); + } + + void VertexArray::setIndexBuffer(const std::shared_ptr &indexBuffer) + { + this->bind(); + indexBuffer->bind(); + + m_indexBuffer = indexBuffer; + + this->unbind(); + indexBuffer->unbind(); + } + } diff --git a/inferno/src/inferno/render/buffer.h b/inferno/src/inferno/render/buffer.h index fa3bff6..f4121a3 100644 --- a/inferno/src/inferno/render/buffer.h +++ b/inferno/src/inferno/render/buffer.h @@ -3,10 +3,81 @@ #include // std::size_t #include // std::uint32_t +#include // std::shared_ptr +#include // std::string +#include // std::vector namespace Inferno { - // GPU memory which holds the raw vertex data + enum class BufferElementType { + None = 0, + Int, Int2, Int3, Int4, + Mat3, Mat4, + Vec, Vec2, Vec3, Vec4, + }; + +// ----------------------------------------- + + // Describes one element of the BufferLayout + class BufferElement { + public: + BufferElement(BufferElementType type, std::string name, bool normalized = false); + + uint32_t getTypeSize() const; + uint32_t getTypeCount() const; + uint32_t getTypeGL() const; + static uint32_t getTypeSize(const BufferElementType type); + static uint32_t getTypeCount(const BufferElementType type); + static uint32_t getTypeGL(const BufferElementType type); + + inline BufferElementType getType() const{ return m_type; } + inline std::string getName() const { return m_name; } + inline uint32_t getSize() const { return m_size; } + inline uint32_t getOffset() const { return m_offset; } + inline bool getNormalized() const { return m_normalized; } + + inline void setType(const BufferElementType &type) { m_type = type; } + inline void setName(const std::string &name) { m_name = name; } + inline void setSize(const uint32_t &size) { m_size = size; } + inline void setOffset(const uint32_t &offset) { m_offset = offset; } + inline void setNormalized(const bool &normalized) { m_normalized = normalized; } + + private: + BufferElementType m_type; + std::string m_name; + uint32_t m_size; + uint32_t m_offset; + bool m_normalized; + }; + +// ----------------------------------------- + + // Layout that describes raw vertex data + class BufferLayout { + public: + BufferLayout() {} + BufferLayout(const std::initializer_list &elements); + + inline const std::vector &getElements() const { return m_elements; } + inline uint32_t getStride() const { return m_stride; } + + // Iterators + std::vector::iterator begin() { return m_elements.begin(); } + std::vector::iterator end() { return m_elements.end(); } + std::vector::const_iterator begin() const { return m_elements.begin(); } + std::vector::const_iterator end() const { return m_elements.end(); } + + protected: + void calculateOffsetsAndStride(); + + private: + std::vector m_elements; + uint32_t m_stride; + }; + +// ----------------------------------------- + + // GPU memory which holds raw vertex data class VertexBuffer { public: VertexBuffer(float* vertices, size_t size); @@ -15,8 +86,13 @@ namespace Inferno { void bind() const; void unbind() const; + inline BufferLayout const &getLayout() const { return m_layout; } + + inline void setLayout(const BufferLayout &layout) { m_layout = layout; } + private: uint32_t m_id; + BufferLayout m_layout; }; // ----------------------------------------- @@ -30,8 +106,6 @@ namespace Inferno { void bind() const; void unbind() const; -// ----------------------------------------- - inline uint32_t getCount() const { return m_count; } private: @@ -39,6 +113,28 @@ namespace Inferno { uint32_t m_count; }; +// ----------------------------------------- + + // Array that holds the vertex attributes configuration + class VertexArray { + public: + VertexArray(); + ~VertexArray(); + + void bind() const; + void unbind() const; + + void addVertexBuffer(const std::shared_ptr &vertexBuffer); + void setIndexBuffer(const std::shared_ptr &indexBuffer); + + const std::vector> &getVertexBuffers() const { return m_vertexBuffers; } + const std::shared_ptr &getIndexBuffer() const { return m_indexBuffer; } + + private: + uint32_t m_id; + std::vector> m_vertexBuffers; + std::shared_ptr m_indexBuffer; + }; } #endif // BUFFER_H