From f6ccb823c72b1c420e865dc70465c7350c433f16 Mon Sep 17 00:00:00 2001 From: Atdunbg <979541498@qq.com> Date: Fri, 16 May 2025 15:55:00 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=AA=97=E5=8F=A3=E8=87=AA?= =?UTF-8?q?=E7=94=B1=E7=BC=A9=E6=94=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Hazel/src/Hazel/Application.cpp | 44 +++- Hazel/src/Hazel/Application.h | 2 + Hazel/src/Hazel/ImGui/ImGuiLayer.cpp | 1 - Hazel/src/Hazel/Log.cpp | 9 +- .../Hazel/OrthographicCameraController.cpp | 82 +++++++ .../src/Hazel/OrthographicCameraController.h | 49 ++++ .../src/Hazel/Renderer/OrthographicCamera.cpp | 6 + Hazel/src/Hazel/Renderer/OrthographicCamera.h | 2 +- Hazel/src/Hazel/Renderer/Renderer.cpp | 6 +- Hazel/src/Hazel/Renderer/Renderer.h | 1 + Hazel/src/Hazel/Renderer/RendererAPI.h | 1 + Hazel/src/Hazel/Renderer/RendererCommand.h | 15 +- Hazel/src/Hazel/Renderer/Shader.cpp | 60 ++++- Hazel/src/Hazel/Renderer/Shader.h | 23 +- Hazel/src/Hazel/Window.h | 2 + .../src/Platform/OpenGL/OpenGLRendererAPI.cpp | 7 +- Hazel/src/Platform/OpenGL/OpenGLRendererAPI.h | 1 + Hazel/src/Platform/OpenGL/OpenGLShader.cpp | 223 +++++++++++++----- Hazel/src/Platform/OpenGL/OpenGLShader.h | 12 +- Hazel/src/Platform/Windows/WindowsWindow.cpp | 14 +- Hazel/src/Platform/Windows/WindowsWindow.h | 3 + Sandbox/assets/shaders/Texture.glsl | 38 +++ Sandbox/src/SandboxApp.cpp | 133 +++-------- 23 files changed, 549 insertions(+), 185 deletions(-) create mode 100644 Hazel/src/Hazel/OrthographicCameraController.cpp create mode 100644 Hazel/src/Hazel/OrthographicCameraController.h create mode 100644 Sandbox/assets/shaders/Texture.glsl diff --git a/Hazel/src/Hazel/Application.cpp b/Hazel/src/Hazel/Application.cpp index b6fad78..cef142c 100644 --- a/Hazel/src/Hazel/Application.cpp +++ b/Hazel/src/Hazel/Application.cpp @@ -24,6 +24,7 @@ namespace Hazel { m_Window = std::unique_ptr(Window::Create()); m_Window->SetEventCallback(std::bind(&Application::OnEvent, this, std::placeholders::_1)); + m_Window->SetWindowResizeEventCallback(std::bind(&Application::OnWindowResize, this, std::placeholders::_1)); Renderer::Init(); @@ -44,21 +45,21 @@ namespace Hazel { m_lastFrameTime = currentTime; - for (Layer* layer : m_layerStack) + if (!m_Minimized) { - layer->OnUpdate(timestep); + for (Layer* layer : m_layerStack) + { + layer->OnUpdate(timestep); + } + + m_imguiLayer->Begin(); + for (Layer* layer : m_layerStack) + { + layer->OnImGuiRender(); + } + m_imguiLayer->End(); } - m_imguiLayer->Begin(); - for (Layer* layer : m_layerStack) - { - layer->OnImGuiRender(); - } - m_imguiLayer->End(); - - - // HZ_CORE_INFO("{}", Input::IsKeyPressed(HZ_KEY_0)); - m_Window->OnUpdate(); } } @@ -71,12 +72,29 @@ namespace Hazel { (*--it)->OnEvent(e); } - if (e.type == SDL_EVENT_QUIT) + + switch (e.type) { + case SDL_EVENT_QUIT: m_Running = false; + break; + case SDL_EVENT_WINDOW_MINIMIZED: + m_Minimized = true; + break; + case SDL_EVENT_WINDOW_RESTORED: + m_Minimized = false; + break; + default: + break; } } + void Application::OnWindowResize(SDL_Event& e) + { + m_Minimized = false; + HZ_CORE_INFO("Resized window:({0}, {1})", m_Window->GetWidth(), m_Window->GetHeight()); + Renderer::OnWindowResize(m_Window->GetWidth(), m_Window->GetHeight()); + } void Application::PushLayer(Layer* layer) { m_layerStack.PushLayer(layer); diff --git a/Hazel/src/Hazel/Application.h b/Hazel/src/Hazel/Application.h index 0ed01a4..7c815bd 100644 --- a/Hazel/src/Hazel/Application.h +++ b/Hazel/src/Hazel/Application.h @@ -19,6 +19,7 @@ namespace Hazel { void Run(); void OnEvent(SDL_Event& e); + void OnWindowResize(SDL_Event& e); void PushLayer(Layer* layer); void PushOverlay(Layer* layer); inline Window& GetWindow() { return *m_Window; } @@ -34,6 +35,7 @@ namespace Hazel { TimeStep m_TimeStep; float m_lastFrameTime = 0.0f; + bool m_Minimized = false; private: static Application* s_Instance; }; diff --git a/Hazel/src/Hazel/ImGui/ImGuiLayer.cpp b/Hazel/src/Hazel/ImGui/ImGuiLayer.cpp index 2e1059e..4dc85af 100644 --- a/Hazel/src/Hazel/ImGui/ImGuiLayer.cpp +++ b/Hazel/src/Hazel/ImGui/ImGuiLayer.cpp @@ -63,7 +63,6 @@ namespace Hazel void ImGuiLayer::OnImGuiRender() { - ImGui::ShowDemoWindow(); } void ImGuiLayer::Begin() diff --git a/Hazel/src/Hazel/Log.cpp b/Hazel/src/Hazel/Log.cpp index 43056b8..a12eede 100644 --- a/Hazel/src/Hazel/Log.cpp +++ b/Hazel/src/Hazel/Log.cpp @@ -2,6 +2,11 @@ #include +#ifdef _DEBUG + #define LOG_LEVEL spdlog::level::trace +#else + #define LOG_LEVEL spdlog::level::debug +#endif namespace Hazel { @@ -11,10 +16,10 @@ namespace Hazel { void Log::init() { spdlog::set_pattern("%^[%T] %n: %v%$"); s_CoreLogger = spdlog::stdout_color_mt("Hazel"); - s_CoreLogger->set_level(spdlog::level::trace); + s_CoreLogger->set_level(LOG_LEVEL); s_ClientLogger = spdlog::stdout_color_mt("App"); - s_ClientLogger->set_level(spdlog::level::trace); + s_ClientLogger->set_level(LOG_LEVEL); } } diff --git a/Hazel/src/Hazel/OrthographicCameraController.cpp b/Hazel/src/Hazel/OrthographicCameraController.cpp new file mode 100644 index 0000000..8dd55c9 --- /dev/null +++ b/Hazel/src/Hazel/OrthographicCameraController.cpp @@ -0,0 +1,82 @@ +// +// Created by sfd on 25-5-12. +// + +#include "OrthographicCameraController.h" + + +namespace Hazel +{ + OrthographicCameraController::OrthographicCameraController(float aspectRatio, bool isRotation) : m_AspectRatio(aspectRatio), m_Camera(-m_AspectRatio * m_ZoomLevel, m_AspectRatio * m_ZoomLevel, -m_ZoomLevel, m_ZoomLevel), m_isRotation(isRotation) + { + } + + void OrthographicCameraController::OnUpdate(TimeStep ts) + { + const bool* state = SDL_GetKeyboardState(NULL); + float time = ts; + if (state[SDL_SCANCODE_A]) + { + m_CameraPosition.x -= m_CameraTranslationSpeed * time; + } + else if (state[SDL_SCANCODE_D]) + { + m_CameraPosition.x += m_CameraTranslationSpeed * time; + } + if (state[SDL_SCANCODE_W]) + { + m_CameraPosition.y += m_CameraTranslationSpeed * time; + } + else if (state[SDL_SCANCODE_S]) + { + m_CameraPosition.y -= m_CameraTranslationSpeed * time; + } + if (m_isRotation) + { + if (state[SDL_SCANCODE_Q]) + { + m_CameraRotation += m_CameraRotationSpeed * time; + } + else if (state[SDL_SCANCODE_E]) + { + m_CameraRotation -= m_CameraRotationSpeed * time; + } + + m_Camera.SetRotation(m_CameraRotation); + } + + + m_Camera.SetPosition(m_CameraPosition); + + m_CameraTranslationSpeed = m_ZoomLevel; + } + + void OrthographicCameraController::OnEvent(SDL_Event& e) + { + OnMouseScrolled(e); + OnWindowResized(e); + } + + bool OrthographicCameraController::OnMouseScrolled(SDL_Event& e) + { + if (e.type == SDL_EVENT_MOUSE_WHEEL) + { + m_ZoomLevel += e.wheel.y * 0.25f; + m_ZoomLevel = std::max(m_ZoomLevel, 0.25f); + m_Camera.SetProjection(-m_AspectRatio * m_ZoomLevel, m_AspectRatio * m_ZoomLevel, -m_ZoomLevel, m_ZoomLevel); + return false; + } + return true; + } + + bool OrthographicCameraController::OnWindowResized(SDL_Event& e) + { + if (e.type == SDL_EVENT_WINDOW_RESIZED) + { + m_AspectRatio = static_cast(e.window.data1) / static_cast(e.window.data2); + m_Camera.SetProjection(-m_AspectRatio * m_ZoomLevel, m_AspectRatio * m_ZoomLevel, -m_ZoomLevel, m_ZoomLevel); + return false; + } + return true; + } +} diff --git a/Hazel/src/Hazel/OrthographicCameraController.h b/Hazel/src/Hazel/OrthographicCameraController.h new file mode 100644 index 0000000..826a225 --- /dev/null +++ b/Hazel/src/Hazel/OrthographicCameraController.h @@ -0,0 +1,49 @@ +// +// Created by sfd on 25-5-12. +// + +#ifndef ORTHOGRAPHICCAMERACONTROLLER_H +#define ORTHOGRAPHICCAMERACONTROLLER_H + +#include + +#include "Core.h" +#include "Core/TimeStep.h" +#include "Renderer/OrthographicCamera.h" + + + +namespace Hazel +{ + class HAZEL_API OrthographicCameraController + { + public: + OrthographicCameraController(float aspectRatio, bool isRotation = false); + void SetProjection(float left, float right, float bottom, float top); + + + void OnUpdate(TimeStep ts); + void OnEvent(SDL_Event& e); + + + OrthographicCamera& GetCamera() {return m_Camera;} + const OrthographicCamera& GetCamera() const {return m_Camera;} + + private: + bool OnMouseScrolled(SDL_Event& e); + bool OnWindowResized(SDL_Event& e); + + private: + float m_AspectRatio; + float m_ZoomLevel = 1.0f; + OrthographicCamera m_Camera; + bool m_isRotation; + + glm::vec3 m_CameraPosition = { 0.0f, 0.0f, 0.0f }; + float m_CameraRotation = 0.0f; + float m_CameraTranslationSpeed = 20.0f, m_CameraRotationSpeed = 30.0f; + }; +} + + +#endif //ORTHOGRAPHICCAMERACONTROLLER_H diff --git a/Hazel/src/Hazel/Renderer/OrthographicCamera.cpp b/Hazel/src/Hazel/Renderer/OrthographicCamera.cpp index 678d079..f00ccaa 100644 --- a/Hazel/src/Hazel/Renderer/OrthographicCamera.cpp +++ b/Hazel/src/Hazel/Renderer/OrthographicCamera.cpp @@ -16,6 +16,12 @@ namespace Hazel } + void OrthographicCamera::SetProjection(float left, float right, float bottom, float top) + { + m_ProjectionMatrix = glm::ortho(left, right, bottom, top, -1.0f, 1.0f); + m_ViewProjectionMatrix = m_ProjectionMatrix * m_ViewMatrix; + } + void OrthographicCamera::RecalculateViewMatrix() { glm::mat4 transform = glm::translate(glm::mat4(1.0f), m_Position) * glm::rotate(glm::mat4(1.0f), glm::radians(m_Rotation), glm::vec3(0.0f, 0.0f, 1.0f)); diff --git a/Hazel/src/Hazel/Renderer/OrthographicCamera.h b/Hazel/src/Hazel/Renderer/OrthographicCamera.h index e63374d..ca9ae50 100644 --- a/Hazel/src/Hazel/Renderer/OrthographicCamera.h +++ b/Hazel/src/Hazel/Renderer/OrthographicCamera.h @@ -14,7 +14,7 @@ namespace Hazel { public: OrthographicCamera(float left, float right, float bottom, float top); - + void SetProjection(float left, float right, float bottom, float top); const glm::vec3& GetPosition() const { return m_Position; } diff --git a/Hazel/src/Hazel/Renderer/Renderer.cpp b/Hazel/src/Hazel/Renderer/Renderer.cpp index 012bba6..4d674a5 100644 --- a/Hazel/src/Hazel/Renderer/Renderer.cpp +++ b/Hazel/src/Hazel/Renderer/Renderer.cpp @@ -4,7 +4,6 @@ #include "Renderer.h" -#include #include "Platform/OpenGL/OpenGLShader.h" #include "RendererCommand.h" @@ -19,6 +18,11 @@ namespace Hazel RendererCommand::Init(); } + void Renderer::OnWindowResize(uint32_t width, uint32_t height) + { + RendererCommand::SetViewPort(0, 0, width, height); + } + void Renderer::BeginScene(OrthographicCamera& camera) { m_SceneData->ViewProjectionMatrix = camera.GetViewProjectionMatrix(); diff --git a/Hazel/src/Hazel/Renderer/Renderer.h b/Hazel/src/Hazel/Renderer/Renderer.h index 855ebed..d2b9006 100644 --- a/Hazel/src/Hazel/Renderer/Renderer.h +++ b/Hazel/src/Hazel/Renderer/Renderer.h @@ -19,6 +19,7 @@ namespace Hazel { public: static void Init(); + static void OnWindowResize(uint32_t width, uint32_t height); static void BeginScene(OrthographicCamera& camera); static void EndScene(); diff --git a/Hazel/src/Hazel/Renderer/RendererAPI.h b/Hazel/src/Hazel/Renderer/RendererAPI.h index 029a151..b7d1be0 100644 --- a/Hazel/src/Hazel/Renderer/RendererAPI.h +++ b/Hazel/src/Hazel/Renderer/RendererAPI.h @@ -25,6 +25,7 @@ namespace Hazel public: virtual void Init() = 0; virtual void SetClearColor(const glm::vec4& color) = 0; + virtual void SetViewPort(uint32_t x, uint32_t y, uint32_t width, uint32_t height) = 0; virtual void Clear() = 0; virtual void DrawIndexed(const std::shared_ptr& vertexArray) = 0; diff --git a/Hazel/src/Hazel/Renderer/RendererCommand.h b/Hazel/src/Hazel/Renderer/RendererCommand.h index 9ba86cf..bbac879 100644 --- a/Hazel/src/Hazel/Renderer/RendererCommand.h +++ b/Hazel/src/Hazel/Renderer/RendererCommand.h @@ -20,14 +20,23 @@ namespace Hazel { { s_RendererAPI->SetClearColor(color); } + + inline static void SetViewPort(uint32_t x, uint32_t y, uint32_t width, uint32_t height) + { + s_RendererAPI->SetViewPort(x, y, width, height); + } + inline static void Clear() { s_RendererAPI->Clear(); } - inline static void DrawIndexed(const std::shared_ptr& vertexArray) { - s_RendererAPI->DrawIndexed(vertexArray); - } + inline static void DrawIndexed(const std::shared_ptr& vertexArray) + { + s_RendererAPI->DrawIndexed(vertexArray); + } + + private: static RendererAPI* s_RendererAPI; diff --git a/Hazel/src/Hazel/Renderer/Shader.cpp b/Hazel/src/Hazel/Renderer/Shader.cpp index 14b6390..617629e 100644 --- a/Hazel/src/Hazel/Renderer/Shader.cpp +++ b/Hazel/src/Hazel/Renderer/Shader.cpp @@ -9,16 +9,72 @@ namespace Hazel { - Shader* Shader::Create(const std::string& vertexSrc, const std::string& fragmentSrc) + Ref Shader::Create(const std::string& name, const std::string& vertexSrc, const std::string& fragmentSrc) { switch (Renderer::GetAPI()) { case RendererAPI::API::NONE: return nullptr; - case RendererAPI::API::OPENGL: return new OpenGLShader(vertexSrc, fragmentSrc); + case RendererAPI::API::OPENGL: return std::make_shared(name, vertexSrc, fragmentSrc); } HZ_CORE_ERROR("Unknown RendererAPI"); return nullptr; } + Ref Shader::Create(const std::string& filepath) + { + switch (Renderer::GetAPI()) + { + case RendererAPI::API::NONE: return nullptr; + case RendererAPI::API::OPENGL: return std::make_shared(filepath); + } + + HZ_CORE_ERROR("Unknown RendererAPI"); + return nullptr; + } + + void ShaderLibrary::Add(const std::string& name, const Ref& shader) + { + if (Exists(name)) + { + HZ_CORE_ERROR("Shader already exists"); + return; + } + m_Shaders[name] = shader; + } + + void ShaderLibrary::Add(const Ref& shader) + { + auto& name = shader->GetName(); + Add(name, shader); + } + + Ref ShaderLibrary::Load(const std::string& filepath) + { + auto shader = std::make_shared(filepath); + Add(shader); + return shader; + } + + Ref ShaderLibrary::Load(const std::string& name, const std::string& filepath) + { + auto shader = std::make_shared(filepath); + Add(name, shader); + return shader; + } + + Ref ShaderLibrary::Get(const std::string& name) + { + if (!Exists(name)) + { + HZ_CORE_ERROR("Shader not found"); + return nullptr; + } + return m_Shaders[name]; + } + + bool ShaderLibrary::Exists(const std::string& name) const + { + return m_Shaders.contains(name); + } } diff --git a/Hazel/src/Hazel/Renderer/Shader.h b/Hazel/src/Hazel/Renderer/Shader.h index 546e717..f4ad9dc 100644 --- a/Hazel/src/Hazel/Renderer/Shader.h +++ b/Hazel/src/Hazel/Renderer/Shader.h @@ -5,6 +5,7 @@ #ifndef SHADER_H #define SHADER_H #include +#include #include @@ -18,10 +19,30 @@ namespace Hazel virtual void Bind() const = 0; virtual void Unbind() const = 0; - static Shader* Create(const std::string& vertexSrc, const std::string& fragmentSrc); + virtual const std::string& GetName() const = 0; + + static Ref Create(const std::string& name, const std::string& vertexSrc, const std::string& fragmentSrc); + static Ref Create(const std::string& filepath); private: uint32_t m_RendererID; }; + + class HAZEL_API ShaderLibrary + { + public: + void Add(const Ref& shader); + void Add(const std::string& name, const Ref& shader); + + Ref Load(const std::string& filepath); // example: texture.glsl + Ref Load(const std::string& name, const std::string& filepath); + + Ref Get(const std::string& name); + + bool Exists(const std::string& name) const; + private: + std::unordered_map> m_Shaders; + }; + } diff --git a/Hazel/src/Hazel/Window.h b/Hazel/src/Hazel/Window.h index c150806..412e0ca 100644 --- a/Hazel/src/Hazel/Window.h +++ b/Hazel/src/Hazel/Window.h @@ -28,6 +28,7 @@ namespace Hazel { public: using EventCallbackFn = std::function; + using WindowsResizeCallbackFn = std::function; virtual ~Window() = default; @@ -38,6 +39,7 @@ namespace Hazel // Window attributes virtual void SetEventCallback(const EventCallbackFn& callback) = 0; + virtual void SetWindowResizeEventCallback(const WindowsResizeCallbackFn& callback) = 0; virtual void SetVSync(bool enabled) = 0; virtual bool IsVSync() const = 0; diff --git a/Hazel/src/Platform/OpenGL/OpenGLRendererAPI.cpp b/Hazel/src/Platform/OpenGL/OpenGLRendererAPI.cpp index 392d6cc..3f891ec 100644 --- a/Hazel/src/Platform/OpenGL/OpenGLRendererAPI.cpp +++ b/Hazel/src/Platform/OpenGL/OpenGLRendererAPI.cpp @@ -11,7 +11,6 @@ namespace Hazel void OpenGLRendererAPI::Init() { glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } @@ -20,6 +19,12 @@ namespace Hazel glClearColor(color.x, color.y, color.z, color.w); } + void OpenGLRendererAPI::SetViewPort(uint32_t x, uint32_t y, uint32_t width, uint32_t height) + { + HZ_CORE_INFO("Setting viewport to ({0}, {1}), ({2}, {3})", x, y, width, height); + glViewport(x, y, width, height); + } + void OpenGLRendererAPI::Clear() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); diff --git a/Hazel/src/Platform/OpenGL/OpenGLRendererAPI.h b/Hazel/src/Platform/OpenGL/OpenGLRendererAPI.h index b828116..cecac13 100644 --- a/Hazel/src/Platform/OpenGL/OpenGLRendererAPI.h +++ b/Hazel/src/Platform/OpenGL/OpenGLRendererAPI.h @@ -14,6 +14,7 @@ namespace Hazel public: virtual void Init() override; virtual void SetClearColor(const glm::vec4& color) override; + virtual void SetViewPort(uint32_t x, uint32_t y, uint32_t width, uint32_t height) override; virtual void Clear() override; virtual void DrawIndexed(const std::shared_ptr& vertexArray) override; }; diff --git a/Hazel/src/Platform/OpenGL/OpenGLShader.cpp b/Hazel/src/Platform/OpenGL/OpenGLShader.cpp index 629101c..1455b93 100644 --- a/Hazel/src/Platform/OpenGL/OpenGLShader.cpp +++ b/Hazel/src/Platform/OpenGL/OpenGLShader.cpp @@ -3,81 +3,55 @@ // #include "OpenGLShader.h" + +#include #include -#include +#include #include #include "glm/gtc/type_ptr.hpp" +#include "spdlog/fmt/bundled/compile.h" namespace Hazel { - OpenGLShader::OpenGLShader(const std::string& vertexSrc, const std::string& fragmentSrc) + static GLenum ShaderTypeFromString(const std::string& type) { - GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); - - const char* vertexShaderSrc = vertexSrc.c_str(); - glShaderSource(vertexShader, 1, &vertexShaderSrc, 0); - - glCompileShader(vertexShader); - - GLint compileSuccess = 0; - glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &compileSuccess); - if (compileSuccess == GL_FALSE) - { - int length = 0; - glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &length); - - std::vector infoLog(length); - glGetShaderInfoLog(vertexShader, length, &length, &infoLog[0]); - - glDeleteShader(vertexShader); - HZ_CORE_ERROR("Vertex shader compilation failed!"); - HZ_CORE_ERROR("{0}", infoLog.data()); - return; - } + if (type == "vertex") return GL_VERTEX_SHADER; + if (type == "fragment" || type == "pixel") return GL_FRAGMENT_SHADER; + if (type == "geometry") return GL_GEOMETRY_SHADER; + if (type == "compute") return GL_COMPUTE_SHADER; + HZ_CORE_ERROR("Unknown Shader Type"); + return 0; + } - GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); - const char* fragmentShaderSrc = fragmentSrc.c_str(); - glShaderSource(fragmentShader, 1, &fragmentShaderSrc, 0); - glCompileShader(fragmentShader); - glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &compileSuccess); - if (compileSuccess == GL_FALSE) - { - int length = 0; - glGetShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &length); - std::vector infoLog(length); - glGetShaderInfoLog(fragmentShader, length, &length, &infoLog[0]); - glDeleteShader(fragmentShader); + OpenGLShader::OpenGLShader(const std::string& filepath) + { + std::string shaderSrc = ReadFile(filepath); + auto shaderSources = PreProcess(shaderSrc); + Compile(shaderSources); - HZ_CORE_ERROR("[{0}:{1}]: Fragment shader compilation failed!", __FILE__, __LINE__); - HZ_CORE_ERROR("{0}", infoLog.data()); + // example: /assets/shaders/Texture.glsl + auto lastSlash = filepath.find_last_of("\\/"); + auto lastDot = filepath.find_last_of("."); + m_Name = filepath.substr(lastSlash + 1, lastDot - lastSlash - 1); - return; - } - m_RendererID = glCreateProgram(); - glAttachShader(m_RendererID, vertexShader); - glAttachShader(m_RendererID, fragmentShader); - glLinkProgram(m_RendererID); - glGetProgramiv(m_RendererID, GL_LINK_STATUS, &compileSuccess); - if (compileSuccess == GL_FALSE) - { - int length = 0; - glGetProgramiv(m_RendererID, GL_INFO_LOG_LENGTH, &length); - std::vector infoLog(length); - glGetProgramInfoLog(m_RendererID, length, &length, &infoLog[0]); - glDeleteShader(vertexShader); - glDeleteShader(fragmentShader); - glDeleteProgram(m_RendererID); + /* + auto lastSlash = filepath.find_last_of("\\/"); + lastSlash = lastSlash == std::string::npos ? 0 : lastSlash + 1; + auto lastDot = filepath.rfind("."); + auto count = lastDot == std::string::npos ? filepath.size() - lastSlash : lastDot - lastSlash; + m_Name = filepath.substr(lastSlash, count); + */ + } - HZ_CORE_ERROR("shaderProgram link failed!"); - HZ_CORE_ERROR("{0}", infoLog.data()); - return; - } - - glDeleteShader(vertexShader); - glDeleteShader(fragmentShader); + OpenGLShader::OpenGLShader(const std::string& name, const std::string& vertexSrc, const std::string& fragmentSrc): m_Name(name) + { + std::unordered_map shaderSources; + shaderSources[GL_VERTEX_SHADER] = vertexSrc; + shaderSources[GL_FRAGMENT_SHADER] = fragmentSrc; + Compile(shaderSources); } @@ -114,6 +88,133 @@ namespace Hazel glUniformMatrix4fv(location, 1, GL_FALSE, glm::value_ptr(matrix)); } + std::string OpenGLShader::ReadFile(const std::string& filepath) + { + std::ifstream in(filepath, std::ios::in, std::ios::binary); // window platform api + if (!in.is_open()) + { + HZ_CORE_ERROR("Failed to open shader file {0}", filepath); + return ""; + } + + std::string result; + in.seekg(0, std::ios::end); + result.resize(in.tellg()); + in.seekg(0, std::ios::beg); + in.read(&result[0], result.size()); + in.close(); + + return result; + } + + std::unordered_map OpenGLShader::PreProcess(const std::string& source) + { + std::unordered_map shaderSource; + const char* typeToken = "#type"; + size_t typeTokenLength = strlen(typeToken); + size_t pos = source.find(typeToken, 0); + + while (pos != std::string::npos) + { + size_t eol = source.find_first_of("\r\n", pos); + if (eol == std::string::npos) + { + HZ_CORE_ERROR("[{0}:{1}]: Failed to parse shader source", __FILE__, __LINE__); + return shaderSource; + } + size_t start = pos + typeTokenLength + 1; + std::string type = source.substr(start, eol - start); + if (!ShaderTypeFromString(type)) + { + HZ_CORE_ERROR("[{0}:{1}]: Unsupported shader type", __FILE__, __LINE__); + return shaderSource; + } + + size_t nextLinePos = source.find_first_of("\r\n", eol); + pos = source.find(typeToken, nextLinePos); + shaderSource[ShaderTypeFromString(type)] = source.substr(nextLinePos, pos - (nextLinePos == std::string::npos ? source.size() - 1 : nextLinePos)); + + } + return shaderSource; + + } + + void OpenGLShader::Compile(std::unordered_map& shaderSource) + { + + GLuint program = glCreateProgram(); + // std::vector glShaderIDs; + // glShaderIDs.reserve(shaderSource.size()); + + if (shaderSource.size() > 2) + { + HZ_CORE_ERROR("Only support 2 shaders Now!"); + } + std::array glShaderIDs; + int glShaderIDIndex = 0; + for (auto& shaderSource : shaderSource) + { + GLenum type = shaderSource.first; + const std::string source = shaderSource.second; + + GLuint shader = glCreateShader(type); + + const char* shaderSrc = source.c_str(); + glShaderSource(shader, 1, &shaderSrc, 0); + + glCompileShader(shader); + + GLint compileSuccess = 0; + glGetShaderiv(shader, GL_COMPILE_STATUS, &compileSuccess); + if (compileSuccess == GL_FALSE) + { + int length = 0; + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length); + + std::vector infoLog(length); + glGetShaderInfoLog(shader, length, &length, &infoLog[0]); + + glDeleteShader(shader); + HZ_CORE_ERROR("shader compilation failed!"); + HZ_CORE_ERROR("{0}", infoLog.data()); + return; + } + + glAttachShader(program, shader); + glShaderIDs[glShaderIDIndex++] = shader; + } + + + + glLinkProgram(program); + + GLint compileSuccess = 0; + glGetProgramiv(program, GL_LINK_STATUS, &compileSuccess); + if (compileSuccess == GL_FALSE) + { + int length = 0; + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length); + std::vector infoLog(length); + glGetProgramInfoLog(program, length, &length, &infoLog[0]); + for (const auto id : glShaderIDs) + { + glDeleteShader(id); + } + + HZ_CORE_ERROR("shaderProgram link failed!"); + HZ_CORE_ERROR("{0}", infoLog.data()); + return; + } + + for (const auto id : glShaderIDs) + { + glDetachShader(program, id); + glDeleteShader(id); + } + + m_RendererID = program; + } + void OpenGLShader::UploadUniformInt(const char* str, const int value) const { const GLint location = glGetUniformLocation(m_RendererID, str); diff --git a/Hazel/src/Platform/OpenGL/OpenGLShader.h b/Hazel/src/Platform/OpenGL/OpenGLShader.h index dbb8305..3fc24bb 100644 --- a/Hazel/src/Platform/OpenGL/OpenGLShader.h +++ b/Hazel/src/Platform/OpenGL/OpenGLShader.h @@ -8,6 +8,7 @@ #include "glm/fwd.hpp" #include "glm/vec4.hpp" +#include namespace Hazel @@ -15,20 +16,29 @@ namespace Hazel class HAZEL_API OpenGLShader : public Shader { public: - OpenGLShader(const std::string& vertexSrc, const std::string& fragmentSrc); + OpenGLShader(const std::string& filepath); + OpenGLShader(const std::string& name, const std::string& vertexSrc, const std::string& fragmentSrc); virtual ~OpenGLShader() override; void Bind() const override; void Unbind() const override; + virtual const std::string& GetName() const override {return m_Name;} + void UploadUniformInt(const char* str, int value) const; void UploadUniformFloat3(const std::string& name, const glm::vec3& value) const; void UploadUniformFloat4(const std::string& name, const glm::vec4& value) const; void UploadUniformMat4(const std::string& name, const glm::mat4& matrix) const; + private: + std::string ReadFile(const std::string& filepath); + std::unordered_map PreProcess(const std::string& source); + void Compile(std::unordered_map& shaderSource); + private: uint32_t m_RendererID; + std::string m_Name; }; } diff --git a/Hazel/src/Platform/Windows/WindowsWindow.cpp b/Hazel/src/Platform/Windows/WindowsWindow.cpp index 97e6975..5e9ae1e 100644 --- a/Hazel/src/Platform/Windows/WindowsWindow.cpp +++ b/Hazel/src/Platform/Windows/WindowsWindow.cpp @@ -9,6 +9,8 @@ #include #include +#include "glm/gtc/constants.hpp" + namespace Hazel { @@ -65,7 +67,7 @@ namespace Hazel HZ_CORE_INFO("Initing GLAD..."); - if (!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress)) + if (!gladLoadGLLoader(reinterpret_cast(SDL_GL_GetProcAddress))) { HZ_CORE_ERROR("Could not initialize GLAD context!"); } @@ -87,6 +89,16 @@ namespace Hazel while (SDL_PollEvent(&event)) { + if (event.type == SDL_EVENT_WINDOW_RESIZED) + { + m_Data.width = event.window.data1; + m_Data.height = event.window.data2; + + if (this->OnWindowResize != nullptr) + { + OnWindowResize(event); + } + } if (m_Data.eventCallback != nullptr) { m_Data.eventCallback(event); diff --git a/Hazel/src/Platform/Windows/WindowsWindow.h b/Hazel/src/Platform/Windows/WindowsWindow.h index bd8f91c..7fdbd6f 100644 --- a/Hazel/src/Platform/Windows/WindowsWindow.h +++ b/Hazel/src/Platform/Windows/WindowsWindow.h @@ -13,6 +13,7 @@ namespace Hazel { + class GraphicsContext; class WindowsWindow : public Window @@ -29,6 +30,7 @@ namespace Hazel // Window attributes inline void SetEventCallback(const EventCallbackFn& callback) override { m_Data.eventCallback = callback; } + inline void SetWindowResizeEventCallback(const WindowsResizeCallbackFn& callback) override {OnWindowResize = callback;} void SetVSync(bool enabled) override; bool IsVSync() const override; @@ -52,6 +54,7 @@ namespace Hazel EventCallbackFn eventCallback; }; + WindowsResizeCallbackFn OnWindowResize; WindowData m_Data; }; } diff --git a/Sandbox/assets/shaders/Texture.glsl b/Sandbox/assets/shaders/Texture.glsl new file mode 100644 index 0000000..19446b2 --- /dev/null +++ b/Sandbox/assets/shaders/Texture.glsl @@ -0,0 +1,38 @@ +#type vertex +#version 460 core + +layout(location = 0) in vec3 a_Position; +layout(location = 1) in vec2 a_TexCoord; + +uniform mat4 u_ViewProjection; +uniform mat4 u_Transform; + +out vec2 v_TexCoord; + +void main() { + v_TexCoord = a_TexCoord; + gl_Position = u_ViewProjection * u_Transform * vec4(a_Position, 1.0f); +} + +#type fragment +#version 460 core + +layout(location = 0) out vec4 color; + +in vec2 v_TexCoord; + +uniform sampler2D u_Texture; + +void main() { + vec4 tmpColor = texture(u_Texture, v_TexCoord); + if(gl_FragCoord.x < 635){ + color = tmpColor; + } + else{ + if(tmpColor.a < 0.1){ + discard; + }else{ + color = vec4(v_TexCoord, 0.0f, 1.0f); + } + } +} diff --git a/Sandbox/src/SandboxApp.cpp b/Sandbox/src/SandboxApp.cpp index 7bd0462..c9022c4 100644 --- a/Sandbox/src/SandboxApp.cpp +++ b/Sandbox/src/SandboxApp.cpp @@ -4,7 +4,7 @@ #define GLM_ENABLE_EXPERIMENTAL -#include +#include #include #include @@ -17,7 +17,7 @@ class ExampleLayer : public Hazel::Layer public: // ExampleLayer() : Layer("ExampleLayer"), m_Camera(-1.0f, 1.0f, -1.0f, 1.0f), m_CameraPosition(0.0f) - ExampleLayer() : Layer("ExampleLayer"), m_Camera(-1.6f, 1.6f, -0.9f, 0.9f), m_CameraPosition(0.0f), m_SquarePosition(glm::vec3(0.0f)) + ExampleLayer() : Layer("ExampleLayer"), m_CameraController(1280.0f / 720.0f), m_SquarePosition(glm::vec3(0.0f)) { // ------------------------------------------------------------test------------------------------------------------------------ // Vertex Array @@ -76,7 +76,7 @@ public: color = vec4(v_Color, 1.0f); } )"; - m_Shader.reset(Hazel::Shader::Create(vertexSrc, fragmentSrc)); + m_Shader = Hazel::Shader::Create("demoShader", vertexSrc, fragmentSrc); m_SquareVA.reset(Hazel::VertexArray::Create()); @@ -103,7 +103,7 @@ public: squareIB.reset(Hazel::IndexBuffer::Create(squareIndice, sizeof(squareIndice) / sizeof(uint32_t))); m_SquareVA->SetIndexBuffer(squareIB); - std::string bluevertexSrc = R"( + std::string coloeVertexSrc = R"( #version 460 core layout(location = 0) in vec3 a_Position; @@ -119,7 +119,7 @@ public: gl_Position = u_ViewProjection * u_Transform * vec4(a_Position, 1.0f); } )"; - std::string bluefragmentSrc = R"( + std::string colorFragmentSrc = R"( #version 460 core layout(location = 0) out vec4 color; @@ -131,168 +131,107 @@ public: color = u_Color; } )"; - m_colorShader.reset(Hazel::Shader::Create(bluevertexSrc, bluefragmentSrc)); + m_colorShader = Hazel::Shader::Create("ColorShader", coloeVertexSrc, colorFragmentSrc); - std::string textureVertexSrc = R"( - #version 460 core - - layout(location = 0) in vec3 a_Position; - layout(location = 1) in vec2 a_TexCoord; - - uniform mat4 u_ViewProjection; - uniform mat4 u_Transform; - - out vec2 v_TexCoord; - - void main() { - v_TexCoord = a_TexCoord; - gl_Position = u_ViewProjection * u_Transform * vec4(a_Position, 1.0f); - } - )"; - std::string textureFragmentSrc = R"( - #version 460 core - - layout(location = 0) out vec4 color; - - in vec2 v_TexCoord; - - uniform sampler2D u_Texture; - - void main() { - vec4 tmpColor = texture(u_Texture, v_TexCoord); - if(gl_FragCoord.x < 635){ - color = tmpColor; - } - else{ - if(tmpColor.a < 0.1){ - discard; - }else{ - color = vec4(v_TexCoord, 0.0f, 1.0f); - } - } - } - )"; - - m_TextureShader.reset(Hazel::Shader::Create(textureVertexSrc, textureFragmentSrc)); + // Texture.Shader + // m_TextureShader = Hazel::Shader::Create("assets/shaders/Texture.glsl"); + auto textureShader = m_ShaderLibrary.Load("assets/shaders/Texture.glsl"); // Texture m_Texture = Hazel::Texture2D::Create("assets/textures/Checkerboard.png"); m_logoTexture = Hazel::Texture2D::Create("assets/textures/iceLogo.png"); - std::dynamic_pointer_cast(m_TextureShader)->Bind(); - std::dynamic_pointer_cast(m_TextureShader)->UploadUniformInt("u_Texture", 0); + std::dynamic_pointer_cast(textureShader)->Bind(); + std::dynamic_pointer_cast(textureShader)->UploadUniformInt("u_Texture", 0); } void OnUpdate(Hazel::TimeStep& ts) override { + m_CameraController.OnUpdate(ts); + // key event { float time = ts; const bool* state = SDL_GetKeyboardState(NULL); - if (state[SDL_SCANCODE_A]) - { - m_CameraPosition.x -= m_CameraSpeed * time; - } - else if (state[SDL_SCANCODE_D]) - { - m_CameraPosition.x += m_CameraSpeed * time; - } - if (state[SDL_SCANCODE_W]) - { - m_CameraPosition.y += m_CameraSpeed * time; - } - else if (state[SDL_SCANCODE_S]) - { - m_CameraPosition.y -= m_CameraSpeed * time; - } - if (state[SDL_SCANCODE_Q]) - { - m_CameraRotation += m_CameraRotationSpeed * time; - } - else if (state[SDL_SCANCODE_E]) - { - m_CameraRotation -= m_CameraRotationSpeed * time; - } if (state[SDL_SCANCODE_I]) { - m_SquarePosition.y += m_CameraSpeed * time; + m_SquarePosition.y += 5 * time; } else if (state[SDL_SCANCODE_K]) { - m_SquarePosition.y -= m_CameraSpeed * time; + m_SquarePosition.y -= 5 * time; } if (state[SDL_SCANCODE_J]) { - m_SquarePosition.x -= m_CameraSpeed * time; + m_SquarePosition.x -= 5 * time; } else if (state[SDL_SCANCODE_L]) { - m_SquarePosition.x += m_CameraSpeed * time; + m_SquarePosition.x += 5 * time; } } - - Hazel::RendererCommand::SetClearColor({0.1f, 0.1f, 0.1f, 1.0f}); + Hazel::RendererCommand::SetClearColor(m_ScreenClearColor); Hazel::RendererCommand::Clear(); - m_Camera.SetPosition(m_CameraPosition); - m_Camera.SetRotation(m_CameraRotation); - - - - Hazel::Renderer::BeginScene(m_Camera); + Hazel::Renderer::BeginScene(m_CameraController.GetCamera()); auto transform = glm::translate(glm::mat4(1.0f), m_SquarePosition); + auto textureShader = m_ShaderLibrary.Get("Texture"); m_Texture->Bind(); - Hazel::Renderer::Submit(m_TextureShader, m_SquareVA, transform); + Hazel::Renderer::Submit(textureShader, m_SquareVA, transform); m_logoTexture->Bind(); - Hazel::Renderer::Submit(m_TextureShader, m_SquareVA); + Hazel::Renderer::Submit(textureShader, m_SquareVA); Hazel::Renderer::EndScene(); } void OnEvent(SDL_Event& event) override { + m_CameraController.OnEvent(event); } void OnImGuiRender() override { + ImGui::ShowDemoWindow(); + + const auto cameraRotation = m_CameraController.GetCamera().GetRotation(); + const auto cameraPosition = m_CameraController.GetCamera().GetPosition(); ImGui::Begin("Hazel Layer"); - ImGui::Text("Rotation: %f", m_CameraRotation); - ImGui::Text("Position: ( %.2f, %.2f, %.2f)", m_CameraPosition.x, m_CameraPosition.y, m_CameraPosition.z); + ImGui::Text("Rotation: %f", cameraRotation); + ImGui::Text("Position: ( %.2f, %.2f, %.2f)", cameraPosition.x, cameraPosition.y, cameraPosition.z); ImGui::Text("frame: %.3f", ImGui::GetIO().Framerate); ImGui::ColorEdit3("Square Color", glm::value_ptr(m_SquareColor)); + ImGui::NewLine(); + ImGui::ColorEdit4("Screen Clear Color", glm::value_ptr(m_ScreenClearColor)); ImGui::End(); } private: + Hazel::ShaderLibrary m_ShaderLibrary; Hazel::Ref m_Shader; Hazel::Ref m_VertexArray; Hazel::Ref m_SquareVA; - Hazel::Ref m_colorShader, m_TextureShader; + Hazel::Ref m_colorShader; Hazel::Ref m_Texture, m_logoTexture; - Hazel::OrthographicCamera m_Camera; - - glm::vec3 m_CameraPosition; - float m_CameraSpeed = 1.0f; - - float m_CameraRotation = 0.0f; - float m_CameraRotationSpeed = 30.f; + Hazel::OrthographicCameraController m_CameraController; glm::vec3 m_SquarePosition; float m_SquareMoveSpeed = 1.0f; glm::vec3 m_SquareColor = {0.2f, 0.3f, 0.8f}; + + glm::vec4 m_ScreenClearColor = {0.1f, 0.1f, 0.1f, 1.0f}; };