引入GLFW:
在vendor里创建GLFW文件夹:
在github上下载,把包下载到GLFW包下。
GitHub – TheCherno/glfw: A multi-platform library for OpenGL, OpenGL ES, Vulkan, window and input修改SRC/premake5.lua的配置:12、13、15、36、37、38、39、40行的代码是新加上去的:
workspace "YOTOEngine"-- sln文件名architecture "x64"configurations{"Debug","Release","Dist"}-- https://github.com/premake/premake-core/wiki/Tokens#value-tokens-- 组成输出目录:Debug-windows-x86_64outputdir = "%{cfg.buildcfg}-%{cfg.system}-%{cfg.architecture}"IncludeDir={}IncludeDir["GLFW"]="YOTOEngine/vendor/GLFW/include"include "YOTOEngine/vendor/GLFW"project "YOTOEngine"--Hazel项目location "YOTOEngine"--在sln所属文件夹下的Hazel文件夹kind "SharedLib"--dll动态库language "C++"targetdir ("bin/" .. outputdir .. "/%{prj.name}") -- 输出目录objdir ("bin-int/" .. outputdir .. "/%{prj.name}")-- 中间目录pchheader "ytpch.h"pchsource "YOTOEngine/src/ytpch.cpp"-- 包含的所有h和cpp文件files{"%{prj.name}/src/**.h","%{prj.name}/src/**.cpp"}-- 包含目录includedirs{"%{prj.name}/src","%{prj.name}/vendor/spdlog-1.x/include","%{IncludeDir.GLFW}"}links{"GLFW","opengl32.lib"}-- 如果是window系统filter "system:windows"cppdialect "C++17"-- On:代码生成的运行库选项是MTD,静态链接MSVCRT.lib库;-- Off:代码生成的运行库选项是MDD,动态链接MSVCRT.dll库;打包后的exe放到另一台电脑上若无这个dll会报错staticruntime "On"systemversion "latest"-- windowSDK版本-- 预处理器定义defines{"YT_PLATFORM_WINDOWS","YT_BUILD_DLL","YT_ENABLE_ASSERTS",}-- 编译好后移动Hazel.dll文件到Sandbox文件夹下postbuildcommands{("{COPY} %{cfg.buildtarget.relpath} ../bin/" .. outputdir .. "/Sandbox")}-- 不同配置下的预定义不同filter "configurations:Debug"defines "YT_DEBUG"symbols "On"filter "configurations:Release"defines "YT_RELEASE"optimize "On"filter "configurations:Dist"defines "YT_DIST"optimize "On"project "Sandbox"location "Sandbox"kind "ConsoleApp"language "C++"targetdir ("bin/" .. outputdir .. "/%{prj.name}")objdir ("bin-int/" .. outputdir .. "/%{prj.name}")files{"%{prj.name}/src/**.h","%{prj.name}/src/**.cpp"}-- 同样包含spdlog头文件includedirs{"YOTOEngine/vendor/spdlog-1.x/include","YOTOEngine/src"}-- 引用hazellinks{"YOTOEngine","GLFW","opengl32.lib"}filter "system:windows"cppdialect "C++17"staticruntime "On"systemversion "latest"defines{"YT_PLATFORM_WINDOWS"}filter "configurations:Debug"defines "YT_DEBUG"symbols "On"filter "configurations:Release"defines "YT_RELEASE"optimize "On"filter "configurations:Dist"defines "YT_DIST"optimize "On"
GLFW中的premake5.lua:
project "GLFW"kind "StaticLib"language "C"staticruntime "off"warnings "off"targetdir ("bin/" .. outputdir .. "/%{prj.name}")objdir ("bin-int/" .. outputdir .. "/%{prj.name}")files{"include/GLFW/glfw3.h","include/GLFW/glfw3native.h","src/glfw_config.h","src/context.c","src/init.c","src/input.c","src/monitor.c","src/null_init.c","src/null_joystick.c","src/null_monitor.c","src/null_window.c","src/platform.c","src/vulkan.c","src/window.c",}filter "system:linux"pic "On"systemversion "latest"files{"src/x11_init.c","src/x11_monitor.c","src/x11_window.c","src/xkb_unicode.c","src/posix_module.c","src/posix_time.c","src/posix_thread.c","src/posix_module.c","src/glx_context.c","src/egl_context.c","src/osmesa_context.c","src/linux_joystick.c"}defines{"_GLFW_X11"}filter "system:macosx"pic "On"files{"src/cocoa_init.m","src/cocoa_monitor.m","src/cocoa_window.m","src/cocoa_joystick.m","src/cocoa_time.c","src/nsgl_context.m","src/posix_thread.c","src/posix_module.c","src/osmesa_context.c","src/egl_context.c"}defines{"_GLFW_COCOA"}filter "system:windows"systemversion "latest"files{"src/win32_init.c","src/win32_joystick.c","src/win32_module.c","src/win32_monitor.c","src/win32_time.c","src/win32_thread.c","src/win32_window.c","src/wgl_context.c","src/egl_context.c","src/osmesa_context.c"}defines { "_GLFW_WIN32","_CRT_SECURE_NO_WARNINGS"}--解决bug的部分:buildoptions "/MTD" 和"/MT"filter "configurations:Debug"defines "YT_DEBUG"buildoptions "/MTd"symbols "On"filter { "system:windows", "configurations:Debug-AS" }runtime "Debug"symbols "on"sanitize { "Address" }flags { "NoRuntimeChecks", "NoIncrementalLink" }filter "configurations:Release"defines "YT_RELEASE"buildoptions "/MT"symbols "On"filter "configurations:Dist"defines "YT_DIST"buildoptions "/MT"symbols "On"
运行测试:
如出现此BUG:请找GLFW中的premake5文件,把上述的premake5.lua的bug解决部分改一下:
使GLFW项目的运行库,只能是MT或者MTD,不能是MD或者MDD
执行GenerateProject.bat文件:
刷新解决方案得到GLFW的包:
窗口抽象:
创建window基类,用于不同平台window的实现。
YOTO/Window.h:
#pragma once#include"ytpch.h"#include"YOTO/Core.h"#include"YOTO/Event/Event.h"namespace YOTO {struct WindowProps {std::string Title;unsigned int Width;unsigned int Height;WindowProps(const std::string &title="YOTO Engine",unsigned int width =1280, unsigned int height = 1280 ):Title(title),Width(width),Height(height){}};class YOTO_API Window {public://用EventCallbackFn代替std::function:输入为Event&返回值为void 的函数using EventCallbackFn = std::function;virtual ~Window(){}//=0为纯虚函数virtual void OnUpdate() = 0;virtual unsigned int GetWidth() const = 0;virtual unsigned int GetHeight() const = 0;virtual void SetEventCallback(const EventCallbackFn& callback) = 0;virtual void SetSync(bool enable)const = 0;virtual bool IsVSync() const = 0;static Window* Creat(const WindowProps& props = WindowProps());};}
实现类:
创建文件夹src/Platform/Windows
WindowsWindow.h:
#pragma once#include "YOTO/Window.h"#include#include"YOTO/Log.h"namespace YOTO {class WindowsWindow :public Window{public :WindowsWindow(const WindowProps& props);virtual ~WindowsWindow();void OnUpdate() override;inline unsigned int GetWidth() const override { return m_Data.Width; };inline unsigned int GetHeight() const override { return m_Data.Height; };inline void SetEventCallback(const EventCallbackFn& callback)override { m_Data.EventCallback = callback; };void SetVSync(bool enable) ;bool IsVSync()const;private: virtual void Init(const WindowProps& props);virtual void ShutDown();private:GLFWwindow* m_Window;struct WindowData {std::string Title;unsigned int Width, Height;bool VSync;EventCallbackFn EventCallback;};WindowData m_Data;};}
WindowsWindow.cpp:
#include "ytpch.h"#include "WindowsWindow.h"namespace YOTO {static bool s_GLFWInitialized = false;Window* Window::Creat(const WindowProps& props) {return new WindowsWindow(props);}WindowsWindow::WindowsWindow(const WindowProps& props) {Init(props);}WindowsWindow::~WindowsWindow() {ShutDown();}void WindowsWindow::Init(const WindowProps& props) {m_Data.Title = props.Title;m_Data.Width = props.Width;m_Data.Height = props.Height;YT_CORE_INFO("创建了{0},{1},{2}", props.Title, props.Width, props.Height);if (!s_GLFWInitialized) {int success = glfwInit();YT_CLIENT_ASSERT("不能创建新的glfw,{0}", success);s_GLFWInitialized = true;}m_Window = glfwCreateWindow((int)props.Width, (int)props.Height, m_Data.Title.c_str(), nullptr, nullptr);glfwMakeContextCurrent(m_Window); glfwSetWindowUserPointer(m_Window, &m_Data);SetVSync(true);}void WindowsWindow::ShutDown() {glfwDestroyWindow(m_Window);}void WindowsWindow::OnUpdate(){//轮询事件glfwPollEvents();//交换缓冲区glfwSwapBuffers(m_Window);}void WindowsWindow::SetVSync(bool enable) {if (enable)glfwSwapInterval(1);elseglfwSwapInterval(0);m_Data.VSync = enable;}bool WindowsWindow::IsVSync() const {return m_Data.VSync;}}
Core.h:添加新的Error
#pragma once//用于dll的宏#ifdef YT_PLATFORM_WINDOWS#ifdef YT_BUILD_DLL#define YOTO_API __declspec(dllexport) #else#define YOTO_API __declspec(dllimport) #endif // DEBUG#else#error YOTO_ONLY_SUPPORT_WINDOWS#endif // YOTO_PLATFORM_WINDOWS#ifdef YT_ENABLE_ASSERTS#define YT_CLIENT_ASSERT(x,...) {if(!(x)){YT_CLIENT_ERROR("断言错误:{0}",__VA_ARGS__);__debugbreak();}}#define YT_CORE_ASSERT(x,...) {if(!(x)){YT_CORE_ERROR("断言错误:{0}",__VA_ARGS__);__debugbreak();}}#else#define YT_ASSERT(x,...)#define YT_CORE_ASSERT(x,...)#endif // YT_ENABLE_ASSERTS#define BIT(x)(1<<x)
Application.h:创建智能指针作为窗口的指针
#pragma once#include"Core.h"#include"Event/Event.h"#include namespace YOTO {class YOTO_API Application{public:Application();virtual ~Application();void Run();private:std::unique_ptrm_Window;bool m_Running = true;};//在客户端定义Application* CreateApplication();}
最终测试:
Application.cpp:在构造函数中创建窗口,在run的while循环中调用Update,写一段opengl测试代码窗口改变颜色
#include"ytpch.h"#include "Application.h"#include"Event/ApplicationEvent.h"#include"Log.h"#includenamespace YOTO {Application::Application() {//智能指针m_Window = std::unique_ptr(Window::Creat());}Application::~Application() {}void Application::Run() {WindowResizeEvent e(1280, 720);if (e.IsInCategory(EventCategoryApplication)) {YT_CORE_TRACE(e);}if (e.IsInCategory(EventCategoryInput)) {YT_CORE_ERROR(e);}while (m_Running){glClearColor(1,0,1,1);glClear(GL_COLOR_BUFFER_BIT);m_Window->OnUpdate();}}}
BUG:只需要重新生成一下YOTOEngine就好了
BUG:可抽象的一个bug。原因是WindowsWindow.cpp错误的添加了#include”YOTO.h”把它删掉就好了。
结果:
至此,基本的环境已经搭建完毕。