diff --git a/Editor/Editor.cpp b/Editor/Editor.cpp index a8443f64..178185c2 100644 --- a/Editor/Editor.cpp +++ b/Editor/Editor.cpp @@ -99,10 +99,7 @@ namespace DT ImGui::EndFrame(); ImGui::Render(); ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); - - renderer->BindFrameBuffer(renderer->GetRenderFBO()); } - void Editor::Close() { diff --git a/Editor/EditorCamera.h b/Editor/EditorCamera.h new file mode 100644 index 00000000..7313d855 --- /dev/null +++ b/Editor/EditorCamera.h @@ -0,0 +1,66 @@ +/* +MIT License + +Copyright (c) 2021 - 2023 Aryan Baburajan + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#pragma once + +#include + +namespace DT +{ + class EditorCamera : public BaseCamera + { + public: + Transform transform; + + using BaseCamera::BaseCamera; + + void Recalculate(Window *window) + { + PROFILE(); + + view = glm::lookAtLH(transform.translation, transform.translation + transform.Forward(), transform.Up()); + + glm::vec2 winSize = window->GetWindowSize(); + float aspect = (float)winSize.x/winSize.y; + if (isOrthographic) + projection = glm::orthoLH(-aspect, aspect, -1.0f, 1.0f, nearPlane, farPlane); + else + projection = glm::perspectiveLH(glm::radians(fieldOfView), window->GetWindowSize().x / window->GetWindowSize().y, nearPlane, farPlane); + } + + glm::vec3 GetPosition() override + { + PROFILE(); + + return transform.translation; + } + + glm::quat GetRotation() override + { + PROFILE(); + + return transform.rotation; + } + }; +} \ No newline at end of file diff --git a/Editor/Panels/GameView.h b/Editor/Panels/GameView.h index d04a6393..4f5a1b03 100644 --- a/Editor/Panels/GameView.h +++ b/Editor/Panels/GameView.h @@ -35,49 +35,52 @@ namespace DT void Init(Context &ctx) override { PROFILE(); + + isOpen = false; - renderer = ctx.GetService().Fatal("WorldViewPanel::Init()"); - window = ctx.GetService().Fatal("WorldViewPanel::Init()"); + renderer = ctx.GetService().Fatal("GameViewPanel::Init()"); + window = ctx.GetService().Fatal("GameViewPanel::Init()"); } void Tick(Context &ctx, const float &dt) override { PROFILE(); - - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.f, 0.f)); - ImGui::Begin("World View", &isOpen); - - sceneViewActive = ImGui::IsWindowFocused() || ImGui::IsWindowHovered(); - ImVec2 vMin = ImGui::GetWindowContentRegionMin(); - ImVec2 vMax = ImGui::GetWindowContentRegionMax(); - - vMin.x += ImGui::GetWindowPos().x; - vMin.y += ImGui::GetWindowPos().y; - vMax.x += ImGui::GetWindowPos().x; - vMax.y += ImGui::GetWindowPos().y; - - windowPos = vMin; - - ImVec2 windowSize = ImVec2(vMax.x - vMin.x, vMax.y - vMin.y); - - if (window->GetWindowSize() != glm::vec2(windowSize.x, windowSize.y)) - { - if (glm::vec2(windowSize.x, windowSize.y) != glm::vec2(0.f, 0.f)) - { - window->SetWindowSize({windowSize.x, windowSize.y}); - renderer->SetViewport({windowSize.x, windowSize.y}); - } - } - - ImGui::GetWindowDrawList()->AddImage( - (ImTextureID)(uintptr_t)renderer->GetRenderFBO(), - vMin, - vMax, - ImVec2(0, 1), - ImVec2(1, 0)); - - ImGui::End(); - ImGui::PopStyleVar(); + + /// Proper Game Runtime to be implemented in the future + // ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.f, 0.f)); + // ImGui::Begin("Game View", &isOpen); + + // sceneViewActive = ImGui::IsWindowFocused() || ImGui::IsWindowHovered(); + // ImVec2 vMin = ImGui::GetWindowContentRegionMin(); + // ImVec2 vMax = ImGui::GetWindowContentRegionMax(); + + // vMin.x += ImGui::GetWindowPos().x; + // vMin.y += ImGui::GetWindowPos().y; + // vMax.x += ImGui::GetWindowPos().x; + // vMax.y += ImGui::GetWindowPos().y; + + // windowPos = vMin; + + // ImVec2 windowSize = ImVec2(vMax.x - vMin.x, vMax.y - vMin.y); + + // if (window->GetWindowSize() != glm::vec2(windowSize.x, windowSize.y)) + // { + // if (glm::vec2(windowSize.x, windowSize.y) != glm::vec2(0.f, 0.f)) + // { + // window->SetWindowSize({windowSize.x, windowSize.y}); + // renderer->SetViewport({windowSize.x, windowSize.y}); + // } + // } + + // ImGui::GetWindowDrawList()->AddImage( + // (ImTextureID)(uintptr_t)Camera::GetActiveCamera()->renderTexture, + // vMin, + // vMax, + // ImVec2(0, 1), + // ImVec2(1, 0)); + + // ImGui::End(); + // ImGui::PopStyleVar(); } private: diff --git a/Editor/Panels/WorldOutliner.h b/Editor/Panels/WorldOutliner.h index 53bab075..9ada5123 100644 --- a/Editor/Panels/WorldOutliner.h +++ b/Editor/Panels/WorldOutliner.h @@ -26,6 +26,7 @@ SOFTWARE. #include #include +#include namespace DT { @@ -37,6 +38,7 @@ namespace DT PROFILE(); sceneManager = ctx.GetService().Fatal("WorldOutlinerPanel::Init()"); + worldView = editor->GetPanel().Fatal("InspectorPanel::Init()"); } void Tick(Context &ctx, const float &dt) override @@ -45,6 +47,8 @@ namespace DT ImGui::Begin("World Outliner", &isOpen); + worldView->editorCamera.transform.InspectorMenu(ctx, dt); + for (Entity entity : sceneManager->activeScene.GetEntities()) { std::string label; @@ -67,6 +71,7 @@ namespace DT private: SceneManager *sceneManager; + WorldViewPanel *worldView; Entity selectedEntity = 0; friend class InspectorPanel; diff --git a/Editor/Panels/WorldView.h b/Editor/Panels/WorldView.h index b7e25aef..d99a1d3d 100644 --- a/Editor/Panels/WorldView.h +++ b/Editor/Panels/WorldView.h @@ -25,18 +25,133 @@ SOFTWARE. #pragma once #include +#include namespace DT { class WorldViewPanel : public Panel { public: + EditorCamera editorCamera; + + WorldViewPanel(Context &ctx) : editorCamera(ctx) {} + + void Init(Context &ctx) override + { + PROFILE(); + + renderer = ctx.GetService().Fatal("WorldViewPanel::Init()"); + window = ctx.GetService().Fatal("WorldViewPanel::Init()"); + sceneManager = ctx.GetService().Fatal("WorldViewPanel::Init()"); + input = ctx.GetService().Fatal("WorldViewPanel::Init()"); + + editorCamera.transform.translation = glm::vec3(0.f, 0.f, -3.f); + } + void Tick(Context &ctx, const float &dt) override { PROFILE(); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.f, 0.f)); ImGui::Begin("World View", &isOpen); + + sceneViewActive = ImGui::IsWindowFocused() || ImGui::IsWindowHovered(); + ImVec2 vMin = ImGui::GetWindowContentRegionMin(); + ImVec2 vMax = ImGui::GetWindowContentRegionMax(); + + vMin.x += ImGui::GetWindowPos().x; + vMin.y += ImGui::GetWindowPos().y; + vMax.x += ImGui::GetWindowPos().x; + vMax.y += ImGui::GetWindowPos().y; + + windowPos = vMin; + + ImVec2 windowSize = ImVec2(vMax.x - vMin.x, vMax.y - vMin.y); + + if (window->GetWindowSize() != glm::vec2(windowSize.x, windowSize.y)) + { + if (glm::vec2(windowSize.x, windowSize.y) != glm::vec2(0.f, 0.f)) + { + window->SetWindowSize({windowSize.x, windowSize.y}); + renderer->SetViewport({windowSize.x, windowSize.y}); + } + } + + // Freelook + if (sceneViewActive) + { + if (editorCamera.isOrthographic) + { + if (input->IsKeyHeld(KEY_W)) + editorCamera.transform.translation += speed * dt * editorCamera.transform.Up(); + if (input->IsKeyHeld(KEY_A)) + editorCamera.transform.translation -= speed * dt * editorCamera.transform.Right(); + if (input->IsKeyHeld(KEY_S)) + editorCamera.transform.translation -= speed * dt * editorCamera.transform.Up(); + if (input->IsKeyHeld(KEY_D)) + editorCamera.transform.translation += speed * dt * editorCamera.transform.Right(); + + editorCamera.transform.translation.z = -3.f; + editorCamera.transform.SetEulerRotation({0.f, 180.f, 0.f}); + } + else + { + if (input->IsKeyHeld(KEY_W)) + editorCamera.transform.translation += speed * dt * editorCamera.transform.Forward(); + if (input->IsKeyHeld(KEY_A)) + editorCamera.transform.translation -= speed * dt * editorCamera.transform.Right(); + if (input->IsKeyHeld(KEY_S)) + editorCamera.transform.translation -= speed * dt * editorCamera.transform.Forward(); + if (input->IsKeyHeld(KEY_D)) + editorCamera.transform.translation += speed * dt * editorCamera.transform.Right(); + if (input->IsKeyHeld(KEY_SPACE)) + editorCamera.transform.translation += speed * dt * glm::vec3(0.f, 1.f, 0.f); + if (input->IsKeyHeld(KEY_LEFT_SHIFT)) + editorCamera.transform.translation -= speed * dt * glm::vec3(0.f, 1.f, 0.f); + if (input->IsKeyHeld(KEY_E)) + orientation.z += sensitivity * dt; + if (input->IsKeyHeld(KEY_Q)) + orientation.z -= sensitivity * dt; + + // Look + orientation.y += input->GetMouseDelta().x * sensitivity * dt; + orientation.x += -input->GetMouseDelta().y * sensitivity * dt; + + if (orientation.x < -90.0f) + orientation.x = -90.0f; + if (orientation.x > 90.0f) + orientation.x = 90.0f; + + orientation = glm::angNormalize(orientation); + editorCamera.transform.SetEulerRotation(orientation); + } + } + + // Render + editorCamera.transform.LookAt(glm::vec3(1.f, 0.f, 0.f)); + + ImGui::GetWindowDrawList()->AddImage( + (ImTextureID)(uintptr_t)editorCamera.renderTexture, + vMin, + vMax, + ImVec2(0, 1), + ImVec2(1, 0)); + ImGui::End(); + ImGui::PopStyleVar(); } + + private: + bool sceneViewActive; + ImVec2 windowPos, windowSize; + + glm::vec3 orientation; + float speed = 2.5f, sensitivity = 75.f; + float lastx; + + Renderer *renderer; + Window *window; + SceneManager *sceneManager; + InputManager *input; }; } \ No newline at end of file diff --git a/Engine/Components/Camera.cpp b/Engine/Components/Camera.cpp index e563f7e6..ef67f506 100644 --- a/Engine/Components/Camera.cpp +++ b/Engine/Components/Camera.cpp @@ -46,6 +46,5 @@ namespace DT projection = glm::orthoLH(-aspect, aspect, -1.0f, 1.0f, nearPlane, farPlane); else projection = glm::perspectiveLH(glm::radians(fieldOfView), window->GetWindowSize().x / window->GetWindowSize().y, nearPlane, farPlane); - } } \ No newline at end of file diff --git a/Engine/Components/Camera.h b/Engine/Components/Camera.h index c7002c32..ff6f5e48 100644 --- a/Engine/Components/Camera.h +++ b/Engine/Components/Camera.h @@ -29,35 +29,43 @@ SOFTWARE. #include #include #include +#include namespace DT { - class Camera : public Component + class Camera : public Component, public BaseCamera { public: - float fieldOfView = 75.f, nearPlane = 0.1f, farPlane = 100.f; - glm::mat4 projection, view; - bool isOrthographic = false; + Camera(Context &ctx) : BaseCamera(ctx) + { + activeCamera = std::shared_ptr(this); + } void Init(Context &ctx) override; void Tick(Context &ctx, const float &dt) override; - - inline glm::vec3 GetPosition() + + glm::vec3 GetPosition() override { PROFILE(); return transform->translation; } - inline glm::quat GetRotation() + glm::quat GetRotation() override { PROFILE(); return transform->rotation; } + static std::shared_ptr GetActiveCamera() + { + return activeCamera; + } + private: std::shared_ptr transform; + static inline std::shared_ptr activeCamera; Window *window; }; } \ No newline at end of file diff --git a/Engine/Components/SpriteRenderer.cpp b/Engine/Components/SpriteRenderer.cpp index 7ab46981..b337fe10 100644 --- a/Engine/Components/SpriteRenderer.cpp +++ b/Engine/Components/SpriteRenderer.cpp @@ -53,4 +53,11 @@ namespace DT mesh.Draw(*renderer, transform->GetModelMatrix(), material); } + + void SpriteRenderer::EditorTick(Context &ctx, const float &dt) + { + PROFILE(); + + mesh.Draw(*renderer, transform->GetModelMatrix(), material); + } } \ No newline at end of file diff --git a/Engine/Components/SpriteRenderer.h b/Engine/Components/SpriteRenderer.h index b7821963..96cb7a15 100644 --- a/Engine/Components/SpriteRenderer.h +++ b/Engine/Components/SpriteRenderer.h @@ -38,8 +38,9 @@ namespace DT public: SpriteRenderer(Context *ctx, const std::filesystem::path &texturePath); - void Init(Context &ctx); + void Init(Context &ctx) override; void Tick(Context &ctx, const float &dt) override; + void EditorTick(Context &ctx, const float &dt) override; private: Mesh &mesh = Mesh::Quad(); diff --git a/Engine/Core/EventSystem.h b/Engine/Core/EventSystem.h new file mode 100644 index 00000000..2604d02c --- /dev/null +++ b/Engine/Core/EventSystem.h @@ -0,0 +1,53 @@ +/* +MIT License + +Copyright (c) 2021 - 2023 Aryan Baburajan + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#pragma once + +namespace DT +{ + class Colleague + { + public: + virtual void Receive(const std::string &message) = 0; + }; + + class Mediator + { + public: + void RegisterColleague(Colleague *colleague) + { + colleagues.push_back(colleague); + } + + void SendMessage(Colleague *sender, const std::string &message) + { + for (Colleague *colleague : colleagues) + if (colleague != sender) + colleague->Receive(message); + } + + private: + std::vector colleagues; + }; +} \ No newline at end of file diff --git a/Engine/ECS/Component.h b/Engine/ECS/Component.h index eb6b0a68..bf1a9214 100644 --- a/Engine/ECS/Component.h +++ b/Engine/ECS/Component.h @@ -39,6 +39,7 @@ namespace DT virtual void Init(Context &ctx) {} virtual void Tick(Context &ctx, const float &dt) {} + virtual void EditorTick(Context &ctx, const float &dt) {} virtual void InspectorMenu(Context &ctx, const float &dt) {} }; } \ No newline at end of file diff --git a/Engine/ECS/Scene.cpp b/Engine/ECS/Scene.cpp index ccebd8b0..2ab8c101 100644 --- a/Engine/ECS/Scene.cpp +++ b/Engine/ECS/Scene.cpp @@ -23,6 +23,7 @@ SOFTWARE. */ #include +#include namespace DT { @@ -45,4 +46,13 @@ namespace DT return ErrorOr>>("Invalid entity.\n"); return components.at(entity); } + + ErrorOr Scene::GetEntityNamed(const std::string &name) + { + for (Entity entity : GetEntities()) + if (Has(entity)) + if (Get(entity).Fatal("Scene::GetEntityWithName()")->name == name) + return entity; + return ErrorOr("No entity named " + name + ".\n"); + } } \ No newline at end of file diff --git a/Engine/ECS/Scene.h b/Engine/ECS/Scene.h index dcb0e180..3e615cee 100644 --- a/Engine/ECS/Scene.h +++ b/Engine/ECS/Scene.h @@ -35,6 +35,7 @@ namespace DT public: std::unordered_set GetEntities(); ErrorOr>> View(Entity entity); + ErrorOr GetEntityNamed(const std::string &name); bool IsValid(Entity entity) { diff --git a/Engine/ECS/SceneManager.cpp b/Engine/ECS/SceneManager.cpp index 6a509e4a..6ab53d6f 100644 --- a/Engine/ECS/SceneManager.cpp +++ b/Engine/ECS/SceneManager.cpp @@ -62,4 +62,13 @@ namespace DT for (std::pair> &component : activeScene.View(entity).Fatal("SceneManager::Tick()")) component.second->Tick(ctx, deltaTime); } + + void SceneManager::EditorTick(Context &ctx, const float &deltaTime) + { + PROFILE(); + + for (Entity entity : activeScene.GetEntities()) + for (std::pair> &component : activeScene.View(entity).Fatal("SceneManager::Tick()")) + component.second->EditorTick(ctx, deltaTime); + } } \ No newline at end of file diff --git a/Engine/ECS/SceneManager.h b/Engine/ECS/SceneManager.h index 07cd9cff..de6c1399 100644 --- a/Engine/ECS/SceneManager.h +++ b/Engine/ECS/SceneManager.h @@ -43,5 +43,6 @@ namespace DT void Init(Context &ctx); void Tick(Context &ctx, const float &deltaTime); + void EditorTick(Context &ctx, const float &deltaTime); }; } \ No newline at end of file diff --git a/Engine/Renderer/BaseCamera.cpp b/Engine/Renderer/BaseCamera.cpp new file mode 100644 index 00000000..2642e8ef --- /dev/null +++ b/Engine/Renderer/BaseCamera.cpp @@ -0,0 +1,30 @@ +/* +MIT License + +Copyright (c) 2021 - 2023 Aryan Baburajan + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#include + +namespace DT +{ + std::unordered_set BaseCamera::cameras; +} \ No newline at end of file diff --git a/Engine/Renderer/BaseCamera.h b/Engine/Renderer/BaseCamera.h new file mode 100644 index 00000000..05ac6c27 --- /dev/null +++ b/Engine/Renderer/BaseCamera.h @@ -0,0 +1,88 @@ +/* +MIT License + +Copyright (c) 2021 - 2023 Aryan Baburajan + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#pragma once + +#include +#include +#include + +namespace DT +{ + class BaseCamera + { + public: + float fieldOfView = 75.f, nearPlane = 0.1f, farPlane = 100.f; + glm::mat4 projection, view; + bool isOrthographic = false; + unsigned int FBO, RBO, renderTexture; + + static std::unordered_set cameras; + + BaseCamera(Context &ctx) + { + Window *window = ctx.GetService().Fatal("BaseCamera::BaseCamera()"); + + // FBO + glGenFramebuffers(1, &FBO); + glBindFramebuffer(GL_FRAMEBUFFER, FBO); + + // Texture + glGenTextures(1, &renderTexture); + glBindTexture(GL_TEXTURE_2D, renderTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, window->GetWindowSize().x, window->GetWindowSize().y, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTexture, 0); + + // RBO + glGenRenderbuffers(1, &RBO); + glBindRenderbuffer(GL_RENDERBUFFER, RBO); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, window->GetWindowSize().x, window->GetWindowSize().y); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, RBO); + + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + { + std::cout << "[ERR] Framebuffer incomplete!\n"; + return; + } + + cameras.insert(this); + } + + void SetViewportSize(const glm::vec2 &viewportSize) + { + glBindTexture(GL_TEXTURE_2D, renderTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, viewportSize.x, viewportSize.y, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); + glBindTexture(GL_TEXTURE_2D, 0); + + glBindRenderbuffer(GL_RENDERBUFFER, RBO); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, viewportSize.x, viewportSize.y); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + } + + virtual glm::vec3 GetPosition() = 0; + virtual glm::quat GetRotation() = 0; + }; +} \ No newline at end of file diff --git a/Engine/Renderer/Renderer.cpp b/Engine/Renderer/Renderer.cpp index 67b7eaf2..4f8a82b4 100644 --- a/Engine/Renderer/Renderer.cpp +++ b/Engine/Renderer/Renderer.cpp @@ -57,51 +57,22 @@ GLenum glCheckError_(const char *file, int line) namespace DT { - Renderer::Renderer(Context &ctx, const json &rendererData) : - screenShader(Shader::Load(ctx.projectPath / "Engine" / "Shaders" / "Screen.frag", ctx.projectPath / "Engine" / "Shaders" / "Screen.vert").Fatal("Renderer::Renderer()")) + Renderer::Renderer(Context &ctx, const json &rendererData) : screenShader(Shader::Load(ctx.projectPath / "Engine" / "Shaders" / "Screen.frag", ctx.projectPath / "Engine" / "Shaders" / "Screen.vert").Fatal("Renderer::Renderer()")) { renderFrameBuffer = rendererData.value("renderFrameBuffer", true); - - glEnable(GL_DEPTH_TEST); - window = ctx.GetService().Fatal("Renderer::Renderer()"); glfwSetFramebufferSizeCallback(window->GetRawWindowPointer(), FramebufferSizeCallback); - // FBO - glGenFramebuffers(1, &FBO); - BindFrameBuffer(FBO); - - // Texture - glGenTextures(1, &renderTexture); - glBindTexture(GL_TEXTURE_2D, renderTexture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, window->GetWindowSize().x, window->GetWindowSize().y, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTexture, 0); - - // RBO - glGenRenderbuffers(1, &RBO); - glBindRenderbuffer(GL_RENDERBUFFER, RBO); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, window->GetWindowSize().x, window->GetWindowSize().y); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, RBO); - - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) - { - std::cout << "[ERR] Framebuffer incomplete!\n"; - return; - } - // Quad - float quadVertices[] = {// vertex attributes for a quad that fills the entire screen in Normalized Device Coordinates. - // positions // texCoords - -1.0f, 1.0f, 0.0f, 1.0f, - -1.0f, -1.0f, 0.0f, 0.0f, - 1.0f, -1.0f, 1.0f, 0.0f, + float quadVertices[] = { + -1.0f, 1.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 0.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 0.0f, - -1.0f, 1.0f, 0.0f, 1.0f, - 1.0f, -1.0f, 1.0f, 0.0f, - 1.0f, 1.0f, 1.0f, 1.0f}; + -1.0f, 1.0f, 0.0f, 1.0f, + 1.0f, -1.0f, 1.0f, 0.0f, + 1.0f, 1.0f, 1.0f, 1.0f}; glGenVertexArrays(1, &quadVAO); glGenBuffers(1, &quadVBO); @@ -112,13 +83,15 @@ namespace DT glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void *)0); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void *)(2 * sizeof(float))); - + std::cout << "[LOG] Renderer Constructed\n"; } - void Renderer::BeginScene() + void Renderer::BeginScene(BaseCamera *camera) { - BindFrameBuffer(FBO); + activeRenderCamera = camera; + + BindFrameBuffer(activeRenderCamera->FBO); glEnable(GL_DEPTH_TEST); glClearColor(0.15f, 0.15f, 0.15f, 1.0f); @@ -130,46 +103,24 @@ namespace DT BindFrameBuffer(0); glDisable(GL_DEPTH_TEST); - glClearColor(1.f, 1.f, 1.f, 1.0f); + glClearColor(0.f, 1.f, 0.f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); if (renderFrameBuffer) { - screenShader.Use().Fatal("Renderer::Renderer()"); + screenShader.Use().Fatal("Renderer::EndScene()"); glBindVertexArray(quadVAO); - glBindTexture(GL_TEXTURE_2D, renderTexture); + glBindTexture(GL_TEXTURE_2D, activeRenderCamera->renderTexture); glDrawArrays(GL_TRIANGLES, 0, 6); } } - void Renderer::FetchCamera(Context &ctx) + void Renderer::SetViewport(const glm::vec2 &newViewportSize) { - Scene &scene = ctx.GetService().Fatal("Renderer::Init()")->activeScene; - for (Entity entity : scene.GetEntities()) - { - if (scene.Has(entity)) - { - camera = scene.Get(entity).Fatal("Renderer::Renderer()"); - return; - } - } - } - - void Renderer::SetCamera(std::shared_ptr cam) - { - camera = cam; - } - - void Renderer::SetViewport(const glm::vec2 &viewportSize) - { - customViewportSize = viewportSize; - glBindTexture(GL_TEXTURE_2D, renderTexture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, customViewportSize.x, customViewportSize.y, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); - glBindTexture(GL_TEXTURE_2D, 0); - - glBindRenderbuffer(GL_RENDERBUFFER, RBO); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, customViewportSize.x, customViewportSize.y); - glBindRenderbuffer(GL_RENDERBUFFER, 0); + viewportSize = newViewportSize; + + for (BaseCamera *cam : BaseCamera::cameras) + cam->SetViewportSize(viewportSize); } Error Renderer::ActivateShader(Shader &shader) @@ -177,10 +128,10 @@ namespace DT Error err = shader.Use(); if (err.HasError()) return err; - shader.SetMat4("projection", camera->projection); - shader.SetMat4("view", camera->view); - shader.SetVec3("viewPos", camera->GetPosition()); - + shader.SetMat4("projection", activeRenderCamera->projection); + shader.SetMat4("view", activeRenderCamera->view); + shader.SetVec3("viewPos", activeRenderCamera->GetPosition()); + return Error(); } diff --git a/Engine/Renderer/Renderer.h b/Engine/Renderer/Renderer.h index 2e40e98c..f1d5264c 100644 --- a/Engine/Renderer/Renderer.h +++ b/Engine/Renderer/Renderer.h @@ -42,13 +42,10 @@ namespace DT public: Renderer(Context &ctx, const json &rendererData); - void BeginScene(); + void BeginScene(BaseCamera *camera); void EndScene(); - void FetchCamera(Context &ctx); - void SetCamera(std::shared_ptr cam); - - void SetViewport(const glm::vec2 &viewportSize); + void SetViewport(const glm::vec2 &newViewportSize); Error ActivateShader(Shader &shader); @@ -57,11 +54,6 @@ namespace DT bool GetFreePointLightSpot(unsigned int *spot); void UnoccupyPointLightSpot(unsigned int spot); - unsigned int GetRenderFBO() - { - return FBO; - } - void SetRenderFrameBuffer(bool flag) { renderFrameBuffer = flag; @@ -75,17 +67,27 @@ namespace DT bindedFBO = fbo; } + glm::vec2 GetViewportSize() + { + return viewportSize; + } + + BaseCamera *GetActiveRenderCamera() + { + return activeRenderCamera; + } + static void FramebufferSizeCallback(GLFWwindow *window, int width, int height); private: - glm::vec2 customViewportSize; + glm::vec2 viewportSize; + BaseCamera *activeRenderCamera; unsigned int bindedFBO = 0; bool renderFrameBuffer = true; - unsigned int FBO, RBO, renderTexture, quadVAO, quadVBO; + unsigned int quadVAO, quadVBO; - std::shared_ptr camera; std::array occupiedDirectionalLights = {false}; std::array occupiedPointLights = {false}; Window *window; diff --git a/Engine/Utils/imgui.cpp b/Engine/Utils/imgui.cpp index fe581541..8bec65e0 100644 --- a/Engine/Utils/imgui.cpp +++ b/Engine/Utils/imgui.cpp @@ -22,9 +22,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#pragma once - -#include #include void ImGui::Vec3(const std::string &label, glm::vec3 &vec3) diff --git a/Runtime/Main.cpp b/Runtime/Main.cpp index 96cccf64..01a1baa5 100644 --- a/Runtime/Main.cpp +++ b/Runtime/Main.cpp @@ -22,6 +22,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +// #define DT_EXPORT + #include #include #include @@ -61,7 +63,7 @@ class FreeLookCamera : public Component PROFILE(); transform = scene->Require(entity).Fatal("FreeLookCamera::Init()"); - camera = scene->Require(entity).Fatal("FreeLookCamera::Init()"); + camera = scene->Require(entity, ctx).Fatal("FreeLookCamera::Init()"); window = ctx.GetService().Fatal("FreeLookCamera::Init()"); input = ctx.GetService().Fatal("FreeLookCamera::Init()"); @@ -211,23 +213,22 @@ int main(int argc, char* argv[]) sceneManager.activeScene.Require(nyan, "Nyan").Fatal("main()"); sceneManager.activeScene.Require(nyan).Fatal("main()")->translation = glm::vec3(1.f, 0.f, 0.f); sceneManager.activeScene.Require(nyan, &context, projectPath / "User" / "Textures" / "nyan.png").Fatal("main()"); - // sceneManager.activeScene.Require(nyan, 'y').Fatal("main()"); + sceneManager.activeScene.Require(nyan, 'y').Fatal("main()"); Entity logo2 = sceneManager.activeScene.CreateEntity(); sceneManager.activeScene.Require(logo2, "Logo 2").Fatal("main()"); sceneManager.activeScene.Require(logo2).Fatal("main()")->translation = glm::vec3(2.f, 0.f, 0.f); sceneManager.activeScene.Require(logo2, &context, projectPath / "User" / "Textures" / "logo.png").Fatal("main()"); - // sceneManager.activeScene.Require(logo2, 'z').Fatal("main()"); + sceneManager.activeScene.Require(logo2, 'z').Fatal("main()"); Entity camera = sceneManager.activeScene.CreateEntity(); - sceneManager.activeScene.Require(camera, "Camera").Fatal("main()"); - sceneManager.activeScene.Require(camera).Fatal("main()"); + sceneManager.activeScene.Require(camera, "MainCamera").Fatal("main()"); + sceneManager.activeScene.Require(camera, context).Fatal("main()"); sceneManager.activeScene.Require(camera).Fatal("main()")->translation = glm::vec3(0.f, 0.f, -3.f); sceneManager.activeScene.Get(camera).Fatal("main()")->LookAt(glm::vec3(1.f, 0.f, 0.f)); sceneManager.activeScene.Require(camera).Fatal("main()"); sceneManager.Init(context); - renderer.FetchCamera(context); // Editor #ifndef DT_EXPORT @@ -239,7 +240,7 @@ int main(int argc, char* argv[]) GameViewPanel gameView; InspectorPanel inspector; WorldOutlinerPanel worldOutliner; - WorldViewPanel worldView; + WorldViewPanel worldView(context); editor.AttachPanel(&exportPanel).Fatal("main()"); editor.AttachPanel(&fileSystem).Fatal("main()"); @@ -272,10 +273,16 @@ int main(int argc, char* argv[]) editor.NewFrame(); editor.Tick(context, deltaTime); #endif - renderer.BeginScene(); + renderer.BeginScene(Camera::GetActiveCamera().get()); +#ifdef DT_EXPORT sceneManager.Tick(context, deltaTime); +#endif renderer.EndScene(); #ifndef DT_EXPORT + renderer.BeginScene(&worldView.editorCamera); + worldView.editorCamera.Recalculate(&window); + sceneManager.EditorTick(context, deltaTime); + renderer.EndScene(); editor.EndFrame(); #endif window.SwapBuffers();