diff --git a/App/Src/Main.cpp b/App/Src/Main.cpp index abdd9e6..deeb249 100644 --- a/App/Src/Main.cpp +++ b/App/Src/Main.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -52,27 +53,19 @@ namespace const auto& renderDevice = engine.RenderDevice(); if (!shader.Load(renderDevice.get_device(), vertexSpirV, fragmentSpirV)) { throw std::runtime_error{"Failed to load shaders"}; } - static constexpr auto Vertices = std::array{ - Tkge::Graphics::Vertex{.position = {-200.0f, -200.0f}}, - Tkge::Graphics::Vertex{.position = {200.0f, -200.0f}}, - Tkge::Graphics::Vertex{.position = {200.0f, 200.0f}}, - Tkge::Graphics::Vertex{.position = {-200.0f, 200.0f}}, - }; + auto quad = Tkge::Graphics::Quad{}; + quad.Create(glm::vec2{400.0f}); + quad.transform.position.x = -250.0f; + quad.tint = kvf::magenta_v; - static constexpr auto Indices = std::array{ - 0u, 1u, 2u, 2u, 3u, 0u, - }; + auto instancedQuad = Tkge::Graphics::InstancedQuad{}; + instancedQuad.Create(glm::vec2{150.0f}); - static constexpr auto Primitive = Tkge::Graphics::Primitive{ - .vertices = Vertices, - .indices = Indices, - }; - - auto instances = std::array{}; - instances[0].transform.position.x = -250.0f; - instances[0].tint = kvf::cyan_v; - instances[1].transform.position.x = 250.0f; - instances[1].tint = kvf::yellow_v; + instancedQuad.instances.resize(2); + instancedQuad.instances[0].transform.position = {250.0f, -100.0f}; + instancedQuad.instances[0].tint = kvf::cyan_v; + instancedQuad.instances[1].transform.position = {250.0f, 100.0f}; + instancedQuad.instances[1].tint = kvf::yellow_v; auto wireframe = false; auto lineWidth = 3.0f; @@ -87,8 +80,9 @@ namespace const auto dt = deltaTime.tick(); elapsed += dt; - instances[0].tint.w = kvf::Color::to_u8((0.5f * std::sin(elapsed.count())) + 0.5f); - instances[1].tint.w = kvf::Color::to_u8((0.5f * std::sin(-elapsed.count())) + 0.5f); + instancedQuad.instances[0].tint.w = kvf::Color::to_u8((0.5f * std::sin(elapsed.count())) + 0.5f); + instancedQuad.instances[1].tint.w = kvf::Color::to_u8((0.5f * std::sin(-elapsed.count())) + 0.5f); + quad.tint.w = kvf::Color::to_u8((0.5f * std::cos(elapsed.count())) + 0.5f); if (ImGui::Begin("Misc")) { @@ -102,7 +96,8 @@ namespace renderer.BindShader(shader); renderer.SetLineWidth(lineWidth); renderer.SetWireframe(wireframe); - renderer.Draw(Primitive, instances); + instancedQuad.Draw(renderer); + quad.Draw(renderer); } engine.Present(); diff --git a/Lib/Include/Tkge/Graphics/Drawable.hpp b/Lib/Include/Tkge/Graphics/Drawable.hpp new file mode 100644 index 0000000..ba2a037 --- /dev/null +++ b/Lib/Include/Tkge/Graphics/Drawable.hpp @@ -0,0 +1,50 @@ +#pragma once +#include +#include +#include + +namespace Tkge::Graphics +{ + class IDrawable : public klib::Polymorphic + { + public: + [[nodiscard]] virtual Primitive GetPrimitive() const = 0; + [[nodiscard]] virtual std::span GetInstances() const = 0; + + virtual void Draw(Renderer& renderer) const { renderer.Draw(GetPrimitive(), GetInstances()); } + }; + + template TGeometry> + class BasicDrawable : public TGeometry, public IDrawable + { + public: + [[nodiscard]] Primitive GetPrimitive() const final + { + return Primitive{ + .vertices = this->GetVertices(), + .indices = this->GetIndices(), + .topology = this->GetTopology(), + }; + } + }; + + template TGeometry> + class Drawable : public BasicDrawable, public RenderInstance + { + public: + [[nodiscard]] std::span GetInstances() const final { return {static_cast(this), 1}; } + }; + + template TGeometry> + class InstancedDrawable : public BasicDrawable + { + public: + [[nodiscard]] std::span GetInstances() const final { return instances; } + + std::vector instances{}; + }; + + using Quad = Drawable; + using InstancedQuad = InstancedDrawable; + +} // namespace Tkge::Graphics diff --git a/Lib/Include/Tkge/Graphics/IGeometry.hpp b/Lib/Include/Tkge/Graphics/IGeometry.hpp new file mode 100644 index 0000000..6377607 --- /dev/null +++ b/Lib/Include/Tkge/Graphics/IGeometry.hpp @@ -0,0 +1,16 @@ +#pragma once +#include +#include +#include +#include + +namespace Tkge::Graphics +{ + class IGeometry : public klib::Polymorphic + { + public: + [[nodiscard]] virtual std::span GetVertices() const = 0; + [[nodiscard]] virtual std::span GetIndices() const = 0; + [[nodiscard]] virtual vk::PrimitiveTopology GetTopology() const = 0; + }; +} // namespace Tkge::Graphics diff --git a/Lib/Include/Tkge/Graphics/Shape.hpp b/Lib/Include/Tkge/Graphics/Shape.hpp new file mode 100644 index 0000000..d45141a --- /dev/null +++ b/Lib/Include/Tkge/Graphics/Shape.hpp @@ -0,0 +1,30 @@ +#pragma once +#include +#include +#include +#include + +namespace Tkge::Graphics +{ + class QuadShape : public IGeometry + { + public: + static constexpr auto Indices = std::array{0u, 1u, 2u, 2u, 3u, 0u}; + static constexpr std::size_t VertexCount{6}; + + [[nodiscard]] std::span GetVertices() const final { return m_vertices; } + [[nodiscard]] std::span GetIndices() const final { return Indices; } + [[nodiscard]] vk::PrimitiveTopology GetTopology() const final { return vk::PrimitiveTopology::eTriangleList; } + + void Create(const kvf::Rect<>& rect, const kvf::UvRect& uv = kvf::uv_rect_v, kvf::Color colour = kvf::white_v); + void Create(const glm::vec2 size) { Create(kvf::Rect<>::from_size(size)); } + + [[nodiscard]] kvf::Rect<> GetRect() const; + [[nodiscard]] kvf::UvRect GetUv() const; + [[nodiscard]] glm::vec2 GetSize() const { return GetRect().size(); } + [[nodiscard]] kvf::Color GetColour() const { return m_vertices.front().colour; } + + private: + std::array m_vertices{}; + }; +} // namespace Tkge::Graphics diff --git a/Lib/Src/Graphics/Shape.cpp b/Lib/Src/Graphics/Shape.cpp new file mode 100644 index 0000000..272314b --- /dev/null +++ b/Lib/Src/Graphics/Shape.cpp @@ -0,0 +1,25 @@ +#include + +namespace Tkge::Graphics +{ + namespace + { + constexpr std::size_t LeftBottom{0}; + constexpr std::size_t RightBottom{1}; + constexpr std::size_t RightTop{2}; + constexpr std::size_t LeftTop{3}; + } // namespace + + void QuadShape::Create(const kvf::Rect<>& rect, const kvf::UvRect& uv, const kvf::Color colour) + { + m_vertices[LeftBottom] = Vertex{.position = rect.bottom_left(), .colour = colour.to_linear(), .uv = uv.bottom_left()}; + m_vertices[RightBottom] = Vertex{.position = rect.bottom_right(), .colour = colour.to_linear(), .uv = uv.bottom_right()}; + m_vertices[RightTop] = Vertex{.position = rect.top_right(), .colour = colour.to_linear(), .uv = uv.top_right()}; + m_vertices[LeftTop] = Vertex{.position = rect.top_left(), .colour = colour.to_linear(), .uv = uv.top_left()}; + } + + kvf::Rect<> QuadShape::GetRect() const { return kvf::Rect<>{.lt = m_vertices[LeftTop].position, .rb = m_vertices[RightBottom].position}; } + + [[nodiscard]] kvf::UvRect QuadShape::GetUv() const { return {.lt = m_vertices[LeftTop].uv, .rb = m_vertices[RightBottom].uv}; } + +} // namespace Tkge::Graphics