diff options
Diffstat (limited to 'src/Platform/OpenGL')
| -rw-r--r-- | src/Platform/OpenGL/OpenGLIndexBuffer.cpp | 28 | ||||
| -rw-r--r-- | src/Platform/OpenGL/OpenGLIndexBuffer.h | 22 | ||||
| -rw-r--r-- | src/Platform/OpenGL/OpenGLRendererAPI.cpp | 34 | ||||
| -rw-r--r-- | src/Platform/OpenGL/OpenGLRendererAPI.h | 19 | ||||
| -rw-r--r-- | src/Platform/OpenGL/OpenGLShader.cpp | 224 | ||||
| -rw-r--r-- | src/Platform/OpenGL/OpenGLShader.h | 47 | ||||
| -rw-r--r-- | src/Platform/OpenGL/OpenGLVertexArray.cpp | 55 | ||||
| -rw-r--r-- | src/Platform/OpenGL/OpenGLVertexArray.h | 40 | ||||
| -rw-r--r-- | src/Platform/OpenGL/OpenGLVertexBuffer.cpp | 34 | ||||
| -rw-r--r-- | src/Platform/OpenGL/OpenGLVertexBuffer.h | 25 |
10 files changed, 528 insertions, 0 deletions
diff --git a/src/Platform/OpenGL/OpenGLIndexBuffer.cpp b/src/Platform/OpenGL/OpenGLIndexBuffer.cpp new file mode 100644 index 0000000..7faee62 --- /dev/null +++ b/src/Platform/OpenGL/OpenGLIndexBuffer.cpp @@ -0,0 +1,28 @@ +#include "OpenGLIndexBuffer.h" +#include <glad/glad.h> + +namespace Donut +{ + OpenGLIndexBuffer::OpenGLIndexBuffer(const uint32_t* indices, uint32_t count) + : m_Count(count) + { + glCreateBuffers(1, &m_RendererID); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_RendererID); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, count * sizeof(uint32_t), indices, GL_STATIC_DRAW); + } + + OpenGLIndexBuffer::~OpenGLIndexBuffer() + { + glDeleteBuffers(1, &m_RendererID); + } + + void OpenGLIndexBuffer::Bind() const + { + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_RendererID); + } + + void OpenGLIndexBuffer::Unbind() const + { + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + } +}; diff --git a/src/Platform/OpenGL/OpenGLIndexBuffer.h b/src/Platform/OpenGL/OpenGLIndexBuffer.h new file mode 100644 index 0000000..0de8fb2 --- /dev/null +++ b/src/Platform/OpenGL/OpenGLIndexBuffer.h @@ -0,0 +1,22 @@ +#pragma once + +#include "Rendering/IndexBuffer.h" + +namespace Donut +{ + class OpenGLIndexBuffer + : public IndexBuffer + { + public: + OpenGLIndexBuffer(const uint32_t* indices, uint32_t count); + virtual ~OpenGLIndexBuffer(); + + virtual void Bind() const override; + virtual void Unbind() const override; + virtual uint32_t GetCount() const override { return m_Count; } + + private: + uint32_t m_RendererID; + uint32_t m_Count; + }; +}; diff --git a/src/Platform/OpenGL/OpenGLRendererAPI.cpp b/src/Platform/OpenGL/OpenGLRendererAPI.cpp new file mode 100644 index 0000000..c1c2e9b --- /dev/null +++ b/src/Platform/OpenGL/OpenGLRendererAPI.cpp @@ -0,0 +1,34 @@ +#include "OpenGLRendererAPI.h" +#include <glad/glad.h> + +namespace Donut +{ + void OpenGLRendererAPI::Init() + { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_DEPTH_TEST); + } + + void OpenGLRendererAPI::SetViewport(uint32_t x, uint32_t y, uint32_t width, uint32_t height) + { + glViewport(x, y, width, height); + } + + void OpenGLRendererAPI::SetClearColor(const glm::vec4& color) + { + glClearColor(color.r, color.g, color.b, color.a); + } + + void OpenGLRendererAPI::Clear() + { + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + } + + void OpenGLRendererAPI::DrawIndexed(const std::shared_ptr<VertexArray>& vertexArray, uint32_t indexCount) + { + uint32_t count = indexCount ? indexCount : vertexArray->GetIndexBuffer()->GetCount(); + glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, nullptr); + glBindTexture(GL_TEXTURE_2D, 0); + } +}; diff --git a/src/Platform/OpenGL/OpenGLRendererAPI.h b/src/Platform/OpenGL/OpenGLRendererAPI.h new file mode 100644 index 0000000..33547c0 --- /dev/null +++ b/src/Platform/OpenGL/OpenGLRendererAPI.h @@ -0,0 +1,19 @@ +#pragma once + +#include "Rendering/Renderer.h" +#include <glad/glad.h> + +namespace Donut +{ + class OpenGLRendererAPI + : public RendererAPI + { + public: + virtual void Init() override; + virtual void SetViewport(uint32_t x, uint32_t y, uint32_t width, uint32_t height) override; + virtual void SetClearColor(const glm::vec4& color) override; + virtual void Clear() override; + + virtual void DrawIndexed(const std::shared_ptr<VertexArray>& vertexArray, uint32_t indexCount = 0) override; + }; +}; diff --git a/src/Platform/OpenGL/OpenGLShader.cpp b/src/Platform/OpenGL/OpenGLShader.cpp new file mode 100644 index 0000000..bb75f3d --- /dev/null +++ b/src/Platform/OpenGL/OpenGLShader.cpp @@ -0,0 +1,224 @@ +#include "OpenGLShader.h" +#include <glad/glad.h> +#include <glm/gtc/type_ptr.hpp> +#include <fstream> +#include <iostream> + +namespace Donut +{ + static uint32_t ShaderTypeFromString(const std::string& type) + { + if (type == "vertex") + return GL_VERTEX_SHADER; + if (type == "fragment" || type == "pixel") + return GL_FRAGMENT_SHADER; + return 0; + } + + OpenGLShader::OpenGLShader(const std::string& filepath) + { + std::string source = ReadFile(filepath); + auto shaderSources = PreProcess(source); + Compile(shaderSources); + + auto lastSlash = filepath.find_last_of("/\\"); + lastSlash = lastSlash == std::string::npos ? 0 : lastSlash + 1; + auto lastDot = filepath.rfind('.'); + auto count = lastDot == std::string::npos ? filepath.size() - lastSlash : lastDot - lastSlash; + m_Name = filepath.substr(lastSlash, count); + } + + OpenGLShader::OpenGLShader(const std::string& name, const std::string& vertexSrc, const std::string& fragmentSrc) + : m_Name(name) + { + std::unordered_map<uint32_t, std::string> sources; + sources[GL_VERTEX_SHADER] = vertexSrc; + sources[GL_FRAGMENT_SHADER] = fragmentSrc; + Compile(sources); + } + + OpenGLShader::~OpenGLShader() + { + glDeleteProgram(m_RendererID); + } + + std::string OpenGLShader::ReadFile(const std::string& filepath) + { + std::string result; + std::ifstream in(filepath, std::ios::in | std::ios::binary); + if (in) { + in.seekg(0, std::ios::end); + size_t size = in.tellg(); + if (size != -1) { + result.resize(size); + in.seekg(0, std::ios::beg); + in.read(&result[0], size); + } + } + return result; + } + + std::unordered_map<uint32_t, std::string> OpenGLShader::PreProcess(const std::string& source) + { + std::unordered_map<uint32_t, std::string> shaderSources; + + const char* typeToken = "#type"; + size_t typeTokenLength = strlen(typeToken); + size_t pos = source.find(typeToken, 0); + while (pos != std::string::npos) { + size_t eol = source.find_first_of("\r\n", pos); + size_t begin = pos + typeTokenLength + 1; + std::string type = source.substr(begin, eol - begin); + + size_t nextLinePos = source.find_first_not_of("\r\n", eol); + pos = source.find(typeToken, nextLinePos); + shaderSources[ShaderTypeFromString(type)] = (pos == std::string::npos) ? source.substr(nextLinePos) : + source.substr(nextLinePos, pos - nextLinePos); + } + + return shaderSources; + } + + void OpenGLShader::Compile(const std::unordered_map<uint32_t, std::string>& shaderSources) + { + uint32_t program = glCreateProgram(); + std::vector<uint32_t> glShaderIDs(shaderSources.size()); + for (auto& kv : shaderSources) + { + uint32_t type = kv.first; + const std::string& source = kv.second; + + uint32_t shader = glCreateShader(type); + const char* sourceCStr = source.c_str(); + glShaderSource(shader, 1, &sourceCStr, 0); + glCompileShader(shader); + + int isCompiled = 0; + glGetShaderiv(shader, GL_COMPILE_STATUS, &isCompiled); + if (isCompiled == GL_FALSE) + { + int maxLength = 0; + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength); + std::vector<char> infoLog(maxLength); + glGetShaderInfoLog(shader, maxLength, &maxLength, &infoLog[0]); + glDeleteShader(shader); + std::cout << "Shader compilation failure!" << std::endl << infoLog.data() << std::endl; + return; + } + glAttachShader(program, shader); + glShaderIDs.push_back(shader); + } + + m_RendererID = program; + glLinkProgram(m_RendererID); + + int isLinked = 0; + glGetProgramiv(m_RendererID, GL_LINK_STATUS, (int*)&isLinked); + if (isLinked == GL_FALSE) + { + int maxLength = 0; + glGetProgramiv(m_RendererID, GL_INFO_LOG_LENGTH, &maxLength); + std::vector<char> infoLog(maxLength); + glGetProgramInfoLog(m_RendererID, maxLength, &maxLength, &infoLog[0]); + glDeleteProgram(m_RendererID); + for (auto id : glShaderIDs) + glDeleteShader(id); + std::cout << "Shader link failure!" << std::endl << infoLog.data() << std::endl; + return; + } + + for (auto id : glShaderIDs) + { + glDetachShader(m_RendererID, id); + glDeleteShader(id); + } + } + + void OpenGLShader::Bind() const + { + glUseProgram(m_RendererID); + } + + void OpenGLShader::Unbind() const + { + glUseProgram(0); + } + + void OpenGLShader::SetInt(const std::string& name, int value) + { + UploadUniformInt(name, value); + } + + void OpenGLShader::SetIntArray(const std::string& name, int* values, uint32_t count) + { + UploadUniformIntArray(name, values, count); + } + + void OpenGLShader::SetFloat(const std::string& name, float value) + { + UploadUniformFloat(name, value); + } + + void OpenGLShader::SetFloat3(const std::string& name, const glm::vec3& value) + { + UploadUniformFloat3(name, value); + } + + void OpenGLShader::SetFloat4(const std::string& name, const glm::vec4& value) + { + UploadUniformFloat4(name, value); + } + + void OpenGLShader::SetMat4(const std::string& name, const glm::mat4& value) + { + UploadUniformMat4(name, value); + } + + void OpenGLShader::UploadUniformInt(const std::string& name, int value) + { + int location = glGetUniformLocation(m_RendererID, name.c_str()); + glUniform1i(location, value); + } + + void OpenGLShader::UploadUniformIntArray(const std::string& name, int* values, uint32_t count) + { + int location = glGetUniformLocation(m_RendererID, name.c_str()); + glUniform1iv(location, count, values); + } + + void OpenGLShader::UploadUniformFloat(const std::string& name, float value) + { + int location = glGetUniformLocation(m_RendererID, name.c_str()); + glUniform1f(location, value); + } + + void OpenGLShader::UploadUniformFloat2(const std::string& name, const glm::vec2& value) + { + int location = glGetUniformLocation(m_RendererID, name.c_str()); + glUniform2f(location, value.x, value.y); + } + + void OpenGLShader::UploadUniformFloat3(const std::string& name, const glm::vec3& value) + { + int location = glGetUniformLocation(m_RendererID, name.c_str()); + glUniform3f(location, value.x, value.y, value.z); + } + + void OpenGLShader::UploadUniformFloat4(const std::string& name, const glm::vec4& value) + { + int location = glGetUniformLocation(m_RendererID, name.c_str()); + glUniform4f(location, value.x, value.y, value.z, value.w); + } + + void OpenGLShader::UploadUniformMat3(const std::string& name, const glm::mat3& matrix) + { + int location = glGetUniformLocation(m_RendererID, name.c_str()); + glUniformMatrix3fv(location, 1, GL_FALSE, glm::value_ptr(matrix)); + } + + void OpenGLShader::UploadUniformMat4(const std::string& name, const glm::mat4& matrix) + { + int location = glGetUniformLocation(m_RendererID, name.c_str()); + glUniformMatrix4fv(location, 1, GL_FALSE, glm::value_ptr(matrix)); + } +}; diff --git a/src/Platform/OpenGL/OpenGLShader.h b/src/Platform/OpenGL/OpenGLShader.h new file mode 100644 index 0000000..2ebde12 --- /dev/null +++ b/src/Platform/OpenGL/OpenGLShader.h @@ -0,0 +1,47 @@ +#pragma once + +#include "Rendering/Shader.h" +#include <unordered_map> +#include <glm/glm.hpp> + +namespace Donut +{ + class OpenGLShader + : public Shader + { + public: + OpenGLShader(const std::string& filepath); + OpenGLShader(const std::string& name, const std::string& vertexSrc, const std::string& fragmentSrc); + virtual ~OpenGLShader(); + + virtual void Bind() const override; + virtual void Unbind() const override; + + virtual void SetInt(const std::string& name, int value) override; + virtual void SetIntArray(const std::string& name, int* values, uint32_t count) override; + virtual void SetFloat(const std::string& name, float value) override; + virtual void SetFloat3(const std::string& name, const glm::vec3& value) override; + virtual void SetFloat4(const std::string& name, const glm::vec4& value) override; + virtual void SetMat4(const std::string& name, const glm::mat4& value) override; + + virtual const std::string& GetName() const override { return m_Name; } + + void UploadUniformInt(const std::string& name, int value); + void UploadUniformIntArray(const std::string& name, int* values, uint32_t count); + void UploadUniformFloat(const std::string& name, float value); + void UploadUniformFloat2(const std::string& name, const glm::vec2& value); + void UploadUniformFloat3(const std::string& name, const glm::vec3& value); + void UploadUniformFloat4(const std::string& name, const glm::vec4& value); + void UploadUniformMat3(const std::string& name, const glm::mat3& matrix); + void UploadUniformMat4(const std::string& name, const glm::mat4& matrix); + + private: + std::string ReadFile(const std::string& filepath); + std::unordered_map<uint32_t, std::string> PreProcess(const std::string& source); + void Compile(const std::unordered_map<uint32_t, std::string>& shaderSources); + + private: + uint32_t m_RendererID; + std::string m_Name; + }; +}; diff --git a/src/Platform/OpenGL/OpenGLVertexArray.cpp b/src/Platform/OpenGL/OpenGLVertexArray.cpp new file mode 100644 index 0000000..f172b9f --- /dev/null +++ b/src/Platform/OpenGL/OpenGLVertexArray.cpp @@ -0,0 +1,55 @@ +#include <glad/glad.h> +#include "OpenGLVertexArray.h" +#include "Rendering/VertexBuffer.h" +#include "Rendering/IndexBuffer.h" + +namespace Donut +{ + OpenGLVertexArray::OpenGLVertexArray() + { + glCreateVertexArrays(1, &m_RendererID); + } + + OpenGLVertexArray::~OpenGLVertexArray() + { + glDeleteVertexArrays(1, &m_RendererID); + } + + void OpenGLVertexArray::Bind() const + { + glBindVertexArray(m_RendererID); + } + + void OpenGLVertexArray::Unbind() const + { + glBindVertexArray(0); + } + + void OpenGLVertexArray::AddVertexBuffer(const std::shared_ptr<VertexBuffer>& vertexBuffer) + { + glBindVertexArray(m_RendererID); + vertexBuffer->Bind(); + + const auto& layout = vertexBuffer->GetLayout(); + for (const auto& element : layout.GetElements()) + { + glEnableVertexAttribArray(m_VertexBufferIndex); + glVertexAttribPointer(m_VertexBufferIndex, + element.count, + element.type, + element.normalized ? GL_TRUE : GL_FALSE, + layout.GetStride(), + (const void*)element.offset); + m_VertexBufferIndex++; + } + + m_VertexBuffers.push_back(vertexBuffer); + } + + void OpenGLVertexArray::SetIndexBuffer(const std::shared_ptr<IndexBuffer>& indexBuffer) + { + glBindVertexArray(m_RendererID); + indexBuffer->Bind(); + m_IndexBuffer = indexBuffer; + } +}; diff --git a/src/Platform/OpenGL/OpenGLVertexArray.h b/src/Platform/OpenGL/OpenGLVertexArray.h new file mode 100644 index 0000000..6783140 --- /dev/null +++ b/src/Platform/OpenGL/OpenGLVertexArray.h @@ -0,0 +1,40 @@ +#pragma once + +#include "Rendering/VertexArray.h" +#include <vector> +#include <memory> + +namespace Donut +{ + class VertexBuffer; + class IndexBuffer; + + class OpenGLVertexArray + : public VertexArray + { + public: + OpenGLVertexArray(); + virtual ~OpenGLVertexArray(); + + virtual void Bind() const override; + virtual void Unbind() const override; + + virtual void AddVertexBuffer(const std::shared_ptr<VertexBuffer>& vertexBuffer) override; + virtual void SetIndexBuffer(const std::shared_ptr<IndexBuffer>& indexBuffer) override; + + virtual const std::vector<std::shared_ptr<VertexBuffer>>& GetVertexBuffers() const override + { + return m_VertexBuffers; + } + + virtual const std::shared_ptr<IndexBuffer>& GetIndexBuffer() const override + { + return m_IndexBuffer; + } + private: + uint32_t m_RendererID; + uint32_t m_VertexBufferIndex = 0; + std::vector<std::shared_ptr<VertexBuffer>> m_VertexBuffers; + std::shared_ptr<IndexBuffer> m_IndexBuffer; + }; +}; diff --git a/src/Platform/OpenGL/OpenGLVertexBuffer.cpp b/src/Platform/OpenGL/OpenGLVertexBuffer.cpp new file mode 100644 index 0000000..56080c7 --- /dev/null +++ b/src/Platform/OpenGL/OpenGLVertexBuffer.cpp @@ -0,0 +1,34 @@ +#include "OpenGLVertexBuffer.h" +#include "Rendering/VertexBuffer.h" +#include <glad/glad.h> + +namespace Donut +{ + OpenGLVertexBuffer::OpenGLVertexBuffer(const void* data, uint32_t size) + { + glCreateBuffers(1, &m_RendererID); + glBindBuffer(GL_ARRAY_BUFFER, m_RendererID); + glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW); + } + + OpenGLVertexBuffer::~OpenGLVertexBuffer() + { + glDeleteBuffers(1, &m_RendererID); + } + + void OpenGLVertexBuffer::Bind() const + { + glBindBuffer(GL_ARRAY_BUFFER, m_RendererID); + } + + void OpenGLVertexBuffer::Unbind() const + { + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + + void OpenGLVertexBuffer::SetData(const void* data, uint32_t size) + { + glBindBuffer(GL_ARRAY_BUFFER, m_RendererID); + glBufferSubData(GL_ARRAY_BUFFER, 0, size, data); + } +}; diff --git a/src/Platform/OpenGL/OpenGLVertexBuffer.h b/src/Platform/OpenGL/OpenGLVertexBuffer.h new file mode 100644 index 0000000..491af6f --- /dev/null +++ b/src/Platform/OpenGL/OpenGLVertexBuffer.h @@ -0,0 +1,25 @@ +#pragma once + +#include "Rendering/VertexBuffer.h" + +namespace Donut +{ + class OpenGLVertexBuffer + : public VertexBuffer + { + public: + OpenGLVertexBuffer(const void* data, uint32_t size); + virtual ~OpenGLVertexBuffer(); + + virtual void Bind() const override; + virtual void Unbind() const override; + virtual void SetData(const void* data, uint32_t size) override; + + virtual const VertexBufferLayout& GetLayout() const override { return m_Layout; } + virtual void SetLayout(const VertexBufferLayout& layout) override { m_Layout = layout; } + + private: + uint32_t m_RendererID; + VertexBufferLayout m_Layout; + }; +}; |
