增加窗口自由缩放
This commit is contained in:
@ -24,6 +24,7 @@ namespace Hazel {
|
||||
|
||||
m_Window = std::unique_ptr<Window>(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,6 +45,8 @@ namespace Hazel {
|
||||
m_lastFrameTime = currentTime;
|
||||
|
||||
|
||||
if (!m_Minimized)
|
||||
{
|
||||
for (Layer* layer : m_layerStack)
|
||||
{
|
||||
layer->OnUpdate(timestep);
|
||||
@ -55,9 +58,7 @@ namespace Hazel {
|
||||
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);
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
@ -63,7 +63,6 @@ namespace Hazel
|
||||
|
||||
void ImGuiLayer::OnImGuiRender()
|
||||
{
|
||||
ImGui::ShowDemoWindow();
|
||||
}
|
||||
|
||||
void ImGuiLayer::Begin()
|
||||
|
||||
@ -2,6 +2,11 @@
|
||||
|
||||
#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 {
|
||||
|
||||
@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
82
Hazel/src/Hazel/OrthographicCameraController.cpp
Normal file
82
Hazel/src/Hazel/OrthographicCameraController.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
49
Hazel/src/Hazel/OrthographicCameraController.h
Normal file
49
Hazel/src/Hazel/OrthographicCameraController.h
Normal 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
|
||||
@ -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));
|
||||
|
||||
@ -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; }
|
||||
|
||||
|
||||
@ -4,7 +4,6 @@
|
||||
|
||||
#include "Renderer.h"
|
||||
|
||||
#include <SDL3/SDL_opengl.h>
|
||||
|
||||
#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();
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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<Hazel::VertexArray>& vertexArray) = 0;
|
||||
|
||||
@ -20,15 +20,24 @@ 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>& vertexArray) {
|
||||
inline static void DrawIndexed(const std::shared_ptr<VertexArray>& vertexArray)
|
||||
{
|
||||
s_RendererAPI->DrawIndexed(vertexArray);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private:
|
||||
static RendererAPI* s_RendererAPI;
|
||||
};
|
||||
|
||||
@ -9,16 +9,72 @@
|
||||
|
||||
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())
|
||||
{
|
||||
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");
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
#ifndef SHADER_H
|
||||
#define SHADER_H
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <Hazel/Core.h>
|
||||
|
||||
|
||||
@ -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<Shader> Create(const std::string& name, const std::string& vertexSrc, const std::string& fragmentSrc);
|
||||
static Ref<Shader> Create(const std::string& filepath);
|
||||
private:
|
||||
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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -28,6 +28,7 @@ namespace Hazel
|
||||
{
|
||||
public:
|
||||
using EventCallbackFn = std::function<void(SDL_Event&)>;
|
||||
using WindowsResizeCallbackFn = std::function<void(SDL_Event&)>;
|
||||
|
||||
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;
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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<Hazel::VertexArray>& vertexArray) override;
|
||||
};
|
||||
|
||||
@ -3,81 +3,55 @@
|
||||
//
|
||||
|
||||
#include "OpenGLShader.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <glad/glad.h>
|
||||
#include <array>
|
||||
#include <Hazel/Log.h>
|
||||
|
||||
#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<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;
|
||||
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)
|
||||
OpenGLShader::OpenGLShader(const std::string& filepath)
|
||||
{
|
||||
int length = 0;
|
||||
glGetShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &length);
|
||||
std::vector<GLchar> infoLog(length);
|
||||
glGetShaderInfoLog(fragmentShader, length, &length, &infoLog[0]);
|
||||
glDeleteShader(fragmentShader);
|
||||
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;
|
||||
|
||||
/*
|
||||
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);
|
||||
*/
|
||||
}
|
||||
|
||||
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)
|
||||
OpenGLShader::OpenGLShader(const std::string& name, const std::string& vertexSrc, const std::string& fragmentSrc): m_Name(name)
|
||||
{
|
||||
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!");
|
||||
HZ_CORE_ERROR("{0}", infoLog.data());
|
||||
return;
|
||||
}
|
||||
|
||||
glDeleteShader(vertexShader);
|
||||
glDeleteShader(fragmentShader);
|
||||
std::unordered_map<GLenum, std::string> 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<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
|
||||
{
|
||||
const GLint location = glGetUniformLocation(m_RendererID, str);
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
|
||||
#include "glm/fwd.hpp"
|
||||
#include "glm/vec4.hpp"
|
||||
#include <glad/glad.h>
|
||||
|
||||
|
||||
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<GLenum, std::string> PreProcess(const std::string& source);
|
||||
void Compile(std::unordered_map<GLenum, std::string>& shaderSource);
|
||||
|
||||
private:
|
||||
uint32_t m_RendererID;
|
||||
std::string m_Name;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -9,6 +9,8 @@
|
||||
#include <Platform/OpenGL/OpenGLContext.h>
|
||||
#include <glad/glad.h>
|
||||
|
||||
#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<GLADloadproc>(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);
|
||||
|
||||
@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
38
Sandbox/assets/shaders/Texture.glsl
Normal file
38
Sandbox/assets/shaders/Texture.glsl
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4,7 +4,7 @@
|
||||
#define GLM_ENABLE_EXPERIMENTAL
|
||||
|
||||
|
||||
#include <glad/glad.h>
|
||||
#include <Hazel/OrthographicCameraController.h>
|
||||
#include <Platform/OpenGL/OpenGLShader.h>
|
||||
#include <Platform/OpenGL/OpenGLTexture.h>
|
||||
|
||||
@ -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<Hazel::OpenGLShader>(m_TextureShader)->Bind();
|
||||
std::dynamic_pointer_cast<Hazel::OpenGLShader>(m_TextureShader)->UploadUniformInt("u_Texture", 0);
|
||||
std::dynamic_pointer_cast<Hazel::OpenGLShader>(textureShader)->Bind();
|
||||
std::dynamic_pointer_cast<Hazel::OpenGLShader>(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<Hazel::Shader> m_Shader;
|
||||
Hazel::Ref<Hazel::VertexArray> m_VertexArray;
|
||||
|
||||
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::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};
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user