Hazel游戏引擎(011)窗口抽象和GLFW创建窗口

这篇具有很好参考价值的文章主要介绍了Hazel游戏引擎(011)窗口抽象和GLFW创建窗口。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

文中若有代码、术语等错误,欢迎指正

前言

  • 此节目的

    为了有窗口效果,但不想使用原生的window32写起,所以用glfw窗口库。

    也为了完成008计划事件系统的创建窗口部分

  • 图示

    Hazel游戏引擎(011)窗口抽象和GLFW创建窗口,Hazel游戏引擎,游戏引擎,glfw,窗口,git

步骤

GIT添加GLFW子模块及编译

  • 添加glfw子模块

    git add submodule https://github.com/TheCherno/glfw Hazel/vendor/GLFW
    

    Hazel游戏引擎(011)窗口抽象和GLFW创建窗口,Hazel游戏引擎,游戏引擎,glfw,窗口,git

  • 修改premake

    解决方案下的premake修改

    -- 包含相对解决方案的目录
    IncludeDir = {}
    IncludeDir["GLFW"] = "Hazel/vendor/GLFW/include"
    -- 这个include,相当于把glfw下的premake5.lua内容拷贝到这里
    include "Hazel/vendor/GLFW"
    project "Hazel"		--Hazel项目
    	location "Hazel"--在sln所属文件夹下的Hazel文件夹
    	kind "SharedLib"--dll动态库
    	-- 包含目录
    	includedirs{
    		"%{prj.name}/src",
    		"%{prj.name}/vendor/spdlog/include",
    		"%{IncludeDir.GLFW}"
    	}
    	-- Hazel链接glfw项目
    	links 
    	{ 
    		"GLFW",
    		"opengl32.lib"
    	}
    	filter "system:windows"
    		defines{
    			"HZ_PLATFORM_WINDOWS",
    			"HZ_ENABLE_ASSERTS"
    		}
    
  • 效果

    Hazel游戏引擎(011)窗口抽象和GLFW创建窗口,Hazel游戏引擎,游戏引擎,glfw,窗口,git

Window类

  • 目前类图

    Hazel游戏引擎(011)窗口抽象和GLFW创建窗口,Hazel游戏引擎,游戏引擎,glfw,窗口,git

    Application类可以调用创建窗口函数,而窗口类使用glfw库创建真正的窗口。

    窗口类检测glfw窗口的事件,并回调给Application的处理事件函数。

  • 代码

    window.h

    #pragma once
    #include "hzpch.h"
    #include "Hazel/Core.h"
    #include "Hazel/Events/Event.h"
    namespace Hazel {
    	struct WindowProps{// 窗口初始化设置的内容
    		std::string Title;
    		unsigned int Width;
    		unsigned int Height;
    		WindowProps(const std::string& title = "Hazel Engine",
    			unsigned int width = 1280,
    			unsigned int height = 720)
    			: Title(title), Width(width), Height(height){}
    	};
    	class HAZEL_API Window{
    	public:
    		using EventCallbackFn = std::function<void(Event&)>;
    		virtual ~Window() {}
    		virtual void OnUpdate() = 0;
    		virtual unsigned int GetWidth() const = 0;
    		virtual unsigned int GetHeight() const = 0;
    		// Window attributes
    		virtual void SetEventCallback(const EventCallbackFn& callback) = 0;
    		virtual void SetVSync(bool enabled) = 0;
    		virtual bool IsVSync() const = 0;
            // 在Window父类声明创建函数
    		static Window* Create(const WindowProps& props = WindowProps());
    	};
    }
    

    WindowsWindow.h

    #pragma once
    #include "Hazel/Window.h"
    #include <GLFW/glfw3.h>
    namespace Hazel {
    	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; }
    		// 设置Application的回调函数
    		inline void SetEventCallback(const EventCallbackFn& callback) override { m_Data.EventCallback = callback; }
    		void SetVSync(bool enabled) override;
    		bool IsVSync() const override;
    	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 "hzpch.h"
    #include "WindowsWindow.h"
    
    namespace Hazel {
    	static bool s_GLFWInitialized = false;
        // 在WindowsWindow子类定义在Window父类声明的函数
    	Window* Window::Create(const WindowProps& props){
    		return new WindowsWindow(props);
    	}
    	WindowsWindow::WindowsWindow(const WindowProps& props){
    		Init(props);
    	}
    	void WindowsWindow::Init(const WindowProps& props){
    		m_Data.Title = props.Title;
    		m_Data.Width = props.Width;
    		m_Data.Height = props.Height;
    		HZ_CORE_INFO("Creating window {0} ({1}, {2})", props.Title, props.Width, props.Height);
    		if (!s_GLFWInitialized){
    			// TODO: glfwTerminate on system shutdown
    			int success = glfwInit();
    			HZ_CORE_ASSERT(success, "Could not intialize GLFW!");// 是Core.h里面预处理器指令定义了HZ_CORE_ASSERT
    			s_GLFWInitialized = true;
    		}
    		// 创建窗口//
    		m_Window = glfwCreateWindow((int)props.Width, (int)props.Height, m_Data.Title.c_str(), nullptr, nullptr);
    		// 设置glfw当前的上下文
    		glfwMakeContextCurrent(m_Window);
    		/*
    			设置窗口关联的用户数据指针。这里GLFW仅做存储,不做任何的特殊处理和应用。
    			window表示操作的窗口句柄。
    			pointer表示用户数据指针。
    		*/
    		glfwSetWindowUserPointer(m_Window, &m_Data);
    		SetVSync(true);
    	}
    	void WindowsWindow::OnUpdate(){
    		glfwPollEvents();			// 轮询事件	
    		glfwSwapBuffers(m_Window);	// 交换缓冲
    	}
    	.....
    }
    
  • HZ_CORE_ASSERT

    在Core.h中

    #ifdef HZ_ENABLE_ASSERTS
    #define HZ_ASSERT(x, ...) { if(!(x)) { HZ_ERROR("Assertion Failed: {0}", __VA_ARGS__); __debugbreak(); } }
    #define HZ_CORE_ASSERT(x, ...) { if(!(x)) { HZ_CORE_ERROR("Assertion Failed: {0}", __VA_ARGS__); __debugbreak(); } }
    #else
    #define HZ_ASSERT(x, ...)
    #define HZ_CORE_ASSERT(x, ...)
    #endif
    
    HZ_CORE_ASSERT(success, "Could not intialize GLFW!");
    // 转换成
    { if(!(success)) { ::Hazel::Log::GetCoreLogger()->error("Assertion Failed: {0}", "Could not intialize GLFW!"); __debugbreak(); } };
    

    可见:…当做参数包被__VA_ARGS__展开;__debugbreak();是在debug模式下的断点

其它修改

  • Application

    #pragma once
    #include "Core.h"
    #include "Events/Event.h"
    #include "Window.h"
    namespace Hazel {
    	class HAZEL_API Application{
    	public:
    		Application();
    		virtual ~Application();
    		void Run();
    	private:
    		std::unique_ptr<Window> m_Window;
    		bool m_Running = true;
    	};
    	Application* CreateApplication();
    }
    
    #include "hzpch.h"
    #include "Application.h"
    #include "Hazel/Events/ApplicationEvent.h" // 包含事件
    #include "Hazel/Log.h"
    #include <GLFW/glfw3.h>
    namespace Hazel {
    	Application::Application(){
    		m_Window = std::unique_ptr<Window>(Window::Create()); // 创建窗口
    	}
    	Application::~Application() {}
    	void Application::Run(){
    		while (m_Running){
                // 清屏
    			glClearColor(1, 0, 1, 1);
    			glClear(GL_COLOR_BUFFER_BIT);
    			m_Window->OnUpdate();	// 更新glfw
    		}
    	}
    }
    

效果

Hazel游戏引擎(011)窗口抽象和GLFW创建窗口,Hazel游戏引擎,游戏引擎,glfw,窗口,git

Bug记录

  • glfw找不到函数定义

    Hazel游戏引擎(011)窗口抽象和GLFW创建窗口,Hazel游戏引擎,游戏引擎,glfw,窗口,git

  • 解决方法一

    修改GLFW的premake

    filter "configurations:Debug"
        defines "HZ_DEBUG"
        buildoptions "/MTd"
        symbols "On"
    
        filter "configurations:Release"
        defines "HZ_RELEASE"
        buildoptions "/MT"
        symbols "On"
    
        filter "configurations:Dist"
        defines "HZ_DIST"
        buildoptions "/MT"
        symbols "On"
    

    使GLFW项目的运行库,只能是MT或者MTD不能是MD或者MDD

    重新生成项目解决方案才行

    Hazel游戏引擎(011)窗口抽象和GLFW创建窗口,Hazel游戏引擎,游戏引擎,glfw,窗口,git

    关于运行库选项:

    // 运行库选项是MTD,静态链接MSVCRT.lib库;
    // 运行库选项是MDD,动态链接MSVCRT.dll库;打包后的exe放到另一台电脑上若无这个dll会报错
    
    • 为什么GLFW要改为MT或者MTD才行

      Hazel是MTD静态链接MSVCRT.dll库、而引用GLFW项目却是MDD动态链接MSVCRT.dll库,可能不兼容。如下是Hazel项目的运行库选项

      Hazel游戏引擎(011)窗口抽象和GLFW创建窗口,Hazel游戏引擎,游戏引擎,glfw,窗口,git

  • 解决方法二

    由于Hazel默认是MTD,GLFW默认是MDD,那么就将Hazel用premake改为MDD动态链接MSVCRT.dll库,符合Hazel作为dll库(SharedLib)的方式

    更改解决方案下的premake5.lua文件

    project "Hazel"
        ......
       filter "configurations:Debug"
    		defines "HZ_DEBUG"
    		buildoptions "/MDd"
    		symbols "On"
    
    	filter "configurations:Release"
    		defines "HZ_RELEASE"
    		buildoptions "/MD"
    		optimize "On"
    
    	filter "configurations:Dist"
    		defines "HZ_DIST"
    		buildoptions "/MD"
    		optimize "On"
    
    project "Sandbox"
    	......
    	filter "configurations:Debug"
    		defines "HZ_DEBUG"
    		buildoptions "/MDd"
    		symbols "On"
    
    	filter "configurations:Release"
    		defines "HZ_RELEASE"
    		buildoptions "/MD"
    		optimize "On"
    
    	filter "configurations:Dist"
    		defines "HZ_DIST"
    		buildoptions "/MD"
    		optimize "On"
    

    重新编译后,Hazel的运行库依旧是MTd,但是添加了命令行/MDd 会覆盖/MTd

    Hazel游戏引擎(011)窗口抽象和GLFW创建窗口,Hazel游戏引擎,游戏引擎,glfw,窗口,git

    • 后面017节才发现为什么Hazel依旧为MTD,需要添加了命令行/MDd 才会覆盖/MTd

      由于premake设置了staticruntime为on

      -- On:代码生成的运行库选项是MTD,静态链接MSVCRT.lib库;
      -- Off:代码生成的运行库选项是MDD,动态链接MSVCRT.dll库;打包后的exe放到另一台电脑上若无这个dll会报错
      staticruntime "On"	
      

      只需staticruntime 为off即可文章来源地址https://www.toymoban.com/news/detail-636320.html

到了这里,关于Hazel游戏引擎(011)窗口抽象和GLFW创建窗口的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Hazel游戏引擎(008-009)事件系统

    文中若有代码、术语等错误,欢迎指正 此节目的 理清顺序和设计才能更好的编码 设计如图 声明 图是我自己缝合的,流程与大意没错,但是不符合软件工程对应图的规范。 大致是根据视频草稿图与大意画的 使用时序图简单表示 使用类图详细表示 在软件工程中,类图没有消

    2024年02月01日
    浏览(28)
  • Qt配置glfw库(Windows)

    glfw官网下载:https://www.glfw.org/download.html 下载之后,解压如下: 创建一个Qt工程(我创建的是命令行程序),如下所示: 在工程路径下新建一个文件夹 glfw 将下载的glfw库文件夹中的include、lib-mingw-w64复制到新建的 glfw 文件夹中,如下所示: 切换到工程文件(*.pro),鼠标右键

    2024年02月03日
    浏览(16)
  • Visual Studio 2022 搭建GLFW OpenGL开发环境

    最近工作需要 需要写一个全景的视频播放器 网上搜了下大概解决方案是 ffmpeg+opengl b站有很多视频  按照视频 搭建了OpenGL的开发环境 先去GLFW的网站下载 windows平台的库文件 为什么使用GLFW  因为GLFW是跨平台的   我下的是64位版本解压后有目录如下    包含了动态库和静态库

    2024年02月03日
    浏览(40)
  • Ubuntu20.04搭建OpenGL环境(glfw+glad)

    本文在VMware安装Ubuntu20.04桌面版的环境下搭建OpenGL, 按照本文搭建完成后可以执行LearnOpenGL网站上的demo 。 关于VMware可自行到VMware Workstation Pro | CN下载 关于Ubuntu20.04桌面版可自行到官网或Index of /ubuntu-releases/20.04.6/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror下载 这里窗口

    2024年02月12日
    浏览(47)
  • Visual studio2022 利用glfw+glad配置OpenGL环境

    链接:https://visualstudio.microsoft.com/zh-hans/ 搜索时最常见的是glut,但是了解到glut最后更新时间是1998年,比我还小两岁…目前没人维护了,也被弃用了… 目前,最常用的就是freeglut+glew和glfw+glad两种组合。据说前者比较经典,后者比较新潮,所以作为潮人,我选择了后者(具体可

    2024年02月04日
    浏览(52)
  • 【GIS开发】基于C++绘制三维数字地球Earth(OpenGL、glfw、glut)

    🍺三维数字地球系列相关文章如下🍺: 1 【小沐学GIS】基于C++绘制三维数字地球Earth(OpenGL、glfw、glut)第一期 2 【小沐学GIS】基于C++绘制三维数字地球Earth(OpenGL、glfw、glut)第二期 3 【小沐学GIS】基于OpenSceneGraph(OSG)绘制三维数字地球Earth 4 【小沐学GIS】基于C++绘制太阳系

    2023年04月17日
    浏览(50)
  • OpenGL —— 2.5、绘制第一个三角形(附源码,glfw+glad)(更新:纹理贴图)

    源码效果   C++源码        纹理图片            需下载stb_image.h这个解码图片的库,该库只有一个头文件。         具体代码:            vertexShader.glsl              fragmentShader.glsl              main.c      

    2024年02月11日
    浏览(37)
  • 【已解决】GLFW error #65544: X11: Failed to open display :0 连接远程服务器并开启gui界面失败

    本地计算机通过ssh连接服务器运行gui界面的时候报错,但是直接在服务器上跑gui代码没有任何问题。 原因其实在于你本地没有设置显示gui的显示屏,如果之前一直ssh开gui没问题,用的好好地,突然不行了直接跳到第二步,否则从第一步开始看。 Step1. 服务器端ssh设置 修改完后

    2024年02月04日
    浏览(53)
  • Hazel 引擎学习笔记

    https://youtu.be/etdSXlVjXss 我感觉自己照抄视频中的脚本还是有点慢了 因为你不知道他什么时候加了什么东西,或者自己照抄就很容易抄错 我觉得最好的方法就是自己快速过一遍他的视频,知道他大概的思路是怎么样的,然后自己再拉取那个 commit 的代码,用 diff 方便看他具体修

    2024年02月13日
    浏览(39)
  • 跟着cherno手搓游戏引擎【10】使用glm窗口特性

    创建: ImGuiBuild.cpp:引入ImGui Layer.h:加入GuiRender方法,每次渲染Gui都会调用 ImGuiLayer.h:删除冗余部分,仅留下加入,删除,和Render方法,添加Begine和End,用于每次刷新UI的配置和删除UI。 ImGuiLayer.cpp:删除原来的Update,把配置、绘制UI的代码、渲染分离 LayerStack.h:修改m_LayerInsertI

    2024年01月25日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包