增加窗口自由缩放

This commit is contained in:
2025-05-16 15:55:00 +08:00
parent 6b3f6fc521
commit f6ccb823c7
23 changed files with 549 additions and 185 deletions

View File

@ -24,6 +24,7 @@ namespace Hazel {
m_Window = std::unique_ptr<Window>(Window::Create()); m_Window = std::unique_ptr<Window>(Window::Create());
m_Window->SetEventCallback(std::bind(&Application::OnEvent, this, std::placeholders::_1)); m_Window->SetEventCallback(std::bind(&Application::OnEvent, this, std::placeholders::_1));
m_Window->SetWindowResizeEventCallback(std::bind(&Application::OnWindowResize, this, std::placeholders::_1));
Renderer::Init(); Renderer::Init();
@ -44,21 +45,21 @@ namespace Hazel {
m_lastFrameTime = currentTime; 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(); m_Window->OnUpdate();
} }
} }
@ -71,12 +72,29 @@ namespace Hazel {
(*--it)->OnEvent(e); (*--it)->OnEvent(e);
} }
if (e.type == SDL_EVENT_QUIT)
switch (e.type)
{ {
case SDL_EVENT_QUIT:
m_Running = false; 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) void Application::PushLayer(Layer* layer)
{ {
m_layerStack.PushLayer(layer); m_layerStack.PushLayer(layer);

View File

@ -19,6 +19,7 @@ namespace Hazel {
void Run(); void Run();
void OnEvent(SDL_Event& e); void OnEvent(SDL_Event& e);
void OnWindowResize(SDL_Event& e);
void PushLayer(Layer* layer); void PushLayer(Layer* layer);
void PushOverlay(Layer* layer); void PushOverlay(Layer* layer);
inline Window& GetWindow() { return *m_Window; } inline Window& GetWindow() { return *m_Window; }
@ -34,6 +35,7 @@ namespace Hazel {
TimeStep m_TimeStep; TimeStep m_TimeStep;
float m_lastFrameTime = 0.0f; float m_lastFrameTime = 0.0f;
bool m_Minimized = false;
private: private:
static Application* s_Instance; static Application* s_Instance;
}; };

View File

@ -63,7 +63,6 @@ namespace Hazel
void ImGuiLayer::OnImGuiRender() void ImGuiLayer::OnImGuiRender()
{ {
ImGui::ShowDemoWindow();
} }
void ImGuiLayer::Begin() void ImGuiLayer::Begin()

View File

@ -2,6 +2,11 @@
#include <spdlog/sinks/stdout_color_sinks.h> #include <spdlog/sinks/stdout_color_sinks.h>
#ifdef _DEBUG
#define LOG_LEVEL spdlog::level::trace
#else
#define LOG_LEVEL spdlog::level::debug
#endif
namespace Hazel { namespace Hazel {
@ -11,10 +16,10 @@ namespace Hazel {
void Log::init() { void Log::init() {
spdlog::set_pattern("%^[%T] %n: %v%$"); spdlog::set_pattern("%^[%T] %n: %v%$");
s_CoreLogger = spdlog::stdout_color_mt("Hazel"); 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 = spdlog::stdout_color_mt("App");
s_ClientLogger->set_level(spdlog::level::trace); s_ClientLogger->set_level(LOG_LEVEL);
} }
} }

View File

@ -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<float>(e.window.data1) / static_cast<float>(e.window.data2);
m_Camera.SetProjection(-m_AspectRatio * m_ZoomLevel, m_AspectRatio * m_ZoomLevel, -m_ZoomLevel, m_ZoomLevel);
return false;
}
return true;
}
}

View File

@ -0,0 +1,49 @@
//
// Created by sfd on 25-5-12.
//
#ifndef ORTHOGRAPHICCAMERACONTROLLER_H
#define ORTHOGRAPHICCAMERACONTROLLER_H
#include <SDL3/SDL_events.h>
#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

View File

@ -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() 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)); 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));

View File

@ -14,7 +14,7 @@ namespace Hazel
{ {
public: public:
OrthographicCamera(float left, float right, float bottom, float top); 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; } const glm::vec3& GetPosition() const { return m_Position; }

View File

@ -4,7 +4,6 @@
#include "Renderer.h" #include "Renderer.h"
#include <SDL3/SDL_opengl.h>
#include "Platform/OpenGL/OpenGLShader.h" #include "Platform/OpenGL/OpenGLShader.h"
#include "RendererCommand.h" #include "RendererCommand.h"
@ -19,6 +18,11 @@ namespace Hazel
RendererCommand::Init(); RendererCommand::Init();
} }
void Renderer::OnWindowResize(uint32_t width, uint32_t height)
{
RendererCommand::SetViewPort(0, 0, width, height);
}
void Renderer::BeginScene(OrthographicCamera& camera) void Renderer::BeginScene(OrthographicCamera& camera)
{ {
m_SceneData->ViewProjectionMatrix = camera.GetViewProjectionMatrix(); m_SceneData->ViewProjectionMatrix = camera.GetViewProjectionMatrix();

View File

@ -19,6 +19,7 @@ namespace Hazel
{ {
public: public:
static void Init(); static void Init();
static void OnWindowResize(uint32_t width, uint32_t height);
static void BeginScene(OrthographicCamera& camera); static void BeginScene(OrthographicCamera& camera);
static void EndScene(); static void EndScene();

View File

@ -25,6 +25,7 @@ namespace Hazel
public: public:
virtual void Init() = 0; virtual void Init() = 0;
virtual void SetClearColor(const glm::vec4& color) = 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 Clear() = 0;
virtual void DrawIndexed(const std::shared_ptr<Hazel::VertexArray>& vertexArray) = 0; virtual void DrawIndexed(const std::shared_ptr<Hazel::VertexArray>& vertexArray) = 0;

View File

@ -20,14 +20,23 @@ namespace Hazel {
{ {
s_RendererAPI->SetClearColor(color); 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() inline static void Clear()
{ {
s_RendererAPI->Clear(); s_RendererAPI->Clear();
} }
inline static void DrawIndexed(const std::shared_ptr<VertexArray>& vertexArray) { inline static void DrawIndexed(const std::shared_ptr<VertexArray>& vertexArray)
s_RendererAPI->DrawIndexed(vertexArray); {
} s_RendererAPI->DrawIndexed(vertexArray);
}
private: private:
static RendererAPI* s_RendererAPI; static RendererAPI* s_RendererAPI;

View File

@ -9,16 +9,72 @@
namespace Hazel namespace Hazel
{ {
Shader* Shader::Create(const std::string& vertexSrc, const std::string& fragmentSrc) Ref<Shader> Shader::Create(const std::string& name, const std::string& vertexSrc, const std::string& fragmentSrc)
{ {
switch (Renderer::GetAPI()) switch (Renderer::GetAPI())
{ {
case RendererAPI::API::NONE: return nullptr; case RendererAPI::API::NONE: return nullptr;
case RendererAPI::API::OPENGL: return new OpenGLShader(vertexSrc, fragmentSrc); case RendererAPI::API::OPENGL: return std::make_shared<OpenGLShader>(name, vertexSrc, fragmentSrc);
} }
HZ_CORE_ERROR("Unknown RendererAPI"); HZ_CORE_ERROR("Unknown RendererAPI");
return nullptr; return nullptr;
} }
Ref<Shader> Shader::Create(const std::string& filepath)
{
switch (Renderer::GetAPI())
{
case RendererAPI::API::NONE: return nullptr;
case RendererAPI::API::OPENGL: return std::make_shared<OpenGLShader>(filepath);
}
HZ_CORE_ERROR("Unknown RendererAPI");
return nullptr;
}
void ShaderLibrary::Add(const std::string& name, const Ref<Shader>& shader)
{
if (Exists(name))
{
HZ_CORE_ERROR("Shader already exists");
return;
}
m_Shaders[name] = shader;
}
void ShaderLibrary::Add(const Ref<Shader>& shader)
{
auto& name = shader->GetName();
Add(name, shader);
}
Ref<Shader> ShaderLibrary::Load(const std::string& filepath)
{
auto shader = std::make_shared<OpenGLShader>(filepath);
Add(shader);
return shader;
}
Ref<Shader> ShaderLibrary::Load(const std::string& name, const std::string& filepath)
{
auto shader = std::make_shared<OpenGLShader>(filepath);
Add(name, shader);
return shader;
}
Ref<Shader> 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);
}
} }

View File

@ -5,6 +5,7 @@
#ifndef SHADER_H #ifndef SHADER_H
#define SHADER_H #define SHADER_H
#include <string> #include <string>
#include <unordered_map>
#include <Hazel/Core.h> #include <Hazel/Core.h>
@ -18,10 +19,30 @@ namespace Hazel
virtual void Bind() const = 0; virtual void Bind() const = 0;
virtual void Unbind() 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<Shader> Create(const std::string& name, const std::string& vertexSrc, const std::string& fragmentSrc);
static Ref<Shader> Create(const std::string& filepath);
private: private:
uint32_t m_RendererID; uint32_t m_RendererID;
}; };
class HAZEL_API ShaderLibrary
{
public:
void Add(const Ref<Shader>& shader);
void Add(const std::string& name, const Ref<Shader>& shader);
Ref<Shader> Load(const std::string& filepath); // example: texture.glsl
Ref<Shader> Load(const std::string& name, const std::string& filepath);
Ref<Shader> Get(const std::string& name);
bool Exists(const std::string& name) const;
private:
std::unordered_map<std::string, Ref<Shader>> m_Shaders;
};
} }

View File

@ -28,6 +28,7 @@ namespace Hazel
{ {
public: public:
using EventCallbackFn = std::function<void(SDL_Event&)>; using EventCallbackFn = std::function<void(SDL_Event&)>;
using WindowsResizeCallbackFn = std::function<void(SDL_Event&)>;
virtual ~Window() = default; virtual ~Window() = default;
@ -38,6 +39,7 @@ namespace Hazel
// Window attributes // Window attributes
virtual void SetEventCallback(const EventCallbackFn& callback) = 0; virtual void SetEventCallback(const EventCallbackFn& callback) = 0;
virtual void SetWindowResizeEventCallback(const WindowsResizeCallbackFn& callback) = 0;
virtual void SetVSync(bool enabled) = 0; virtual void SetVSync(bool enabled) = 0;
virtual bool IsVSync() const = 0; virtual bool IsVSync() const = 0;

View File

@ -11,7 +11,6 @@ namespace Hazel
void OpenGLRendererAPI::Init() void OpenGLRendererAPI::Init()
{ {
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
} }
@ -20,6 +19,12 @@ namespace Hazel
glClearColor(color.x, color.y, color.z, color.w); 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() void OpenGLRendererAPI::Clear()
{ {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

View File

@ -14,6 +14,7 @@ namespace Hazel
public: public:
virtual void Init() override; virtual void Init() override;
virtual void SetClearColor(const glm::vec4& color) 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 Clear() override;
virtual void DrawIndexed(const std::shared_ptr<Hazel::VertexArray>& vertexArray) override; virtual void DrawIndexed(const std::shared_ptr<Hazel::VertexArray>& vertexArray) override;
}; };

View File

@ -3,81 +3,55 @@
// //
#include "OpenGLShader.h" #include "OpenGLShader.h"
#include <fstream>
#include <vector> #include <vector>
#include <glad/glad.h> #include <array>
#include <Hazel/Log.h> #include <Hazel/Log.h>
#include "glm/gtc/type_ptr.hpp" #include "glm/gtc/type_ptr.hpp"
#include "spdlog/fmt/bundled/compile.h"
namespace Hazel 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); if (type == "vertex") return GL_VERTEX_SHADER;
if (type == "fragment" || type == "pixel") return GL_FRAGMENT_SHADER;
const char* vertexShaderSrc = vertexSrc.c_str(); if (type == "geometry") return GL_GEOMETRY_SHADER;
glShaderSource(vertexShader, 1, &vertexShaderSrc, 0); if (type == "compute") return GL_COMPUTE_SHADER;
HZ_CORE_ERROR("Unknown Shader Type");
glCompileShader(vertexShader); return 0;
}
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<GLchar> infoLog(length);
glGetShaderInfoLog(vertexShader, length, &length, &infoLog[0]);
glDeleteShader(vertexShader);
HZ_CORE_ERROR("Vertex shader compilation failed!");
HZ_CORE_ERROR("{0}", infoLog.data());
return;
}
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); OpenGLShader::OpenGLShader(const std::string& filepath)
const char* fragmentShaderSrc = fragmentSrc.c_str(); {
glShaderSource(fragmentShader, 1, &fragmentShaderSrc, 0); std::string shaderSrc = ReadFile(filepath);
glCompileShader(fragmentShader); auto shaderSources = PreProcess(shaderSrc);
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &compileSuccess); Compile(shaderSources);
if (compileSuccess == GL_FALSE)
{
int length = 0;
glGetShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &length);
std::vector<GLchar> infoLog(length);
glGetShaderInfoLog(fragmentShader, length, &length, &infoLog[0]);
glDeleteShader(fragmentShader);
HZ_CORE_ERROR("[{0}:{1}]: Fragment shader compilation failed!", __FILE__, __LINE__); // example: /assets/shaders/Texture.glsl
HZ_CORE_ERROR("{0}", infoLog.data()); 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); auto lastSlash = filepath.find_last_of("\\/");
glAttachShader(m_RendererID, fragmentShader); lastSlash = lastSlash == std::string::npos ? 0 : lastSlash + 1;
glLinkProgram(m_RendererID); auto lastDot = filepath.rfind(".");
glGetProgramiv(m_RendererID, GL_LINK_STATUS, &compileSuccess); auto count = lastDot == std::string::npos ? filepath.size() - lastSlash : lastDot - lastSlash;
if (compileSuccess == GL_FALSE) m_Name = filepath.substr(lastSlash, count);
{ */
int length = 0; }
glGetProgramiv(m_RendererID, GL_INFO_LOG_LENGTH, &length);
std::vector<GLchar> infoLog(length);
glGetProgramInfoLog(m_RendererID, length, &length, &infoLog[0]);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
glDeleteProgram(m_RendererID);
HZ_CORE_ERROR("shaderProgram link failed!"); OpenGLShader::OpenGLShader(const std::string& name, const std::string& vertexSrc, const std::string& fragmentSrc): m_Name(name)
HZ_CORE_ERROR("{0}", infoLog.data()); {
return; std::unordered_map<GLenum, std::string> shaderSources;
} shaderSources[GL_VERTEX_SHADER] = vertexSrc;
shaderSources[GL_FRAGMENT_SHADER] = fragmentSrc;
glDeleteShader(vertexShader); Compile(shaderSources);
glDeleteShader(fragmentShader);
} }
@ -114,6 +88,133 @@ namespace Hazel
glUniformMatrix4fv(location, 1, GL_FALSE, glm::value_ptr(matrix)); 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<GLenum, std::string> OpenGLShader::PreProcess(const std::string& source)
{
std::unordered_map<GLenum, std::string> 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<GLenum, std::string>& shaderSource)
{
GLuint program = glCreateProgram();
// std::vector<GLenum> glShaderIDs;
// glShaderIDs.reserve(shaderSource.size());
if (shaderSource.size() > 2)
{
HZ_CORE_ERROR("Only support 2 shaders Now!");
}
std::array<GLenum, 2> 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<GLchar> 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<GLchar> 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 void OpenGLShader::UploadUniformInt(const char* str, const int value) const
{ {
const GLint location = glGetUniformLocation(m_RendererID, str); const GLint location = glGetUniformLocation(m_RendererID, str);

View File

@ -8,6 +8,7 @@
#include "glm/fwd.hpp" #include "glm/fwd.hpp"
#include "glm/vec4.hpp" #include "glm/vec4.hpp"
#include <glad/glad.h>
namespace Hazel namespace Hazel
@ -15,20 +16,29 @@ namespace Hazel
class HAZEL_API OpenGLShader : public Shader class HAZEL_API OpenGLShader : public Shader
{ {
public: 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; virtual ~OpenGLShader() override;
void Bind() const override; void Bind() const override;
void Unbind() 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 UploadUniformInt(const char* str, int value) const;
void UploadUniformFloat3(const std::string& name, const glm::vec3& 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 UploadUniformFloat4(const std::string& name, const glm::vec4& value) const;
void UploadUniformMat4(const std::string& name, const glm::mat4& matrix) const; void UploadUniformMat4(const std::string& name, const glm::mat4& matrix) const;
private:
std::string ReadFile(const std::string& filepath);
std::unordered_map<GLenum, std::string> PreProcess(const std::string& source);
void Compile(std::unordered_map<GLenum, std::string>& shaderSource);
private: private:
uint32_t m_RendererID; uint32_t m_RendererID;
std::string m_Name;
}; };
} }

View File

@ -9,6 +9,8 @@
#include <Platform/OpenGL/OpenGLContext.h> #include <Platform/OpenGL/OpenGLContext.h>
#include <glad/glad.h> #include <glad/glad.h>
#include "glm/gtc/constants.hpp"
namespace Hazel namespace Hazel
{ {
@ -65,7 +67,7 @@ namespace Hazel
HZ_CORE_INFO("Initing GLAD..."); HZ_CORE_INFO("Initing GLAD...");
if (!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress)) if (!gladLoadGLLoader(reinterpret_cast<GLADloadproc>(SDL_GL_GetProcAddress)))
{ {
HZ_CORE_ERROR("Could not initialize GLAD context!"); HZ_CORE_ERROR("Could not initialize GLAD context!");
} }
@ -87,6 +89,16 @@ namespace Hazel
while (SDL_PollEvent(&event)) 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) if (m_Data.eventCallback != nullptr)
{ {
m_Data.eventCallback(event); m_Data.eventCallback(event);

View File

@ -13,6 +13,7 @@
namespace Hazel namespace Hazel
{ {
class GraphicsContext; class GraphicsContext;
class WindowsWindow : public Window class WindowsWindow : public Window
@ -29,6 +30,7 @@ namespace Hazel
// Window attributes // Window attributes
inline void SetEventCallback(const EventCallbackFn& callback) override { m_Data.eventCallback = callback; } 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; void SetVSync(bool enabled) override;
bool IsVSync() const override; bool IsVSync() const override;
@ -52,6 +54,7 @@ namespace Hazel
EventCallbackFn eventCallback; EventCallbackFn eventCallback;
}; };
WindowsResizeCallbackFn OnWindowResize;
WindowData m_Data; WindowData m_Data;
}; };
} }

View File

@ -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);
}
}
}

View File

@ -4,7 +4,7 @@
#define GLM_ENABLE_EXPERIMENTAL #define GLM_ENABLE_EXPERIMENTAL
#include <glad/glad.h> #include <Hazel/OrthographicCameraController.h>
#include <Platform/OpenGL/OpenGLShader.h> #include <Platform/OpenGL/OpenGLShader.h>
#include <Platform/OpenGL/OpenGLTexture.h> #include <Platform/OpenGL/OpenGLTexture.h>
@ -17,7 +17,7 @@ class ExampleLayer : public Hazel::Layer
public: public:
// ExampleLayer() : Layer("ExampleLayer"), m_Camera(-1.0f, 1.0f, -1.0f, 1.0f), m_CameraPosition(0.0f) // 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------------------------------------------------------------ // ------------------------------------------------------------test------------------------------------------------------------
// Vertex Array // Vertex Array
@ -76,7 +76,7 @@ public:
color = vec4(v_Color, 1.0f); 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()); m_SquareVA.reset(Hazel::VertexArray::Create());
@ -103,7 +103,7 @@ public:
squareIB.reset(Hazel::IndexBuffer::Create(squareIndice, sizeof(squareIndice) / sizeof(uint32_t))); squareIB.reset(Hazel::IndexBuffer::Create(squareIndice, sizeof(squareIndice) / sizeof(uint32_t)));
m_SquareVA->SetIndexBuffer(squareIB); m_SquareVA->SetIndexBuffer(squareIB);
std::string bluevertexSrc = R"( std::string coloeVertexSrc = R"(
#version 460 core #version 460 core
layout(location = 0) in vec3 a_Position; layout(location = 0) in vec3 a_Position;
@ -119,7 +119,7 @@ public:
gl_Position = u_ViewProjection * u_Transform * vec4(a_Position, 1.0f); gl_Position = u_ViewProjection * u_Transform * vec4(a_Position, 1.0f);
} }
)"; )";
std::string bluefragmentSrc = R"( std::string colorFragmentSrc = R"(
#version 460 core #version 460 core
layout(location = 0) out vec4 color; layout(location = 0) out vec4 color;
@ -131,168 +131,107 @@ public:
color = u_Color; color = u_Color;
} }
)"; )";
m_colorShader.reset(Hazel::Shader::Create(bluevertexSrc, bluefragmentSrc)); m_colorShader = Hazel::Shader::Create("ColorShader", coloeVertexSrc, colorFragmentSrc);
std::string textureVertexSrc = R"( // Texture.Shader
#version 460 core // m_TextureShader = Hazel::Shader::Create("assets/shaders/Texture.glsl");
auto textureShader = m_ShaderLibrary.Load("assets/shaders/Texture.glsl");
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 // Texture
m_Texture = Hazel::Texture2D::Create("assets/textures/Checkerboard.png"); m_Texture = Hazel::Texture2D::Create("assets/textures/Checkerboard.png");
m_logoTexture = Hazel::Texture2D::Create("assets/textures/iceLogo.png"); m_logoTexture = Hazel::Texture2D::Create("assets/textures/iceLogo.png");
std::dynamic_pointer_cast<Hazel::OpenGLShader>(m_TextureShader)->Bind(); std::dynamic_pointer_cast<Hazel::OpenGLShader>(textureShader)->Bind();
std::dynamic_pointer_cast<Hazel::OpenGLShader>(m_TextureShader)->UploadUniformInt("u_Texture", 0); std::dynamic_pointer_cast<Hazel::OpenGLShader>(textureShader)->UploadUniformInt("u_Texture", 0);
} }
void OnUpdate(Hazel::TimeStep& ts) override void OnUpdate(Hazel::TimeStep& ts) override
{ {
m_CameraController.OnUpdate(ts);
// key event // key event
{ {
float time = ts; float time = ts;
const bool* state = SDL_GetKeyboardState(NULL); 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]) if (state[SDL_SCANCODE_I])
{ {
m_SquarePosition.y += m_CameraSpeed * time; m_SquarePosition.y += 5 * time;
} }
else if (state[SDL_SCANCODE_K]) else if (state[SDL_SCANCODE_K])
{ {
m_SquarePosition.y -= m_CameraSpeed * time; m_SquarePosition.y -= 5 * time;
} }
if (state[SDL_SCANCODE_J]) if (state[SDL_SCANCODE_J])
{ {
m_SquarePosition.x -= m_CameraSpeed * time; m_SquarePosition.x -= 5 * time;
} }
else if (state[SDL_SCANCODE_L]) else if (state[SDL_SCANCODE_L])
{ {
m_SquarePosition.x += m_CameraSpeed * time; m_SquarePosition.x += 5 * time;
} }
} }
Hazel::RendererCommand::SetClearColor(m_ScreenClearColor);
Hazel::RendererCommand::SetClearColor({0.1f, 0.1f, 0.1f, 1.0f});
Hazel::RendererCommand::Clear(); Hazel::RendererCommand::Clear();
m_Camera.SetPosition(m_CameraPosition); Hazel::Renderer::BeginScene(m_CameraController.GetCamera());
m_Camera.SetRotation(m_CameraRotation);
Hazel::Renderer::BeginScene(m_Camera);
auto transform = glm::translate(glm::mat4(1.0f), m_SquarePosition); auto transform = glm::translate(glm::mat4(1.0f), m_SquarePosition);
auto textureShader = m_ShaderLibrary.Get("Texture");
m_Texture->Bind(); m_Texture->Bind();
Hazel::Renderer::Submit(m_TextureShader, m_SquareVA, transform); Hazel::Renderer::Submit(textureShader, m_SquareVA, transform);
m_logoTexture->Bind(); m_logoTexture->Bind();
Hazel::Renderer::Submit(m_TextureShader, m_SquareVA); Hazel::Renderer::Submit(textureShader, m_SquareVA);
Hazel::Renderer::EndScene(); Hazel::Renderer::EndScene();
} }
void OnEvent(SDL_Event& event) override void OnEvent(SDL_Event& event) override
{ {
m_CameraController.OnEvent(event);
} }
void OnImGuiRender() override void OnImGuiRender() override
{ {
ImGui::ShowDemoWindow();
const auto cameraRotation = m_CameraController.GetCamera().GetRotation();
const auto cameraPosition = m_CameraController.GetCamera().GetPosition();
ImGui::Begin("Hazel Layer"); ImGui::Begin("Hazel Layer");
ImGui::Text("Rotation: %f", m_CameraRotation); ImGui::Text("Rotation: %f", cameraRotation);
ImGui::Text("Position: ( %.2f, %.2f, %.2f)", m_CameraPosition.x, m_CameraPosition.y, m_CameraPosition.z); ImGui::Text("Position: ( %.2f, %.2f, %.2f)", cameraPosition.x, cameraPosition.y, cameraPosition.z);
ImGui::Text("frame: %.3f", ImGui::GetIO().Framerate); ImGui::Text("frame: %.3f", ImGui::GetIO().Framerate);
ImGui::ColorEdit3("Square Color", glm::value_ptr(m_SquareColor)); ImGui::ColorEdit3("Square Color", glm::value_ptr(m_SquareColor));
ImGui::NewLine();
ImGui::ColorEdit4("Screen Clear Color", glm::value_ptr(m_ScreenClearColor));
ImGui::End(); ImGui::End();
} }
private: private:
Hazel::ShaderLibrary m_ShaderLibrary;
Hazel::Ref<Hazel::Shader> m_Shader; Hazel::Ref<Hazel::Shader> m_Shader;
Hazel::Ref<Hazel::VertexArray> m_VertexArray; Hazel::Ref<Hazel::VertexArray> m_VertexArray;
Hazel::Ref<Hazel::VertexArray> m_SquareVA; Hazel::Ref<Hazel::VertexArray> m_SquareVA;
Hazel::Ref<Hazel::Shader> m_colorShader, m_TextureShader; Hazel::Ref<Hazel::Shader> m_colorShader;
Hazel::Ref<Hazel::Texture2D> m_Texture, m_logoTexture; Hazel::Ref<Hazel::Texture2D> m_Texture, m_logoTexture;
Hazel::OrthographicCamera m_Camera; Hazel::OrthographicCameraController m_CameraController;
glm::vec3 m_CameraPosition;
float m_CameraSpeed = 1.0f;
float m_CameraRotation = 0.0f;
float m_CameraRotationSpeed = 30.f;
glm::vec3 m_SquarePosition; glm::vec3 m_SquarePosition;
float m_SquareMoveSpeed = 1.0f; float m_SquareMoveSpeed = 1.0f;
glm::vec3 m_SquareColor = {0.2f, 0.3f, 0.8f}; glm::vec3 m_SquareColor = {0.2f, 0.3f, 0.8f};
glm::vec4 m_ScreenClearColor = {0.1f, 0.1f, 0.1f, 1.0f};
}; };