IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> Cherno_游戏引擎系列教程(3):44~73 -> 正文阅读

[游戏开发]Cherno_游戏引擎系列教程(3):44~73

44. Shader Asset Files Game Engine series

这里我们会想从一个 shader file 来编译一个 shader。

我们希望最终的 api 可以设计成这样:

Shader::Create("assets/shaders/Texture.glsl");

当然未来最好的是可以把 glsl 转换为我们自己的 shader language

45. Shader Library Game Engine series

当有一些示例shader比如pbr shader之类的,我们就可以存在引擎的 Shader Library 中。本质上就是用一个哈希表去存:

std::unordered_map<std::string, Ref<Shader>> m_Shaders;

46. How to Build a 2D Renderer Game Engine series

对于2D的情况,最简单的就是所有的都看成一个 quad

比如画一个圆,最好的方式不是画边,而是简单地渲染一个 texture(带alpha通道的那种)。

为了避免混淆,我们命名为 HEngine::Renderer2D 这样的:
在这里插入图片描述

可以参考:
https://blog.csdn.net/alexhu2010q/article/details/122871987

47. Camera Controllers Game Engine series

48. Resizing Game Engine series

对于 resize,我们不只是告诉window,我们还需要告诉我们的图形api,我们的渲染区域改变了。

因此这里我们需要 glviewport

当 window minimize的时候 width 和 height 是0,可以打个断点调试一下。所以我们还需要进行一些边界处理。

我们可以在 OnEvent 函数中自己定制想要的缩放效果:

void OnEvent(HEngine::Event& e) override
{
	m_CameraController.OnEvent(e);

	if (e.GetEventType() == HEngine::EventType::WindowResize)
	{
		auto& re = (HEngine::WindowResizeEvent&)e;

		//float zoom = (float)re.GetWidth() / 1280.0f;
		//m_CameraController.SetZoomLevel(zoom);
	}
}

49. Maintenance Game Engine series

确保你的所有configuration都能够build,所以这次维护修改升级我们还需要build一下release版本来试试。

50. Preparing for 2D Rendering Game Engine series

51. Starting our 2D Renderer Game Engine series

52. 2D Renderer Transforms Game Engine series

53. 2D Renderer Textures Game Engine series

54. Single Shader 2D Renderer Game Engine series

55. Intro to Profiling Game Engine series

55.5. Visual Profiling

目前的Profiling用ImGUI绘制出来了,如上图所示,这种很简陋,缺点有:

  • 只能看实时数据,无法看之前帧的数据
  • 没有Hierarchy信息,比如像Unity那种Profiler,可以看具体函数的Hierarchy的Profile信息
  • 没有搜索功能等

参考链接:
https://blog.csdn.net/alexhu2010q/article/details/122871987

为了方便预览和分析程序里想要分析的代码片段每帧所花的时间,这里选了一个很简单的方法,就是在Runtime把Profile信息写到一个JSON文件里,然后利用Chrome提供的Chrome Tracing工具(只要在谷歌浏览器里输入chrome://tracing即可打开它),来帮忙分析这个JSON文件。

实现写入JSON文件的类叫instrumentor,这个单词在英语里其实并不存在,它源自于单词instrumentation,本意是一套仪器、仪表,在CS里的意思是对程序性能、错误等方面的监测:

In the context of computer programming, instrumentation refers to the measure of a product’s performance, to diagnose errors, and to write trace information.[1] Instrumentation can be of two types: source instrumentation and binary instrumentation.

我们生成好 json 文件后,在谷歌浏览器中进入 chrome://tracing

随后我们 load 文件 HEngineProfile-Runtime.json 进来,就可以看到这样的画面:
在这里插入图片描述

注:每次我都是先 F5 运行,然后先关我们的窗口,再关闭我们的console,否则会json解析失败?暂不清楚原因。

56. Instrumentation Game Engine series

现在的Profiling系统,有个比较大的问题:

  • 它会不断的Profiling,然后写入到JSON文件里,每一帧都跑这个数据,这是不科学的,得到的文件可能会到几百兆,像Unity的Profiling系统,就提供了录制功能,而且它只会录制特定帧数的Profiling数据,就是那个不停滚动的Profiling窗口…

SP. Making a GAME in ONE HOUR using MY ENGINE

57. Improving our 2D Rendering API Game Engine series

58. How I Made a Game in an Hour Using Hazel

59. Hazel 2020

60. Batch Rendering

61. Batch Rendering Textures (+ Debugging!)

62. Drawing Rotated Quads

63. Renderer Stats and Batch Improvements

这一节写了一些记录效率的,比如 draw call 有多少个之类的,通过 imgui 渲染出来。

64. Testing Hazel’s Performance!

65. Let’s Make Something in Hazel!

这一节上了一个 particle system,用的 cherno 这里的代码:

https://github.com/TheCherno/OneHourParticleSystem

其实每个 particle 就是一个 quad,我们只不过是写了一个 particle system 类来定义它每个时刻的位置、大小、旋转和颜色罢了。给一个生命周期比如一秒钟,然后大小依次递减即可,借助之前的 Timestep 就很容易做到。

最后通过我们的粒子池和index来发射粒子:

std::vector<Particle> m_ParticlePool;
uint32_t m_PoolIndex;
for (int i = 0; i < 50; i++)
	m_ParticleSystem.Emit(m_Particle);
void ParticleSystem::Emit(const ParticleProps& particleProps)
{
	Particle& particle = m_ParticlePool[m_PoolIndex];
	particle.Active = true;
	particle.Position = particleProps.Position;
	particle.Rotation = Random::Float() * 2.0f * glm::pi<float>();

	// Velocity
	particle.Velocity = particleProps.Velocity;
	particle.Velocity.x += particleProps.VelocityVariation.x * (Random::Float() - 0.5f);
	particle.Velocity.y += particleProps.VelocityVariation.y * (Random::Float() - 0.5f);

	// Color
	particle.ColorBegin = particleProps.ColorBegin;
	particle.ColorEnd = particleProps.ColorEnd;

	particle.LifeTime = particleProps.LifeTime;
	particle.LifeRemaining = particleProps.LifeTime;
	particle.SizeBegin = particleProps.SizeBegin + particleProps.SizeVariation * (Random::Float() - 0.5f);
	particle.SizeEnd = particleProps.SizeEnd;

	m_PoolIndex = --m_PoolIndex % m_ParticlePool.size();
}

66. How Sprite Sheets/Texture Atlases Work

资源:https://kenney.nl/assets/rpg-base

因为至多就 32 个slot,所以比如有 128 张 texture,那么至少就要 4 个 draw call

cherno 表示draw call不是问题,主要是 texture 每次都需要 bind 和 rebind 。因此打图集效率是很高的。

所以似乎 spritesheet 就是 texture atlas?

67. SubTextures - Creating a Sprite Sheet API

68. Creating a Map of Tiles

69. Next Steps + Dockspace Game Engine series

我们想做的是搞个 framebuffer,绘制到一张 texture 上,然后就可以用 imgui 的 render image 去绘制了。

比如:

uint32_t textureID = m_CheckerboardTexture->GetRendererID();
ImGui::Image((void*)textureID, ImVec2{ 256.0, 256.0 });

具体工作要在下一节再做了。

70. Framebuffers Game Engine series

在这里插入图片描述
这里的 bool SwapChainTarget 就是是否是直接渲染到屏幕的意思(是不是GPU端的framebuffer?)

但是这一节发现了一个怪事,就是相机的上下颠倒了,YouTube评论区给出了原因:

If anyone else is having their images rendered upside down in ImGui, add ImVec2{ 0,1 }, ImVec2{1,0} to the parameters of ImGui::Image to change the UV’s of the image. For some reason, ImGui flips them by default

原来是 imgui 的自动处理,我们更改需要在后面加上两个参数 ImVec2{ 0, 1 }, ImVec2{ 1, 0 }:

ImGui::Image((void*)textureID, ImVec2{ 1280, 720 }, ImVec2{ 0, 1 }, ImVec2{ 1, 0 });

71. Making a New C++ Project in Hazel Game Engine series

72. Scene Viewport Game Engine series

73. Code Review + ImGui Layer Events Game Engine series

这里注意几点:

  1. 我们的图形api按理应该可以在运行时选择:vulkan or dx or opengl or metal?
  2. 我们的 Input 应该是编译时根据平台来选择的。Android or Windows or xxx,不可能在安卓设备上运行时选择 WindowsInput 吧!

所以参考cherno后续的代码:
https://github.com/TheCherno/Hazel/blob/master/Hazel/src/Hazel/Core/Input.h

不如直接在 HEngine/HEngine/src/Platform/Windows/WindowsInput.cpp 中直接包含头文件 #include "HEngine/Core/Input.h",而不需要 WindowsInput.h

对于 ImGui Layer Events,我们先做如下测试:

我们通过这两行来测试:

HE_CORE_WARN("Focused: {0}", ImGui::IsWindowFocused());
HE_CORE_WARN("Hovered: {1}", ImGui::IsWindowHovered());

发现 hovered 是看鼠标有没有移动到那个窗口,而focesed就是看是不是选中了那个窗口了,很容易测试。

于是这就可以成为我们是否接收事件的条件判断。

注意我们的 Application 的构造函数中就会 PushOverlay(m_ImGuiLayer)
在这里插入图片描述
而我们对事件的检测是从后向前的:

void Application::OnEvent(Event& e)
{
	EventDispatcher dispatcher(e);
	dispatcher.Dispatch<WindowCloseEvent>(HE_BIND_EVENT_FN(Application::OnWindowClose));
	dispatcher.Dispatch<WindowResizeEvent>(HE_BIND_EVENT_FN(Application::OnWindowResize));

	for (auto it = m_LayerStack.rbegin(); it != m_LayerStack.rend(); ++it)
	{
		if (e.Handled)
			break;
		(*it)->OnEvent(e);
	}
}

我们目前一共就两个层:一个是正常push进去的EditorLayer,一个是构造函数里头默认就会push进去的ImGuiLayer,且是overlay,也就是默认在最后面,因此每次事件都是先 imgui 判断一次,再传播到前面的层。

于是我们在 ImGuiLayer 中新增了一些方法判断:

void BlockEvents(bool block) { m_BlockEvents = block; }
void ImGuiLayer::OnEvent(Event& e)
{
    if (m_BlockEvents)
    {
        ImGuiIO& io = ImGui::GetIO();
        e.Handled |= e.IsInCategory(EventCategoryMouse) & io.WantCaptureMouse;
        e.Handled |= e.IsInCategory(EventCategoryKeyboard) & io.WantCaptureKeyboard;
    }
}

这样我们就可以通过一些设置来判断是否要传播到前面的层了!

比如:

EditorLayer.cpp 中:

m_ViewportFocused = ImGui::IsWindowFocused();
m_ViewportHovered = ImGui::IsWindowHovered();
Application::Get().GetImGuiLayer()->BlockEvents(!m_ViewportFocused || !m_ViewportHovered);
  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2022-04-01 23:44:41  更:2022-04-01 23:46:37 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/16 18:55:03-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码