diff options
Diffstat (limited to 'src/rendering')
| -rw-r--r-- | src/rendering/framebuffer.cpp | 17 | ||||
| -rw-r--r-- | src/rendering/framebuffer.h | 65 | ||||
| -rw-r--r-- | src/rendering/index_buffer.cpp | 21 | ||||
| -rw-r--r-- | src/rendering/index_buffer.h | 18 | ||||
| -rw-r--r-- | src/rendering/renderer.cpp | 64 | ||||
| -rw-r--r-- | src/rendering/renderer.h | 158 | ||||
| -rw-r--r-- | src/rendering/shader.cpp | 84 | ||||
| -rw-r--r-- | src/rendering/shader.h | 58 | ||||
| -rw-r--r-- | src/rendering/texture.cpp | 68 | ||||
| -rw-r--r-- | src/rendering/texture.h | 42 | ||||
| -rw-r--r-- | src/rendering/texture_manager.cpp | 34 | ||||
| -rw-r--r-- | src/rendering/texture_manager.h | 19 | ||||
| -rw-r--r-- | src/rendering/uniform_buffer.cpp | 23 | ||||
| -rw-r--r-- | src/rendering/uniform_buffer.h | 18 | ||||
| -rw-r--r-- | src/rendering/vertex_array.cpp | 32 | ||||
| -rw-r--r-- | src/rendering/vertex_array.h | 28 | ||||
| -rw-r--r-- | src/rendering/vertex_buffer.cpp | 21 | ||||
| -rw-r--r-- | src/rendering/vertex_buffer.h | 73 |
18 files changed, 843 insertions, 0 deletions
diff --git a/src/rendering/framebuffer.cpp b/src/rendering/framebuffer.cpp new file mode 100644 index 0000000..089c31e --- /dev/null +++ b/src/rendering/framebuffer.cpp @@ -0,0 +1,17 @@ +#include "framebuffer.h" +#include "renderer.h" + +#include "platform/opengl/opengl_framebuffer.h" + +namespace Donut +{ + auto Framebuffer::create(const FramebufferSpecification& spec) -> Ref<Framebuffer> + { + switch (Renderer::get_api()) + { + case RendererAPI::API::OpenGL: return create_ref<OpenGLFramebuffer>(spec); + } + + return nullptr; + } +}; diff --git a/src/rendering/framebuffer.h b/src/rendering/framebuffer.h new file mode 100644 index 0000000..a01a81b --- /dev/null +++ b/src/rendering/framebuffer.h @@ -0,0 +1,65 @@ +#pragma once + +#include "core/memory.h" +#include "texture.h" + +namespace Donut +{ + enum class FramebufferTextureFormat + { + None = 0, + + RGBA8, + RED_INTEGER, + + DEPTH24STENCIL8, + + Depth = DEPTH24STENCIL8 + }; + + struct FramebufferTextureSpecification + { + FramebufferTextureSpecification() = default; + FramebufferTextureSpecification(FramebufferTextureFormat format) + : texture_format(format) {} + + FramebufferTextureFormat texture_format = FramebufferTextureFormat::None; + }; + + struct FramebufferAttachmentSpecification + { + FramebufferAttachmentSpecification() = default; + FramebufferAttachmentSpecification(std::initializer_list<FramebufferTextureSpecification> attachments) + : attachments(attachments) {} + + std::vector<FramebufferTextureSpecification> attachments; + }; + + struct FramebufferSpecification + { + uint32_t Width = 0, Height = 0; + FramebufferAttachmentSpecification attachments; + uint32_t Samples = 1; + + bool SwapChainTarget = false; + }; + + class Framebuffer + { + public: + virtual ~Framebuffer() = default; + + virtual auto bind() -> void = 0; + virtual auto unbind() -> void = 0; + + virtual auto resize(uint32_t width, uint32_t height) -> void = 0; + virtual auto read_pixel(uint32_t attachment_index, int x, int y) -> int = 0; + + virtual auto clear_attachment(uint32_t attachment_index, int value) -> void = 0; + virtual auto get_color_attachment_renderer_id(uint32_t index = 0) const -> uint32_t = 0; + + virtual auto get_specification() const -> const FramebufferSpecification& = 0; + + static auto create(const FramebufferSpecification& spec) -> Ref<Framebuffer>; + }; +}; diff --git a/src/rendering/index_buffer.cpp b/src/rendering/index_buffer.cpp new file mode 100644 index 0000000..9603c72 --- /dev/null +++ b/src/rendering/index_buffer.cpp @@ -0,0 +1,21 @@ +#include "index_buffer.h" +#include "renderer.h" + +#include "platform/opengl/opengl_index_buffer.h" +#include "platform/vulkan/vulkan_index_buffer.h" + +namespace Donut +{ + auto IndexBuffer::create(const uint32_t* indices, uint32_t count) -> IndexBuffer* + { + switch (Renderer::get_api()) + { + case RendererAPI::API::OpenGL: + return new OpenGLIndexBuffer(indices, count); + case RendererAPI::API::Vulkan: + return new VulkanIndexBuffer((uint32_t*)indices, count); + default: + return nullptr; + } + } +}; diff --git a/src/rendering/index_buffer.h b/src/rendering/index_buffer.h new file mode 100644 index 0000000..8389f2d --- /dev/null +++ b/src/rendering/index_buffer.h @@ -0,0 +1,18 @@ +#pragma once + +#include <cstdint> + +namespace Donut +{ + class IndexBuffer + { + public: + virtual ~IndexBuffer() = default; + + virtual auto bind() const -> void = 0; + virtual auto unbind() const -> void = 0; + virtual auto get_count() const -> uint32_t = 0; + + static auto create(const uint32_t* indices, uint32_t count) -> IndexBuffer*; + }; +}; diff --git a/src/rendering/renderer.cpp b/src/rendering/renderer.cpp new file mode 100644 index 0000000..28b7962 --- /dev/null +++ b/src/rendering/renderer.cpp @@ -0,0 +1,64 @@ +#include "renderer.h" + +#include "platform/opengl/opengl_renderer_api.h" +#include "platform/vulkan/vulkan_renderer_api.h" + +#include <glm/gtc/matrix_transform.hpp> + +namespace Donut +{ + auto RendererAPI::create() -> Scope<RendererAPI> + { + switch (s_api) + { + case API::OpenGL: + return create_scope<OpenGLRendererAPI>(); + case API::Vulkan: + return create_scope<VulkanRendererAPI>(); + default: + return nullptr; + } + } + + RendererAPI::API RendererAPI::s_api = RendererAPI::API::OpenGL; + + auto Renderer::init() -> void + { + RenderCommand::init(); + RenderCommand::enable_depth_test(); + } + + auto Renderer::shutdown() -> void + { + } + + auto Renderer::on_window_resize(uint32_t width, uint32_t height) -> void + { + RenderCommand::set_viewport(0, 0, width, height); + } + + auto Renderer::submit(const Ref<Shader>& shader, + const Ref<VertexArray>& vertex_array, + const glm::mat4& transform, + const glm::mat4& view_projection) -> void + { + shader->bind(); + shader->set_mat4("u_ViewProjection", view_projection); + shader->set_mat4("u_Transform", transform); + + vertex_array->bind(); + RenderCommand::draw_indexed(vertex_array); + } + + Scope<RendererAPI> RenderCommand::s_renderer_api = RendererAPI::create(); + + auto Renderer::set_clear_color(const glm::vec4& color) -> void + { + RenderCommand::set_clear_color(color); + } + + auto Renderer::clear() -> void + { + RenderCommand::clear(); + } +}; diff --git a/src/rendering/renderer.h b/src/rendering/renderer.h new file mode 100644 index 0000000..189723d --- /dev/null +++ b/src/rendering/renderer.h @@ -0,0 +1,158 @@ +#pragma once + +#include "core/memory.h" +#include "vertex_array.h" +#include "shader.h" +#include "framebuffer.h" + +#include <glm/glm.hpp> + +namespace Donut +{ + class RendererAPI + { + public: + enum class API + { + None = 0, + OpenGL = 1, + Vulkan = 2, + }; + + public: + virtual ~RendererAPI() = default; + + virtual auto init() -> void = 0; + virtual auto set_viewport(uint32_t x, uint32_t y, + uint32_t width, uint32_t height) -> void = 0; + virtual auto set_clear_color(const glm::vec4& color) -> void = 0; + virtual auto clear() -> void = 0; + virtual auto enable_depth_test() -> void = 0; + virtual auto disable_depth_test() -> void = 0; + virtual auto set_face_culling(bool enabled) -> void = 0; + virtual auto enable_blending() -> void = 0; + virtual auto disable_blending() -> void = 0; + + virtual auto draw_indexed(const Ref<VertexArray>& vertex_array, + uint32_t index_count = 0) -> void = 0; + + virtual auto draw_arrays(uint32_t vertex_count, uint32_t first = 0) -> void = 0; + virtual auto draw_lines(const Ref<VertexArray>& vertex_array, + uint32_t index_count = 0) -> void = 0; + virtual auto bind_texture(uint32_t texture_id, uint32_t slot = 0) -> void = 0; + virtual auto bind_image_texture(uint32_t texture_id, + uint32_t slot = 0, + bool read_only = false) -> void = 0; + virtual auto read_pixels(uint32_t x, uint32_t y, uint32_t width, uint32_t height, + uint32_t format, uint32_t type, void* pixels) -> void = 0; + + inline static auto get_api() -> API { return s_api; } + inline static auto set_api(API api) -> void { s_api = api; } + static auto create() -> Scope<RendererAPI>; + + private: + static API s_api; + }; + + class RenderCommand + { + public: + inline static auto init() -> void + { + s_renderer_api->init(); + } + + inline static auto set_viewport(uint32_t x, uint32_t y, uint32_t width, uint32_t height) -> void + { + s_renderer_api->set_viewport(x, y, width, height); + } + + inline static auto set_clear_color(const glm::vec4& color) -> void + { + s_renderer_api->set_clear_color(color); + } + + inline static auto clear() -> void + { + s_renderer_api->clear(); + } + + inline static auto enable_depth_test() -> void + { + s_renderer_api->enable_depth_test(); + } + + inline static auto disable_depth_test() -> void + { + s_renderer_api->disable_depth_test(); + } + + inline static auto set_face_culling(bool enabled) -> void + { + s_renderer_api->set_face_culling(enabled); + } + + inline static auto enable_blending() -> void + { + s_renderer_api->enable_blending(); + } + + inline static auto disable_blending() -> void + { + s_renderer_api->disable_blending(); + } + + inline static auto draw_indexed(const Ref<VertexArray>& vertex_array, uint32_t index_count = 0) -> void + { + s_renderer_api->draw_indexed(vertex_array, index_count); + } + + inline static auto draw_arrays(uint32_t vertex_count, uint32_t first = 0) -> void + { + s_renderer_api->draw_arrays(vertex_count, first); + } + + inline static auto draw_lines(const Ref<VertexArray>& vertex_array, uint32_t index_count = 0) -> void + { + s_renderer_api->draw_lines(vertex_array, index_count); + } + + inline static auto bind_texture(uint32_t texture_id, uint32_t slot = 0) -> void + { + s_renderer_api->bind_texture(texture_id, slot); + } + + inline static auto bind_image_texture(uint32_t texture_id, uint32_t slot = 0, bool read_only = false) -> void + { + s_renderer_api->bind_image_texture(texture_id, slot, read_only); + } + + inline static auto read_pixels(uint32_t x, uint32_t y, uint32_t width, uint32_t height, + uint32_t format, uint32_t type, void* pixels) -> void + { + s_renderer_api->read_pixels(x, y, width, height, format, type, pixels); + } + + private: + static Scope<RendererAPI> s_renderer_api; + }; + + class Renderer + { + public: + static auto init() -> void; + static auto shutdown() -> void; + + static auto on_window_resize(uint32_t width, uint32_t height) -> void; + + static auto submit(const Ref<Shader>& shader, + const Ref<VertexArray>& vertex_array, + const glm::mat4& transform, + const glm::mat4& view_projection) -> void; + + static auto set_clear_color(const glm::vec4& color) -> void; + static auto clear() -> void; + + inline static auto get_api() -> RendererAPI::API { return RendererAPI::get_api(); } + }; +}; diff --git a/src/rendering/shader.cpp b/src/rendering/shader.cpp new file mode 100644 index 0000000..167b855 --- /dev/null +++ b/src/rendering/shader.cpp @@ -0,0 +1,84 @@ +#include "shader.h" +#include "renderer.h" + +#include "platform/opengl/opengl_shader.h" +#include "platform/vulkan/vulkan_shader.h" + +namespace Donut +{ + auto Shader::create(const std::string& filepath) -> Shader* + { + switch (Renderer::get_api()) + { + case RendererAPI::API::OpenGL: + return new OpenGLShader(filepath); + case RendererAPI::API::Vulkan: + return new VulkanShader(filepath); + default: + return nullptr; + } + } + + auto Shader::create(const std::string& name, const std::string& vertex_src, const std::string& fragment_src) -> Shader* + { + switch (Renderer::get_api()) + { + case RendererAPI::API::OpenGL: + return new OpenGLShader(name, vertex_src, fragment_src); + case RendererAPI::API::Vulkan: + return new VulkanShader(name, vertex_src, fragment_src); + default: + return nullptr; + } + } + + auto Shader::create_compute(const std::string& name, const std::string& compute_src) -> Shader* + { + switch (Renderer::get_api()) + { + case RendererAPI::API::OpenGL: + return new OpenGLShader(name, compute_src); + case RendererAPI::API::Vulkan: + return new VulkanShader(name, compute_src); + default: + return nullptr; + } + } + + auto ShaderLibrary::add(const Ref<Shader>& shader) -> void + { + auto& name = shader->get_name(); + add(name, shader); + } + + auto ShaderLibrary::add(const std::string& name, const Ref<Shader>& shader) -> void + { + m_shaders[name] = shader; + } + + auto ShaderLibrary::load(const std::string& filepath) -> Ref<Shader> + { + auto shader = Ref<Shader>(Shader::create(filepath)); + add(shader); + return shader; + } + + auto ShaderLibrary::load(const std::string& name, const std::string& filepath) -> Ref<Shader> + { + auto shader = Ref<Shader>(Shader::create(filepath)); + add(name, shader); + return shader; + } + + auto ShaderLibrary::Get(const std::string& name) -> Ref<Shader> + { + if (exists(name)) + return m_shaders[name]; + return nullptr; + } + + auto ShaderLibrary::exists(const std::string& name) const -> bool + { + return m_shaders.find(name) != m_shaders.end(); + } +}; diff --git a/src/rendering/shader.h b/src/rendering/shader.h new file mode 100644 index 0000000..bc3fd9a --- /dev/null +++ b/src/rendering/shader.h @@ -0,0 +1,58 @@ +#pragma once + +#include "core/memory.h" + +#include <string> +#include <unordered_map> +#include <glm/glm.hpp> + +#define SHADER_STORAGE_BARRIER_BIT 0x00002000 +#define UNIFORM_BARRIER_BIT 0x00000004 +#define TEXTURE_FETCH_BARRIER_BIT 0x00000008 +#define IMAGE_ACCESS_BARRIER_BIT 0x00000020 + +namespace Donut +{ + class Shader + { + public: + virtual ~Shader() = default; + + virtual auto bind() const -> void = 0; + virtual auto unbind() const -> void = 0; + + virtual auto set_int( const std::string& name, int value) -> void = 0; + virtual auto set_int_array(const std::string& name, int* values, uint32_t count) -> void = 0; + virtual auto set_float( const std::string& name, float value) -> void = 0; + virtual auto set_float2( const std::string& name, const glm::vec2& value) -> void = 0; + virtual auto set_float3( const std::string& name, const glm::vec3& value) -> void = 0; + virtual auto set_float4( const std::string& name, const glm::vec4& value) -> void = 0; + virtual auto set_mat4( const std::string& name, const glm::mat4& value) -> void = 0; + + virtual auto dispatch(uint32_t x, uint32_t y = 1, uint32_t z = 1) -> void = 0; + virtual auto dispatch_indirect(uint32_t offset = 0) -> void = 0; + virtual auto memory_barrier(uint32_t barriers) -> void = 0; + + virtual auto get_name() const -> const std::string& = 0; + virtual auto get_renderer_id() const -> uint32_t = 0; + + static auto create(const std::string& filepath) -> Shader*; + static auto create(const std::string& name, const std::string& vertex_src, const std::string& fragment_src) -> Shader*; + static auto create_compute(const std::string& name, const std::string& compute_src) -> Shader*; + }; + + class ShaderLibrary + { + public: + auto add(const Ref<Shader>& shader) -> void; + auto add(const std::string& name, const Ref<Shader>& shader) -> void; + auto load(const std::string& filepath) -> Ref<Shader>; + auto load(const std::string& name, const std::string& filepath) -> Ref<Shader>; + + Ref<Shader> Get(const std::string& name); + + auto exists(const std::string& name) const -> bool; + private: + std::unordered_map<std::string, Ref<Shader>> m_shaders; + }; +}; diff --git a/src/rendering/texture.cpp b/src/rendering/texture.cpp new file mode 100644 index 0000000..2470e46 --- /dev/null +++ b/src/rendering/texture.cpp @@ -0,0 +1,68 @@ +#include "texture.h" +#include "renderer.h" + +#include "platform/opengl/opengl_texture.h" +#include "platform/vulkan/vulkan_texture.h" + +namespace Donut +{ + auto Texture2D::create(uint32_t width, uint32_t height) -> Ref<Texture2D> + { + switch (Renderer::get_api()) + { + case RendererAPI::API::OpenGL: + return create_ref<OpenGLTexture2D>(width, height); + case RendererAPI::API::Vulkan: + return create_ref<VulkanTexture2D>(width, height); + case RendererAPI::API::None: + return nullptr; + default: + return nullptr; + } + } + + auto Texture2D::create(const std::string& path) -> Ref<Texture2D> + { + switch (Renderer::get_api()) + { + case RendererAPI::API::OpenGL: + return create_ref<OpenGLTexture2D>(path); + case RendererAPI::API::Vulkan: + return create_ref<VulkanTexture2D>(path); + case RendererAPI::API::None: + return nullptr; + default: + return nullptr; + } + } + + auto CubemapTexture::create(uint32_t width, uint32_t height) -> Ref<CubemapTexture> + { + switch (Renderer::get_api()) + { + case RendererAPI::API::OpenGL: + return create_ref<OpenGLCubemapTexture>(width, height); + case RendererAPI::API::Vulkan: + return create_ref<VulkanCubemapTexture>(width, height); + case RendererAPI::API::None: + return nullptr; + default: + return nullptr; + } + } + + auto CubemapTexture::create_from_hdri(const std::string& path) -> Ref<CubemapTexture> + { + switch (Renderer::get_api()) + { + case RendererAPI::API::OpenGL: + return create_ref<OpenGLCubemapTexture>(path); + case RendererAPI::API::Vulkan: + return create_ref<VulkanCubemapTexture>(path); + case RendererAPI::API::None: + return nullptr; + default: + return nullptr; + } + } +};
\ No newline at end of file diff --git a/src/rendering/texture.h b/src/rendering/texture.h new file mode 100644 index 0000000..e9b3e0a --- /dev/null +++ b/src/rendering/texture.h @@ -0,0 +1,42 @@ +#pragma once + +#include "core/memory.h" + +#include <string> +#include <glm/glm.hpp> + +namespace Donut +{ + class Texture + { + public: + virtual ~Texture() = default; + + virtual auto get_width() const -> uint32_t = 0; + virtual auto get_height() const -> uint32_t = 0; + virtual auto get_renderer_id() const -> uint32_t = 0; + + virtual auto set_data(void* data, uint32_t size) -> void = 0; + virtual auto bind(uint32_t slot = 0) const -> void = 0; + virtual void bind_as_image(uint32_t slot = 0, + bool read_only = false) const = 0; + + virtual bool operator==(const Texture& other) const = 0; + }; + + class Texture2D + : public Texture + { + public: + static auto create(uint32_t width, uint32_t height) -> Ref<Texture2D>; + static auto create(const std::string& path) -> Ref<Texture2D>; + }; + + class CubemapTexture + : public Texture + { + public: + static auto create(uint32_t width, uint32_t height) -> Ref<CubemapTexture>; + static auto create_from_hdri(const std::string& path) -> Ref<CubemapTexture>; + }; +};
\ No newline at end of file diff --git a/src/rendering/texture_manager.cpp b/src/rendering/texture_manager.cpp new file mode 100644 index 0000000..ad2c68b --- /dev/null +++ b/src/rendering/texture_manager.cpp @@ -0,0 +1,34 @@ +#include "texture_manager.h" +#include "platform/opengl/opengl_texture.h" +#include "platform/opengl/opengl_renderer_api.h" +#include <glad/glad.h> + +namespace Donut +{ + auto TextureManager::create_texture(uint32_t width, uint32_t height) -> Ref<Texture2D> + { + return create_ref<OpenGLTexture2D>(width, height); + } + + auto TextureManager::bind_texture(uint32_t texture_id, uint32_t slot) -> void + { + RenderCommand::bind_texture(texture_id, slot); + } + + auto TextureManager::bind_image_texture(uint32_t texture_id, uint32_t slot, bool read_only) -> void + { + RenderCommand::bind_image_texture(texture_id, slot, read_only); + } + + auto TextureManager::set_texture_data(uint32_t texture_id, void* data, uint32_t width, uint32_t height) -> void + { + glBindTexture(GL_TEXTURE_2D, texture_id); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data); + } + + auto TextureManager::resize_texture(uint32_t texture_id, uint32_t width, uint32_t height) -> void + { + glBindTexture(GL_TEXTURE_2D, texture_id); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + } +}; diff --git a/src/rendering/texture_manager.h b/src/rendering/texture_manager.h new file mode 100644 index 0000000..02c32b1 --- /dev/null +++ b/src/rendering/texture_manager.h @@ -0,0 +1,19 @@ +#pragma once + +#include "core/memory.h" +#include "rendering/texture.h" +#include <cstdint> + +namespace Donut +{ + class TextureManager + { + public: + static auto create_texture(uint32_t width, uint32_t height) -> Ref<Texture2D>; + + static auto bind_texture(uint32_t texture_id, uint32_t slot = 0) -> void; + static auto bind_image_texture(uint32_t texture_id, uint32_t slot = 0, bool read_only = false) -> void; + static auto set_texture_data(uint32_t texture_id, void* data, uint32_t width, uint32_t height) -> void; + static auto resize_texture(uint32_t texture_id, uint32_t width, uint32_t height) -> void; + }; +}; diff --git a/src/rendering/uniform_buffer.cpp b/src/rendering/uniform_buffer.cpp new file mode 100644 index 0000000..c344aec --- /dev/null +++ b/src/rendering/uniform_buffer.cpp @@ -0,0 +1,23 @@ +#include "uniform_buffer.h" +#include "renderer.h" + +#include "platform/opengl/opengl_uniform_buffer.h" +#include "platform/vulkan/vulkan_uniform_buffer.h" + +namespace Donut +{ + auto UniformBuffer::create(uint32_t size, uint32_t binding) -> Ref<UniformBuffer> + { + switch (Renderer::get_api()) + { + case RendererAPI::API::OpenGL: + return create_ref<OpenGLUniformBuffer>(size, binding); + case RendererAPI::API::Vulkan: + return create_ref<VulkanUniformBuffer>(size, binding); + case RendererAPI::API::None: + return nullptr; + default: + return nullptr; + } + } +}; diff --git a/src/rendering/uniform_buffer.h b/src/rendering/uniform_buffer.h new file mode 100644 index 0000000..eb28e53 --- /dev/null +++ b/src/rendering/uniform_buffer.h @@ -0,0 +1,18 @@ +#pragma once + +#include "core/memory.h" +#include <cstdint> + +namespace Donut +{ + class UniformBuffer + { + public: + virtual ~UniformBuffer() = default; + + virtual auto set_data(const void* data, uint32_t size, uint32_t offset = 0) -> void = 0; + virtual auto bind(uint32_t binding) -> void = 0; + + static auto create(uint32_t size, uint32_t binding) -> Ref<UniformBuffer>; + }; +}; diff --git a/src/rendering/vertex_array.cpp b/src/rendering/vertex_array.cpp new file mode 100644 index 0000000..8045707 --- /dev/null +++ b/src/rendering/vertex_array.cpp @@ -0,0 +1,32 @@ +#include "vertex_array.h" +#include "renderer.h" + +#include "platform/opengl/opengl_vertex_array.h" +#include "platform/vulkan/vulkan_vertex_array.h" + +namespace Donut +{ + auto VertexBufferElement::get_size_of_type(uint32_t type) -> uint32_t + { + switch (type) + { + case 0x1406: return 4; // GL_FLOAT + case 0x1405: return 4; // GL_UNSIGNED_INT + case 0x1401: return 1; // GL_UNSIGNED_BYTE + default: return 0; + } + } + + auto VertexArray::create() -> VertexArray* + { + switch (Renderer::get_api()) + { + case RendererAPI::API::OpenGL: + return new OpenGLVertexArray(); + case RendererAPI::API::Vulkan: + return new VulkanVertexArray(); + default: + return nullptr; + } + } +}; diff --git a/src/rendering/vertex_array.h b/src/rendering/vertex_array.h new file mode 100644 index 0000000..921df56 --- /dev/null +++ b/src/rendering/vertex_array.h @@ -0,0 +1,28 @@ +#pragma once + +#include "core/memory.h" + +#include "vertex_buffer.h" +#include "index_buffer.h" + +#include <vector> + +namespace Donut +{ + class VertexArray + { + public: + virtual ~VertexArray() = default; + + virtual auto bind() const -> void = 0; + virtual auto unbind() const -> void = 0; + + virtual auto add_vertex_buffer(const Ref<VertexBuffer>& vertex_buffer) -> void = 0; + virtual auto set_index_buffer(const Ref<IndexBuffer>& index_buffer) -> void = 0; + + virtual auto get_vertex_buffers() const -> const std::vector<Ref<VertexBuffer>>& = 0; + virtual auto get_index_buffer() const -> const Ref<IndexBuffer>& = 0; + + static auto create() -> VertexArray*; + }; +}; diff --git a/src/rendering/vertex_buffer.cpp b/src/rendering/vertex_buffer.cpp new file mode 100644 index 0000000..354d0cd --- /dev/null +++ b/src/rendering/vertex_buffer.cpp @@ -0,0 +1,21 @@ +#include "vertex_buffer.h" +#include "renderer.h" + +#include "platform/opengl/opengl_vertex_buffer.h" +#include "platform/vulkan/vulkan_vertex_buffer.h" + +namespace Donut +{ + auto VertexBuffer::create(const void* data, uint32_t size) -> VertexBuffer* + { + switch (Renderer::get_api()) + { + case RendererAPI::API::OpenGL: + return new OpenGLVertexBuffer(data, size); + case RendererAPI::API::Vulkan: + return new VulkanVertexBuffer((float*)data, size); + default: + return nullptr; + } + } +}; diff --git a/src/rendering/vertex_buffer.h b/src/rendering/vertex_buffer.h new file mode 100644 index 0000000..6be7e34 --- /dev/null +++ b/src/rendering/vertex_buffer.h @@ -0,0 +1,73 @@ +#pragma once + +#include <cstdint> +#include <vector> + +namespace Donut +{ + struct VertexBufferElement + { + uint32_t type; + uint32_t count; + uint8_t normalized; + uint32_t offset; + + static auto get_size_of_type(uint32_t type) -> uint32_t; + }; + + class VertexBufferLayout + { + public: + VertexBufferLayout() = default; + ~VertexBufferLayout() = default; + + template<typename T> + auto push(uint32_t count) -> void + { + static_assert(false); + } + + template<> + void push<float>(uint32_t count) + { + m_elements.push_back({ 0x1406, count, 0, m_stride }); // GL_FLOAT + m_stride += count * VertexBufferElement::get_size_of_type(0x1406); + } + + template<> + void push<uint32_t>(uint32_t count) + { + m_elements.push_back({ 0x1405, count, 0, m_stride }); // GL_UNSIGNED_INT + m_stride += count * VertexBufferElement::get_size_of_type(0x1405); + } + + template<> + void push<uint8_t>(uint32_t count) + { + m_elements.push_back({ 0x1401, count, 1, m_stride }); // GL_UNSIGNED_BYTE + m_stride += count * VertexBufferElement::get_size_of_type(0x1401); + } + + inline auto get_elements() const -> const std::vector<VertexBufferElement>& { return m_elements; } + inline auto get_stride() const -> uint32_t { return m_stride; } + + private: + std::vector<VertexBufferElement> m_elements; + uint32_t m_stride = 0; + }; + + class VertexBuffer + { + public: + virtual ~VertexBuffer() = default; + + virtual auto bind() const -> void = 0; + virtual auto unbind() const -> void = 0; + virtual auto set_data(const void* data, uint32_t size) -> void = 0; + + virtual auto get_layout() const -> const VertexBufferLayout& = 0; + virtual auto set_layout(const VertexBufferLayout& layout) -> void = 0; + + static auto create(const void* data, uint32_t size) -> VertexBuffer*; + }; +}; |
