diff --git a/premake5.lua b/premake5.lua index e739176..7d498e0 100644 --- a/premake5.lua +++ b/premake5.lua @@ -33,7 +33,7 @@ project "bakara" "%{IncludeDirs.glfw}", "%{IncludeDirs.imgui}", "%{IncludeDirs.bakatools}", - "%{InlcudeDirs.stb}" + "%{IncludeDirs.stb}" } links diff --git a/src/bakara.h b/src/bakara.h index 0a85790..2db8dec 100644 --- a/src/bakara.h +++ b/src/bakara.h @@ -14,8 +14,6 @@ Plaform namespace doc */ namespace Bk::Plaform {} -namespace Baka = Bk; - #include #include @@ -26,10 +24,13 @@ namespace Baka = Bk; #include #include +#include #include #include +#include +#include #include #include #include diff --git a/src/bakara/core/application.cpp b/src/bakara/core/application.cpp index f8cb161..6dfc19b 100644 --- a/src/bakara/core/application.cpp +++ b/src/bakara/core/application.cpp @@ -1,5 +1,7 @@ #include "application.h" #include "bakara/core/window.h" +#include "bakara/events/window_event.h" +#include "bakara/renderer/renderer.h" #include "bakatools/logging/assert.h" #include "bakara/events/dispacher.h" @@ -10,11 +12,14 @@ namespace Bk { { BK_CORE_MSG_ASSERT(p_instance == nullptr, "Application already exists, can not create two application.") Application::p_instance = this; + h_window = std::unique_ptr(Window::CreateWindow(WindowProps(title, width, height))); + h_window->SetEventCallback(BK_BIND_EVENT_FN(OnEvent)); + + Renderer::Init(); + imgui_layer = new ImguiLayer(); PushOverlay(imgui_layer); - h_window->SetEventCallback(BK_BIND_EVENT_FN(OnEvent)); - p_running = true; } Application::~Application() { } @@ -22,9 +27,9 @@ namespace Bk { void Application::OnEvent(Event& e) { EventDispatcher dispatcher(e); - if (!(dispatcher.dispatch(BK_BIND_DISPACHER_FN(WindowCloseEvent, OnWindowClose)) - || dispatcher.dispatch(BK_BIND_DISPACHER_FN(WindowResizeEvent, OnWindowResize)))) + if (!dispatcher.dispatch(BK_BIND_DISPACHER_FN(WindowCloseEvent, OnWindowClose))) { + dispatcher.dispatch(BK_BIND_DISPACHER_FN(WindowResizeEvent, OnWindowResize)); for(auto it = p_layer_stack.ReverseBegin(); it != p_layer_stack.ReverseEnd(); it++) { (*it)->OnEvent(e); @@ -34,18 +39,19 @@ namespace Bk { void Application::Close() { - h_window->Close(); p_running = false; } - bool Application::OnWindowClose(WindowCloseEvent& e) + bool Application::OnWindowResize(WindowResizeEvent& e) { - Close(); - return true; + isMinimized = !e.GetWidth() && !e.GetHeight(); + Renderer::ResizeFrame(e.GetWidth(), e.GetHeight()); + return false; } - bool Application::OnWindowResize(WindowResizeEvent& e) + bool Application::OnWindowClose(WindowCloseEvent& e) { + Close(); return true; } @@ -53,8 +59,10 @@ namespace Bk { { while (p_running) { - for (Layer* layer : p_layer_stack) - layer->OnUpdate(h_window->GetTime()); + if (!isMinimized) + for (Layer* layer : p_layer_stack) + layer->OnUpdate(h_window->GetTime()); + imgui_layer->Begin(); for (Layer* layer : p_layer_stack) layer->ImguiRender(); diff --git a/src/bakara/core/application.h b/src/bakara/core/application.h index 1f08473..255f206 100644 --- a/src/bakara/core/application.h +++ b/src/bakara/core/application.h @@ -83,7 +83,8 @@ namespace Bk { private: LayerStack p_layer_stack; //!< Layer stack of the application - bool p_running; //!< Flag that indicates if the update loop should stop or not + bool p_running = true; //!< Flag that indicates if the update loop should stop or not + bool isMinimized = false; static Application* p_instance; }; /*! \fn std::unique_ptr Bk::CreateApp() diff --git a/src/bakara/core/window.h b/src/bakara/core/window.h index a3a6707..2e0d846 100644 --- a/src/bakara/core/window.h +++ b/src/bakara/core/window.h @@ -84,15 +84,6 @@ namespace Bk { Closes the window */ virtual void Close() = 0; - /*! \fn Bk::Window::Open - Opens and Initializes the window - */ - virtual void Open() = 0; - /*! \fn Bk::Window::IsOpen - Indicates if the window is Opened - @return Open flag - */ - virtual bool IsOpen() = 0; virtual void* GetNativeWindow() = 0; diff --git a/src/bakara/events/mouse_event.h b/src/bakara/events/mouse_event.h index 5e4979f..c92dda1 100644 --- a/src/bakara/events/mouse_event.h +++ b/src/bakara/events/mouse_event.h @@ -12,8 +12,8 @@ namespace Bk MouseMoveEvent(const float x, const float y) : p_mouse_x(x), p_mouse_y(y) {} - float get_x() const { return p_mouse_x; } - float get_y() const { return p_mouse_y; } + float GetX() const { return p_mouse_x; } + float GetY() const { return p_mouse_y; } Vec2 get_pos() const { return Vec2(p_mouse_x, p_mouse_y); } @@ -33,8 +33,8 @@ namespace Bk MouseScrollEvent(const float x, const float y) : p_dx(x), p_dy(y) {} - float get_dx() const { return p_dx; } - float get_dy() const { return p_dy; } + float GetDx() const { return p_dx; } + float GetDY() const { return p_dy; } EVENT_STRINGIFY("MouseScrollEvent : (%f, %f)", p_dx, p_dy) @@ -48,7 +48,7 @@ namespace Bk class MouseButtonEvent : public Event { public: - Code get_btn() { return m_btn; } + Code GetBtn() { return m_btn; } EVENT_CLASS_CATEGORY(MouseCategory | InputCategory) protected: diff --git a/src/bakara/events/window_event.h b/src/bakara/events/window_event.h index 94012d1..eca5da3 100644 --- a/src/bakara/events/window_event.h +++ b/src/bakara/events/window_event.h @@ -1,16 +1,17 @@ #pragma once +#include "bakatools/container/types.h" #include "event.h" namespace Bk { class WindowResizeEvent : public Event { public: - WindowResizeEvent(uint width, uint height) + WindowResizeEvent(u32 width, u32 height) : p_width(width), p_height(height) {}; - uint GetWidth() const { return p_width; } - uint GetHeight() const { return p_height; } + u32 GetWidth() const { return p_width; } + u32 GetHeight() const { return p_height; } EVENT_STRINGIFY("WindowResizeEvent : %d %d", p_width, p_height) @@ -18,8 +19,8 @@ namespace Bk { EVENT_CLASS_CATEGORY(AppCategory) private: - uint p_width; - uint p_height; + u32 p_width; + u32 p_height; }; class WindowCloseEvent : public Event diff --git a/src/bakara/math/types.h b/src/bakara/math/types.h index ff4f21c..156b214 100644 --- a/src/bakara/math/types.h +++ b/src/bakara/math/types.h @@ -15,6 +15,8 @@ namespace Bk namespace Math = glm; using Quaterion = glm::quat; + + using Color = glm::vec4; /*! \typedef Bk::Vec2 Wrapper around glm::vec2 diff --git a/src/bakara/renderer/cameras/ortho_camera.cpp b/src/bakara/renderer/cameras/ortho_camera.cpp index ac025e8..f901237 100644 --- a/src/bakara/renderer/cameras/ortho_camera.cpp +++ b/src/bakara/renderer/cameras/ortho_camera.cpp @@ -7,17 +7,23 @@ namespace Bk { - OrthographicCamera::OrthographicCamera(float left, float right, float bottom, float top) - : projectionMatrix(Math::ortho(left, right, bottom, top, -1.0f, 1.0f)) + OrthoCamera::OrthoCamera(float left, float right, float bottom, float top) + : projection(Math::ortho(left, right, bottom, top, -1.0f, 1.0f)) { - RecalculViewMatrix(); + RecalculateView(); } - void OrthographicCamera::RecalculViewMatrix() + void OrthoCamera::SetProjection(float left, float right, float bottom, float top) + { + projection = Math::ortho(left, right, bottom, top, -1.0f, 1.0f); + viewProjection = projection * view; + } + + void OrthoCamera::RecalculateView() { Mat4 transform = Math::translate(Mat4(1.0f), position); transform = Math::rotate(transform, Math::radians(rotation) , Vec3(0.0f, 0.0f, 1.0f)); - viewMatrix = Math::inverse(transform); - viewProjectionMatrix = projectionMatrix * viewMatrix; + view = Math::inverse(transform); + viewProjection = projection * view; } } \ No newline at end of file diff --git a/src/bakara/renderer/cameras/ortho_camera.h b/src/bakara/renderer/cameras/ortho_camera.h index 75e2b76..1e118a8 100644 --- a/src/bakara/renderer/cameras/ortho_camera.h +++ b/src/bakara/renderer/cameras/ortho_camera.h @@ -4,25 +4,26 @@ namespace Bk { - class OrthographicCamera + class OrthoCamera { public: - OrthographicCamera(float left, float right, float bottom, float top); + OrthoCamera(float left, float right, float bottom, float top); - void SetPosition(Vec3 position) { this->position = position; RecalculViewMatrix(); } - Vec3 GetPosition() { return position; } - void SetRotation(float rotation) { this->rotation = rotation; RecalculViewMatrix(); } - float GetRotaion() { return rotation; } + void SetPosition(Vec3 position) { this->position = position; RecalculateView(); } + const Vec3& GetPosition() const { return position; } + void SetRotation(float rotation) { this->rotation = rotation; RecalculateView(); } + float GetRotaion() const { return rotation; } - Mat4 GetViewMatrix() { return viewMatrix; } - Mat4 GetProjectionMatrix() { return projectionMatrix; } - Mat4 GetViewProjectionMatrix() { return viewProjectionMatrix; } + const Mat4 GetView() const { return view; } + void SetProjection(float left, float right, float bottom, float top); + const Mat4 GetProjection() const { return projection; } + const Mat4 GetViewProjection() const { return viewProjection; } private: - void RecalculViewMatrix(); - Mat4 viewMatrix; - Mat4 projectionMatrix; - Mat4 viewProjectionMatrix; + void RecalculateView(); + Mat4 view; + Mat4 projection; + Mat4 viewProjection; Vec3 position = { 0.0f, 0.0f, 0.0f }; float rotation = 0.0f; diff --git a/src/bakara/renderer/cameras/ortho_camera_controller.cpp b/src/bakara/renderer/cameras/ortho_camera_controller.cpp new file mode 100644 index 0000000..491852c --- /dev/null +++ b/src/bakara/renderer/cameras/ortho_camera_controller.cpp @@ -0,0 +1,76 @@ +#include "ortho_camera_controller.h" +#include "bakara/events/dispacher.h" +#include "bakara/events/event.h" +#include "bakara/events/window_event.h" +#include "bakara/io/keyboard.h" +#include "glm/trigonometric.hpp" +#include + +namespace Bk +{ + OrthoCameraController::OrthoCameraController(float aspectRatio, bool rotation, bool zoom) + : aspectRatio(aspectRatio), + camera(-aspectRatio * zoomLevel, aspectRatio * zoomLevel, -zoomLevel, zoomLevel), + rotation(rotation), zoom(zoom) {} + + void OrthoCameraController::OnEvent(Event& e) + { + EventDispatcher dispatcher(e); + dispatcher.dispatch(BK_BIND_DISPACHER_FN(WindowResizeEvent, OnWindowResize)); + dispatcher.dispatch(BK_BIND_DISPACHER_FN(MouseScrollEvent, OnMouseScroll)); + } + + void OrthoCameraController::OnUpdate(DeltaTime dt) + { + if (rotation) + { + if(Keyboard::KeyDown(KeyCode::Q)) + cameraRotation -= rotationSpeed * dt; + if(Keyboard::KeyDown(KeyCode::E)) + cameraRotation += rotationSpeed * dt; + camera.SetRotation(cameraRotation); + } + + if(Keyboard::KeyDown(KeyCode::W)) + { + cameraPosition.x += -std::sin(Math::radians(cameraRotation)) * moveSpeed * dt; + cameraPosition.y += std::cos(Math::radians(cameraRotation)) * moveSpeed * dt; + } + if(Keyboard::KeyDown(KeyCode::S)) + { + cameraPosition.x -= -std::sin(Math::radians(cameraRotation)) * moveSpeed * dt; + cameraPosition.y -= std::cos(Math::radians(cameraRotation)) * moveSpeed * dt; + } + if(Keyboard::KeyDown(KeyCode::D)) + { + cameraPosition.x += std::cos(Math::radians(cameraRotation)) * moveSpeed * dt; + cameraPosition.y += std::sin(Math::radians(cameraRotation)) * moveSpeed * dt; + } + if(Keyboard::KeyDown(KeyCode::A)) + { + cameraPosition.x -= std::cos(Math::radians(cameraRotation)) * moveSpeed * dt; + cameraPosition.y -= std::sin(Math::radians(cameraRotation)) * moveSpeed * dt; + } + camera.SetPosition(cameraPosition); + } + + bool OrthoCameraController::OnMouseScroll(MouseScrollEvent& e) + { + if (zoom) + { + zoomLevel -= e.GetDY() * 0.01; + zoomLevel = std::max(zoomLevel, 0.5f); + zoomLevel = std::min(zoomLevel, 10.0f); + camera.SetProjection(-aspectRatio * zoomLevel, aspectRatio * zoomLevel, -zoomLevel, zoomLevel); + return true; + } + return false; + } + + bool OrthoCameraController::OnWindowResize(WindowResizeEvent& e) + { + aspectRatio = (float)e.GetWidth() / (float)e.GetHeight(); + camera.SetProjection(-aspectRatio * zoomLevel, aspectRatio * zoomLevel, -zoomLevel, zoomLevel); + return false; + } +} \ No newline at end of file diff --git a/src/bakara/renderer/cameras/ortho_camera_controller.h b/src/bakara/renderer/cameras/ortho_camera_controller.h new file mode 100644 index 0000000..0fe27e0 --- /dev/null +++ b/src/bakara/renderer/cameras/ortho_camera_controller.h @@ -0,0 +1,39 @@ +#pragma once + +#include "bakara/core/deltatime.h" +#include "bakara/events/event.h" +#include "bakara/events/mouse_event.h" +#include "bakara/events/window_event.h" +#include "ortho_camera.h" + +namespace Bk +{ + class OrthoCameraController + { + public: + OrthoCameraController(float aspectRatio, bool rotation = false, bool zoom = false); + + void OnUpdate(DeltaTime dt); + void OnEvent(Event& e); + + const OrthoCamera& GetCamera() { return camera; } + + void SetMoveSpeed(float moveSpeed) { this->moveSpeed = moveSpeed; } + void SetRotationSpeed(float rotationSpeed) { this->rotationSpeed = rotationSpeed; } + + private: + float aspectRatio; + float zoomLevel = 1.0f; + + bool rotation, zoom; + float cameraRotation = 0.0f; + Vec3 cameraPosition = { 0, 0, 0 }; + float moveSpeed = 1.0f; + float rotationSpeed = 1.0f; + + OrthoCamera camera; + + bool OnMouseScroll(MouseScrollEvent& e); + bool OnWindowResize(WindowResizeEvent& e); + }; +} \ No newline at end of file diff --git a/src/bakara/renderer/graphics_context.cpp b/src/bakara/renderer/graphics_context.cpp new file mode 100644 index 0000000..ce1ad34 --- /dev/null +++ b/src/bakara/renderer/graphics_context.cpp @@ -0,0 +1,18 @@ +#include "graphics_context.h" +#include "bakara/renderer/renderer.h" +#include "bakatools/logging/assert.h" +#include "platforms/opengl/opengl_context.h" + +namespace Bk +{ + Scope GraphicsContext::Create(void *window_handle) + { + switch (Renderer::GetAPI()) + { + case Renderer::API::None: BK_MSG_ASSERT(false, "API not supported"); return nullptr; + case Renderer::API::Opengl: return CreateScope(window_handle); + } + BK_MSG_ASSERT(false, "API not supported"); + return nullptr; + } +} \ No newline at end of file diff --git a/src/bakara/renderer/graphics_context.h b/src/bakara/renderer/graphics_context.h index 76dfec1..ce67750 100644 --- a/src/bakara/renderer/graphics_context.h +++ b/src/bakara/renderer/graphics_context.h @@ -1,5 +1,6 @@ #pragma once +#include "bakatools/container/types.h" namespace Bk { class GraphicsContext @@ -8,6 +9,7 @@ namespace Bk virtual ~GraphicsContext() {} virtual void Init() = 0; virtual void SwapBuffers() = 0; - virtual void SetViewport(int width, int height) = 0; + + static Scope Create(void* window_handle); }; } \ No newline at end of file diff --git a/src/bakara/renderer/render_command.h b/src/bakara/renderer/render_command.h index 6ae2f29..b02c3f1 100644 --- a/src/bakara/renderer/render_command.h +++ b/src/bakara/renderer/render_command.h @@ -9,8 +9,10 @@ namespace Bk class RenderCommand { public: + static inline void Init() { rendererAPI->Init(); } static inline void Clear(Vec4 color) { rendererAPI->Clear(color.r, color.g, color.b, color.a); } static inline void Clear(float red, float green, float blue, float alpha) { rendererAPI->Clear(red, green, blue, alpha); } + static inline void SetViewport(u32 width, u32 height) { rendererAPI->SetViewport(width, height); } static inline void DrawIndexed(Ref va) { rendererAPI->DrawIndexed(va); } private: static RendererAPI* rendererAPI; diff --git a/src/bakara/renderer/renderer.cpp b/src/bakara/renderer/renderer.cpp index 5f9ac10..2276ede 100644 --- a/src/bakara/renderer/renderer.cpp +++ b/src/bakara/renderer/renderer.cpp @@ -1,14 +1,26 @@ #include "renderer.h" #include "bakara/renderer/cameras/ortho_camera.h" #include "bakara/renderer/render_command.h" +#include "bakara/renderer/renderer2D.h" namespace Bk { Renderer::API Renderer::s_RenderAPI = Renderer::API::Opengl; - Renderer::SceneData* Renderer::sceneData = new Renderer::SceneData(); + Renderer::Storage* Renderer::data = new Renderer::Storage(); - void Renderer::BeginScene(OrthographicCamera camera) + void Renderer::Init() { - sceneData->VPMatrix = camera.GetViewProjectionMatrix(); + RenderCommand::Init(); + Renderer2D::Init(); + } + + void Renderer::ResizeFrame(u32 width, u32 height) + { + RenderCommand::SetViewport(width, height); + } + + void Renderer::BeginScene(const OrthoCamera& camera) + { + data->viewProjection = camera.GetViewProjection(); } void Renderer::EndScene() @@ -20,7 +32,7 @@ namespace Bk { va->Bind(); shader->Bind(); - shader->Set("u_ViewProjection", sceneData->VPMatrix); + shader->Set("u_ViewProjection", data->viewProjection); shader->Set("u_Transform", transform); RenderCommand::DrawIndexed(va); } diff --git a/src/bakara/renderer/renderer.h b/src/bakara/renderer/renderer.h index 70d7877..535d26a 100644 --- a/src/bakara/renderer/renderer.h +++ b/src/bakara/renderer/renderer.h @@ -19,16 +19,20 @@ namespace Bk static API GetAPI() { return s_RenderAPI; } - static void BeginScene(OrthographicCamera camera); + static void Init(); + + static void ResizeFrame(u32 width, u32 height); + + static void BeginScene(const OrthoCamera& camera); static void EndScene(); static void Submit(Ref va, Ref shader, Mat4 transform = Mat4(1.0f)); private: - struct SceneData + struct Storage { - Mat4 VPMatrix; + Mat4 viewProjection; }; - static SceneData* sceneData; + static Storage* data; static API s_RenderAPI; }; } \ No newline at end of file diff --git a/src/bakara/renderer/renderer2D.cpp b/src/bakara/renderer/renderer2D.cpp new file mode 100644 index 0000000..f99dcb2 --- /dev/null +++ b/src/bakara/renderer/renderer2D.cpp @@ -0,0 +1,81 @@ +#include "renderer2D.h" +#include "bakara/renderer/buffer.h" +#include "bakara/renderer/buffer_layout.h" +#include "bakara/renderer/render_command.h" +#include "bakara/renderer/texture.h" + +namespace Bk +{ + Renderer2D::Storage* Renderer2D::data = new Renderer2D::Storage(); + + void Renderer2D::Init() + { + data->shaderLib.Load("assets/shaders/flatColor.glsl"); + data->shaderLib.Load("assets/shaders/texture.glsl"); + data->squareVA = VertexArray::Create(); + + float squareVertices[5 * 4] = { + -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.0f, 1.0f, 1.0f, + -0.5f, 0.5f, 0.0f, 0.0f, 1.0f + }; + Ref squareVB = VertexBuffer::Create(squareVertices, sizeof(squareVertices)); + squareVB->SetLayout({ + { ShaderType::Float3, "a_Position" }, + { ShaderType::Float2, "a_TextCord" } + }); + data->squareVA->AddVertexBuffer(squareVB); + + u32 squareIndices[6] = { 0, 1, 2, 0, 2, 3 }; + data->squareVA->SetIndexbuffer(IndexBuffer::Create(squareIndices, sizeof(squareIndices) / sizeof(u32))); + } + + void Renderer2D::Shutdown() + { + delete data; + } + + void Renderer2D::BeginScene(const OrthoCamera &camera) + { + data->viewProjection = camera.GetViewProjection(); + } + + void Renderer2D::EndScene() + { + + } + + void Renderer2D::DrawQuad(const Vec2& position, const Vec2& size, const Color& color) + { + Renderer2D::DrawQuad(Vec3(position, 0), size, color); + } + + void Renderer2D::DrawQuad(const Vec3& position, const Vec2& size, const Color& color) + { + Ref shader = data->shaderLib["flatColor"]; + data->squareVA->Bind(); + shader->Bind(); + shader->Set("u_FlatColor", color); + shader->Set("u_ViewProjection", data->viewProjection); + shader->Set("u_Transform", Math::scale(Math::translate(Mat4(1.0f), position), Vec3(size, 0))); + RenderCommand::DrawIndexed(data->squareVA); + } + + void Renderer2D::DrawQuad(const Vec2& position, const Vec2& size, const Ref& texture) + { + Renderer2D::DrawQuad(Vec3(position, 0), size, texture); + } + + void Renderer2D::DrawQuad(const Vec3& position, const Vec2& size, const Ref& texture) + { + Ref shader = data->shaderLib["texture"]; + data->squareVA->Bind(); + texture->Bind(); + shader->Bind(); + shader->Set("u_Texture", 0); + shader->Set("u_ViewProjection", data->viewProjection); + shader->Set("u_Transform", Math::scale(Math::translate(Mat4(1.0f), position), Vec3(size, 0))); + RenderCommand::DrawIndexed(data->squareVA); + } +} \ No newline at end of file diff --git a/src/bakara/renderer/renderer2D.h b/src/bakara/renderer/renderer2D.h new file mode 100644 index 0000000..bcaa0e2 --- /dev/null +++ b/src/bakara/renderer/renderer2D.h @@ -0,0 +1,33 @@ +#pragma once + +#include "bakara/renderer/shader.h" +#include "bakara/renderer/texture.h" +#include "bakara/renderer/vertex_array.h" +#include "cameras/ortho_camera.h" + +namespace Bk +{ + class Renderer2D + { + public: + static void Init(); + static void Shutdown(); + + static void BeginScene(const OrthoCamera& camera); + static void EndScene(); + + static void DrawQuad(const Vec2& position, const Vec2& size, const Color& color); + static void DrawQuad(const Vec3& position, const Vec2& size, const Color& color); + static void DrawQuad(const Vec2& position, const Vec2& size, const Ref& texture); + static void DrawQuad(const Vec3& position, const Vec2& size, const Ref& texture); + private: + struct Storage + { + Mat4 viewProjection; + Ref squareVA; + ShaderLibrary shaderLib; + }; + + static Storage* data; + }; +} \ No newline at end of file diff --git a/src/bakara/renderer/renderer_api.h b/src/bakara/renderer/renderer_api.h index c91a4cb..41eb9d0 100644 --- a/src/bakara/renderer/renderer_api.h +++ b/src/bakara/renderer/renderer_api.h @@ -8,7 +8,10 @@ namespace Bk { public: virtual ~RendererAPI() {} + + virtual void Init() = 0; virtual void Clear(float red, float green, float blue, float alpha) = 0; + virtual void SetViewport(u32 width, u32 height) = 0; virtual void DrawIndexed(Ref va) = 0; }; } \ No newline at end of file diff --git a/src/bakara/renderer/shader.cpp b/src/bakara/renderer/shader.cpp index c557917..6481ad5 100644 --- a/src/bakara/renderer/shader.cpp +++ b/src/bakara/renderer/shader.cpp @@ -5,14 +5,56 @@ namespace Bk { - Ref Shader::Create(std::string vertexSrc, std::string fragSrc) + Ref Shader::Create(const std::string& name, const std::string& vertexSrc, const std::string& fragSrc) { switch(Renderer::GetAPI()) { case Renderer::API::None: BK_MSG_ASSERT(false, "API not supported"); return nullptr; - case Renderer::API::Opengl: return CreateRef(vertexSrc, fragSrc); + case Renderer::API::Opengl: return CreateRef(name, vertexSrc, fragSrc); } BK_MSG_ASSERT(false, "API not supported"); return nullptr; } + Ref Shader::Create(const std::string& filePath) + { + switch(Renderer::GetAPI()) + { + case Renderer::API::None: BK_MSG_ASSERT(false, "API not supported"); return nullptr; + case Renderer::API::Opengl: return CreateRef(filePath); + } + BK_MSG_ASSERT(false, "API not supported"); + return nullptr; + } + + void ShaderLibrary::Add(const std::string& name, const Ref& shader) + { + BK_CORE_MSG_ASSERT(!Exists(name), "Shader already exists in library") + shaders[name] = shader; + } + + void ShaderLibrary::Add(const Ref& shader) + { + const auto& name = shader->GetName(); + Add(shader->GetName(), shader); + } + + Ref ShaderLibrary::Load(const std::string& filePath) + { + Ref shader = Shader::Create(filePath); + Add(shader); + return shader; + } + + Ref ShaderLibrary::Load(const std::string& name, const std::string filePath) + { + Ref shader = Shader::Create(filePath); + Add(name, shader); + return shader; + } + + Ref ShaderLibrary::Get(const std::string& name) + { + BK_CORE_MSG_ASSERT(Exists(name), "Shader not found") + return shaders[name]; + } } \ No newline at end of file diff --git a/src/bakara/renderer/shader.h b/src/bakara/renderer/shader.h index a472139..b4afdab 100644 --- a/src/bakara/renderer/shader.h +++ b/src/bakara/renderer/shader.h @@ -3,6 +3,7 @@ #include "bakara/math/types.h" #include "bakatools/container/types.h" #include +#include namespace Bk { @@ -11,6 +12,8 @@ namespace Bk public: virtual ~Shader() {} + virtual const std::string& GetName() = 0; + virtual void Bind() = 0; virtual void Unbind() = 0; @@ -24,6 +27,23 @@ namespace Bk virtual void Set(const std::string name, Mat3 val) = 0; virtual void Set(const std::string name, Mat4 val) = 0; - static Ref Create(std::string vertexSrc, std::string fragSrc); + static Ref Create(const std::string& name, const std::string& vertexSrc, const std::string& fragSrc); + static Ref Create(const std::string& filePath); + }; + + class ShaderLibrary + { + public: + inline bool Exists(const std::string& name) { return shaders.find(name) != shaders.end(); } + + void Add(const std::string& name, const Ref& shader); + void Add(const Ref& shader); + Ref Load(const std::string& filePath); + Ref Load(const std::string& name, const std::string filePath); + + Ref Get(const std::string& name); + inline Ref operator[](const std::string& name) { return Get(name); } + private: + std::unordered_map> shaders; }; } \ No newline at end of file diff --git a/src/bakara/renderer/texture.h b/src/bakara/renderer/texture.h index ed7ba2c..c8919f8 100644 --- a/src/bakara/renderer/texture.h +++ b/src/bakara/renderer/texture.h @@ -11,7 +11,7 @@ namespace Bk virtual ~Texture() {} virtual u32 GetWidth() = 0; virtual u32 GetHeight() = 0; - virtual void Bind() = 0; + virtual void Bind(u32 slot = 0) = 0; }; class Texture2D : public Texture diff --git a/src/platforms/glfw/glfw_window.cpp b/src/platforms/glfw/glfw_window.cpp index 80bee01..e9c7161 100644 --- a/src/platforms/glfw/glfw_window.cpp +++ b/src/platforms/glfw/glfw_window.cpp @@ -3,6 +3,7 @@ #include "bakara/events/key_event.h" #include "bakara/events/mouse_event.h" #include "bakara/events/window_event.h" +#include "bakara/renderer/graphics_context.h" #include "bakatools/logging/assert.h" #include @@ -14,11 +15,6 @@ namespace Bk { } namespace Platform { - GlfwWindowData::~GlfwWindowData() - { - delete context; - } - static uint p_glfw_Initialized = 0; static void glfw_error_callback(int error, const char* description) @@ -41,7 +37,6 @@ namespace Bk { void GlfwWindow::Init() { - h_IsOpen = true; BK_CORE_INFO("Creating window '{0}' ({1}, {2})", p_data.title, p_data.width, p_data.height); if (!p_glfw_Initialized++) { @@ -50,12 +45,10 @@ namespace Bk { glfwSetErrorCallback(glfw_error_callback); } p_window = glfwCreateWindow((int)p_data.width, (int)p_data.height, p_data.title.c_str(), nullptr, nullptr); - p_data.context = new OpenglContext(p_window); - p_data.context->Init(); - p_data.context->SetViewport(p_data.width, p_data.height); + context = GraphicsContext::Create((void*)p_window); + context->Init(); glfwSetWindowUserPointer(p_window, &p_data); SetVsync(true); - InitEventCallbacks(); } @@ -64,7 +57,6 @@ namespace Bk { glfwSetFramebufferSizeCallback(p_window, [](GLFWwindow* window, int width, int height) { GlfwWindowData& data = *(GlfwWindowData*)glfwGetWindowUserPointer(window); - data.context->SetViewport(width, height); WindowResizeEvent e(data.width = (uint)width, data.height = (uint)height); data.callback(e); }); @@ -139,11 +131,7 @@ namespace Bk { dt = DeltaTime(time - lastFrameTime); lastFrameTime = time; glfwPollEvents(); - p_data.context->SwapBuffers(); - if (h_IsOpen) - { - if (p_Shutdown && h_IsOpen) { Shutdown(); } - } + context->SwapBuffers(); } void GlfwWindow::SetEventCallback(const EventCallback callback) @@ -153,38 +141,19 @@ namespace Bk { void GlfwWindow::SetVsync(bool enable) { - if (h_IsOpen) - { - if (enable) { glfwSwapInterval(1); } - else { glfwSwapInterval(0); } - p_data.vsync = enable; - } + if (enable) { glfwSwapInterval(1); } + else { glfwSwapInterval(0); } + p_data.vsync = enable; } bool GlfwWindow::IsVsync() const { return p_data.vsync; } - - void GlfwWindow::Shutdown() - { - h_IsOpen = false; - p_Shutdown = false; - glfwDestroyWindow(p_window); - } void GlfwWindow::Close() { - p_Shutdown = true; - } - - void GlfwWindow::Open() - { - if (!h_IsOpen) - { - Init(); - } + glfwDestroyWindow(p_window); } - } } diff --git a/src/platforms/glfw/glfw_window.h b/src/platforms/glfw/glfw_window.h index 8acce36..cc79e83 100644 --- a/src/platforms/glfw/glfw_window.h +++ b/src/platforms/glfw/glfw_window.h @@ -2,7 +2,7 @@ #include "bakara/core/deltatime.h" #include "bakara/core/window.h" -#include "platforms/opengl/opengl_context.h" +#include "bakara/renderer/graphics_context.h" struct GLFWwindow; @@ -14,8 +14,6 @@ namespace Bk::Platform { uint height; bool vsync; EventCallback callback; - GraphicsContext* context; - ~GlfwWindowData(); }; class GlfwWindow : public Window @@ -34,28 +32,20 @@ namespace Bk::Platform { bool IsVsync() const override; void Close() override; - void Open() override; void* GetNativeWindow() override { return p_window; } - /*! \fn Bk::Window::IsOpen - Indicates if the window is Opened - @return Open flag - */ - bool IsOpen() override { return h_IsOpen; } virtual DeltaTime GetTime() override { return dt; } private: - bool h_IsOpen; //!< indicaste if the window is Opened or not - bool p_Shutdown; - GLFWwindow* p_window; GlfwWindowData p_data; + Scope context; + float lastFrameTime = 0.0f; DeltaTime dt = { 0.0f }; void InitEventCallbacks(); void Init(); - void Shutdown(); }; } \ No newline at end of file diff --git a/src/platforms/opengl/opengl_context.cpp b/src/platforms/opengl/opengl_context.cpp index e410ece..12fb650 100644 --- a/src/platforms/opengl/opengl_context.cpp +++ b/src/platforms/opengl/opengl_context.cpp @@ -6,8 +6,8 @@ namespace Bk::Platform { - OpenglContext::OpenglContext(GLFWwindow* window_handle) - : window_handle(window_handle) {} + OpenglContext::OpenglContext(void* window_handle) + : window_handle((GLFWwindow*)window_handle) {} void OpenglContext::Init() { @@ -30,9 +30,4 @@ namespace Bk::Platform { glfwSwapBuffers(window_handle); } - - void OpenglContext::SetViewport(int width, int height) - { - glViewport(0, 0, width, height); - } } \ No newline at end of file diff --git a/src/platforms/opengl/opengl_context.h b/src/platforms/opengl/opengl_context.h index eb47e1f..8e77f90 100644 --- a/src/platforms/opengl/opengl_context.h +++ b/src/platforms/opengl/opengl_context.h @@ -10,11 +10,10 @@ namespace Bk::Platform class OpenglContext : public GraphicsContext { public: - OpenglContext(GLFWwindow* window_handle); + OpenglContext(void* window_handle); virtual ~OpenglContext() override { } void Init() override; void SwapBuffers() override; - void SetViewport(int width, int height) override; private: GLFWwindow* window_handle; }; diff --git a/src/platforms/opengl/opengl_renderer_api.cpp b/src/platforms/opengl/opengl_renderer_api.cpp index 2f9ed4a..04cc672 100644 --- a/src/platforms/opengl/opengl_renderer_api.cpp +++ b/src/platforms/opengl/opengl_renderer_api.cpp @@ -3,12 +3,24 @@ namespace Bk { + void OpenglRendererAPI::Init() + { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_DEPTH_TEST); + } + void OpenglRendererAPI::Clear(float red, float green, float blue, float alpha) { glClearColor(red, green, blue, alpha); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } + void OpenglRendererAPI::SetViewport(u32 width, u32 height) + { + glViewport(0, 0, width, height); + } + void OpenglRendererAPI::DrawIndexed(Ref va) { glDrawElements(GL_TRIANGLES, va->GetIndexbuffer()->GetCount(), GL_UNSIGNED_INT, nullptr); diff --git a/src/platforms/opengl/opengl_renderer_api.h b/src/platforms/opengl/opengl_renderer_api.h index 731a33f..d4eded3 100644 --- a/src/platforms/opengl/opengl_renderer_api.h +++ b/src/platforms/opengl/opengl_renderer_api.h @@ -2,13 +2,16 @@ #include "bakara/renderer/renderer_api.h" #include "bakara/renderer/vertex_array.h" +#include "bakatools/container/types.h" namespace Bk { class OpenglRendererAPI : public RendererAPI { public: + virtual void Init() override; virtual void Clear(float red, float green, float blue, float alpha) override; + virtual void SetViewport(u32 width, u32 height) override; virtual void DrawIndexed(Ref va) override; }; } \ No newline at end of file diff --git a/src/platforms/opengl/opengl_shader.cpp b/src/platforms/opengl/opengl_shader.cpp index 9c34505..5dcad59 100644 --- a/src/platforms/opengl/opengl_shader.cpp +++ b/src/platforms/opengl/opengl_shader.cpp @@ -1,48 +1,98 @@ #include "opengl_shader.h" -#include "bakatools/logging/log.h" +#include "bakatools/file_system/file.h" +#include "bakatools/logging/assert.h" #include "bakara/math/types.h" -#include +#include "bakatools/logging/log.h" +#include namespace Bk::Platform -{ - OpenglShader::OpenglShader(std::string vertexSrc, std::string fragSrc) +{ + static GLenum ShaderTypeFromString(std::string type) { - int success; - char infoLog[512]; - //Creating a shader program - id = glCreateProgram(); - //Compile shader - GLuint ret = glCreateShader(GL_VERTEX_SHADER); - const GLchar* shader = vertexSrc.c_str(); - glShaderSource(ret, 1, &shader, NULL); - glCompileShader(ret); - glGetShaderiv(ret, GL_COMPILE_STATUS, &success); - if(!success) { - glGetShaderInfoLog(ret, 512, NULL, infoLog); - BK_INFO("Error with fragment shader compilating : {0}", infoLog); + if (type == "vertex") return GL_VERTEX_SHADER; + else if (type == "fragment" || type == "pixel") return GL_FRAGMENT_SHADER; + BK_CORE_MSG_ASSERT(false, "An known shader type") + return 0; + } + + OpenglShader::OpenglShader(const std::string& filePath) + { + File file = File(filePath); + BK_CORE_MSG_ASSERT(file.exists(), "Shader file not found") + std::string filename = file.name(); + size_t pos = filename.find_last_of("."); + name = pos == std::string::npos ? filename : filename.substr(0, pos); + std::string source = file.read(); + auto sources = PreProcess(source); + Compile(sources); + + } + + OpenglShader::OpenglShader(const std::string& name, const std::string& vertexSrc, const std::string& fragSrc) + : name(name) + { + Compile({ + { GL_VERTEX_SHADER, vertexSrc }, + { GL_FRAGMENT_SHADER, fragSrc } + }); + } + + std::unordered_map OpenglShader::PreProcess(std::string source) + { + std::unordered_map sources; + const std::string token("#type"); + size_t pos = source.find(token, 0); + BK_CORE_MSG_ASSERT(pos != std::string::npos, "Not shader found in file") + while (pos != std::string::npos) + { + size_t eol = source.find_first_of("\n", pos); + BK_CORE_MSG_ASSERT(eol != std::string::npos, "Syntax Error in shader file"); + size_t begin = pos + token.length() + 1; + std::string type = source.substr(begin, eol - begin); + GLenum glType = ShaderTypeFromString(type); + size_t nextLine = source.find_first_not_of("\n", eol); + pos = source.find(token, nextLine); + sources[glType] = (pos == std::string::npos) ? source.substr(nextLine) : source.substr(nextLine, pos - nextLine); } - glAttachShader(id, ret); - - GLuint ret1 = glCreateShader(GL_FRAGMENT_SHADER); - shader = fragSrc.c_str(); - glShaderSource(ret1, 1, &shader, NULL); - glCompileShader(ret1); - glGetShaderiv(ret1, GL_COMPILE_STATUS, &success); - if(!success) { - glGetShaderInfoLog(ret1, 512, NULL, infoLog); - BK_INFO("Error with fragment shader compilating : {0}", infoLog); + return sources; + } + + void OpenglShader::Compile(std::unordered_map sources) + { + std::vector shaders; + id = glCreateProgram(); + for(auto& kv : sources) + { + GLenum type = kv.first; + const GLchar* shaderSrc = kv.second.c_str(); + GLuint shader = glCreateShader(type); + glShaderSource(shader, 1, &shaderSrc, NULL); + glCompileShader(shader); + int info; + glGetShaderiv(shader, GL_COMPILE_STATUS, &info); + if(!info) { + std::vector infoLog; + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info); + infoLog.resize(info); + glGetShaderInfoLog(shader, infoLog.size(), NULL, infoLog.data()); + BK_CORE_ERROR("Shader Error : {0}", std::string(infoLog.data(),infoLog.size())); + BK_MSG_ASSERT(false, "Error with shader compilation") + } + glAttachShader(id, shader); + shaders.push_back(shader); } - glAttachShader(id, ret1); glLinkProgram(id); - - glGetProgramiv(id, GL_LINK_STATUS, &success); - if(!success) { - glGetProgramInfoLog(id, 512, NULL, infoLog); - BK_INFO("Error when link sharder in a program : {0}", infoLog); + int info; + glGetProgramiv(id, GL_LINK_STATUS, &info); + if(!info) { + std::vector infoLog; + glGetShaderiv(id, GL_INFO_LOG_LENGTH, &info); + infoLog.resize(info); + glGetProgramInfoLog(id, infoLog.size(), NULL, infoLog.data()); + BK_CORE_ERROR("Shader Error : {0}", std::string(infoLog.data(),infoLog.size())); + BK_MSG_ASSERT(false, "Error when link sharder in a program") } - - glDeleteShader(ret); - glDeleteShader(ret1); + for(auto shader : shaders) glDeleteShader(shader); } OpenglShader::~OpenglShader() @@ -92,7 +142,7 @@ namespace Bk::Platform void OpenglShader::Set(const std::string name, Vec4 v) { - glUniformMatrix3fv(glGetUniformLocation(this->id, name.c_str()), 1, GL_FALSE, Math::value_ptr(v)); + this->Set(name, v.x, v.y, v.z, v.w); } void OpenglShader::Set(const std::string name, Mat3 val) diff --git a/src/platforms/opengl/opengl_shader.h b/src/platforms/opengl/opengl_shader.h index 033a403..40eca71 100644 --- a/src/platforms/opengl/opengl_shader.h +++ b/src/platforms/opengl/opengl_shader.h @@ -1,15 +1,21 @@ #pragma once #include "bakara/renderer/shader.h" +#include +#include +#include namespace Bk::Platform { class OpenglShader : public Shader { public: - OpenglShader(std::string vertexSrc, std::string fragSrc); + OpenglShader(const std::string& filePath); + OpenglShader(const std::string& name, const std::string& vertexSrc, const std::string& fragSrc); virtual ~OpenglShader(); + virtual const std::string& GetName() override { return name; } + virtual void Bind() override; virtual void Unbind() override; @@ -25,5 +31,8 @@ namespace Bk::Platform private: unsigned int id; + std::string name; + std::unordered_map PreProcess(std::string source); + void Compile(std::unordered_map sources); }; } \ No newline at end of file diff --git a/src/platforms/opengl/opengl_texture.cpp b/src/platforms/opengl/opengl_texture.cpp index ca1ad75..ec06bc4 100644 --- a/src/platforms/opengl/opengl_texture.cpp +++ b/src/platforms/opengl/opengl_texture.cpp @@ -1,4 +1,6 @@ #include "opengl_texture.h" +#include "bakatools/logging/assert.h" +#include "bakatools/logging/log.h" #include #include @@ -7,16 +9,40 @@ namespace Bk::Platform { OpenglTexture2D::OpenglTexture2D(const std::string& filePath) { + stbi_set_flip_vertically_on_load(true); + int width, height, channels; + stbi_uc* data = stbi_load(filePath.c_str(), &width, &height, &channels, 0); + + BK_CORE_MSG_ASSERT(data, "Coudn't load image data") + BK_CORE_MSG_ASSERT(channels >= 3 && channels <= 4, "Image format not supported") + this->width = (u32)width; + this->height = (u32)height; + + GLenum internalFormat = 0, format = 0; + if(channels == 4) { internalFormat = GL_RGBA8; format = GL_RGBA; } + else { internalFormat = GL_RGB8; format = GL_RGB; } + + glGenTextures(1, &id); + glBindTexture(GL_TEXTURE_2D, id); + glTexStorage2D(GL_TEXTURE_2D, 1, internalFormat, this->width, this->height); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, this->width, this->height, format, GL_UNSIGNED_BYTE, data); + + stbi_image_free(data); } OpenglTexture2D::~OpenglTexture2D() { - + glDeleteTextures(1, &id); } - void OpenglTexture2D::Bind() + void OpenglTexture2D::Bind(u32 slot) { - + glActiveTexture(GL_TEXTURE0 + slot); + glBindTexture(GL_TEXTURE_2D, id); } } \ No newline at end of file diff --git a/src/platforms/opengl/opengl_texture.h b/src/platforms/opengl/opengl_texture.h index a9107cc..cb92046 100644 --- a/src/platforms/opengl/opengl_texture.h +++ b/src/platforms/opengl/opengl_texture.h @@ -12,7 +12,7 @@ namespace Bk::Platform virtual u32 GetWidth() override { return width; } virtual u32 GetHeight() override { return height; } - virtual void Bind() override; + virtual void Bind(u32 slot = 0) override; private: u32 id; u32 width, height;