UE 入坑系列(六):多线程
参考:
https://blog.csdn.net/j756915370/article/details/122752719
https://zhuanlan.zhihu.com/p/38881269
https://zhuanlan.zhihu.com/p/396824188
预备知识
进程 & 线程 & 异步
线程是调度的基本单位,而进程则是资源拥有的基本单位。多线程是实现异步的一种方式
进程
在多道程序同时运行的背景下,进程之间需要共享系统资源,因此会导致各程序在执行过程中出现相互制约的关系,程序的执行会表现出间断性的特征。这些特征都是在程序的执行过程中发生的,是动态的过程,而传统的程序本身是一组指令的集合,是一个静态的概念,无法描述程序在内存中的执行情况,即我们无法从程序的字面上看出它何时执行、何时停顿,也无法看出它与其他执行程序的关系,因此,程序这个静态概念已不能如实反映程序并发执行过程的特征。为了深刻描述程序动态执行过程的性质乃至更好地支持和管理多道程序的并发执行,人们引入了进程的概念。
进程就是 process,它是一个程序的运行实例。当我 ...
UE 入坑系列(五):Actor 的生命周期
前言
本文整理自 UE 官方文档:Actor 生命周期。
UE 中的 Actor 主要有三种加载方式:Load from Disk、Play in Editor、SpawnActor;无论 Actor 的创建方式如何,它们的销毁路径均相同。
生命周期详解
Load from Disk
已位于关卡中的 Actor 使用此路径,如 LoadMap 发生时、或 AddToWorld(从流关卡或子关卡)被调用时。
包/关卡中的 Actor 从磁盘中进行加载。
PostLoad - 在序列化 Actor 从磁盘加载完成后被调用。在此处可执行自定义版本化和修复操作。PostLoad 与 PostActorCreated 互斥。
InitializeActorsForPlay
为未初始化的 Actor 执行 RouteActorInitialize(包含无缝行程携带)
PreInitializeComponents - 在 Actor 的组件上调用 InitializeComponent 之前进行调用。
InitializeComponent - Actor 上定义的每个组 ...
图形学补完计划(四):光照模型-2
参考
https://sites.cs.ucsb.edu/~lingqi/teaching/games101.html
https://zhuanlan.zhihu.com/p/370903314
全局光照模型
上一节主要分析了以 Phong 模型为主的局部光照模型,这些光照模型都是经验性的,不真实的;本节要介绍的全局光照模型就恰好相反。
全局光照模型是基于光学物理原理的,光照强度的计算依赖于光能在现实世界中的传播情况,考虑光线与整个场景中各物体表面及物体表面间的相互影响,是绘制真实感图形的理论依据;具体而言,包括 路径跟踪(path tracing)、双向路径跟踪(bidirectional path tracing)、辐射度方法(radiosity method)等。
与局部光照模型相比,全局光照模型需要相当大的计算量 ,但同时也能取得非常逼真的真实效果。由于计算机硬件的限制,全局光照模型一般在离线渲染领域如电影中应用,随着GPU硬件的发展和算法的改进 ,采用全局照模型的实时渲染逐渐成为研究的热点。
Ray Tracing (Whitted-Style)
光线跟踪算法通过模 ...
C++ 补完计划(三):泛型与多态
前言
本文将会是一个大杂烩,打算将 C++ 学习以来关于泛型以及多态的各种内容全部塞在这里。可能会没有什么条理性,但反正也没人看我的博客,那干脆就随心所欲一点咯。
今天的 C++ 已经是个多重泛型编程语言(multiparadigm programming lauguage),一个同时支持过程形式(procedural)、面向对象形式(object-oriented)、函数形式(functional)、范型形式(generic)、元编程形式(metaprogramming)的语言。
这些能力和弹性使C++成为一个无可匹敌的工具,但也可能引发使用者的某些迷惑,比如多态。在这几种编程泛型中,面向对象编程、范型编程以及很新的元编程形式都支持多态的概念,但又有所不同。 C++支持多种形式的多态,从表现的形式来看,有虚函数、模板、重载等,从绑定时间来看,可以分成静态多态和动态多态,也称为编译期多态和运行期多态。
编译时多态也称为为静态联编,通过重载和模板来实现,运行时多态称为动态联编,通过继承和虚函数来实现。
本文即讲述这其中的异同。注意泛型编程和元编程通常都是以模板形式实现的,因此在本文中 ...
图形学补完计划(四):光照模型-1
参考:
https://sites.cs.ucsb.edu/~lingqi/teaching/games101.html
https://zhuanlan.zhihu.com/p/49474631
光照模型
当光照射到物体表面时,物体对光会发生反射、透射、吸收、衍射、折射、和干涉,其中被物体吸收的部分转化为热,反射、透射的光进入人的视觉系统,使我们能看见物体。为模拟这一现象,我们建立一些数学模型来替代复杂的物理模型,这些模型就称为明暗效应模型或者光照模型。
光照模型可分为局部光照模型与全局光照模型,下面将按种类进行分析。
局部光照模型
在图形学中,仅处理光源直接照射物体表面的光照明模型被称为局部光照明模型。
局部光照模型是一种比较简单的光照模型,它是与光栅化渲染算法相适应的,光栅化算法一次只考虑一个像素的光照强度,因此局部光照模型不能计算某像素受其他像素影响的光照强度部分。也就是说,局部光照模型只对物体进行直接光照的计算,而不考虑其他的间接影响,常见的局部光照模型有以下几种。
Lambert光照模型
Lambert光照模型主要是用来模拟粗糙物体表面的漫反射光照现象,是一种经验模 ...
图形学补完计划(三):Antialiasing
参考:
https://sites.cs.ucsb.edu/~lingqi/teaching/games101.html
https://blog.csdn.net/qq_51776686/article/details/122462161
https://www.zhihu.com/question/20236638/answer/44821615
https://zhuanlan.zhihu.com/p/431384101
https://zhuanlan.zhihu.com/p/366494818
光栅化所带来的问题
光栅化是将图形转换成像素图像的过程,由于三维空间中的物体都是连续的,而屏幕上的像素则是一个离散的二维数组,判断一个点到底没有被某个像素覆盖的时候单纯是一个“有”或者“没有"问题,丢失了连续性的信息,因此会带来很多问题。
学过 dsp 的同学都知道,离散就意味着采样率有限,因此一定存在一个最大的采样率;当要采样的信号频率大于这个值时,就会出现各种问题。
常见的问题有:锯齿、摩尔纹、车轮效应等。
转动过快的车轮会让人觉得在往反方向旋转
本节主 ...
图形学补完计划(二):Rendering Pipeline
参考:
细说图形学渲染管线
https://zhuanlan.zhihu.com/p/223033896
图形渲染管线
图形渲染管线是实时渲染的核心组件。图形渲染管线实际上指的是一堆原始图形数据途经一个输送管道,期间经过各种变化处理最终出现在屏幕的过程。渲染管线是实时渲染的重要工具,实时渲染离不开渲染管线。
图形渲染管线主要包括两个功能:一是将物体3D坐标转变为屏幕空间2D坐标,二是为屏幕每个像素点进行着色。渲染管线的一般流程如下图所示。分别是:顶点数据的输入、顶点着色器、曲面细分过程、几何着色器、图元组装、裁剪剔除、光栅化、片段着色器以及混合测试。
渲染管线的一个特点就是每个阶段都会把前一个阶段的输出作为该阶段的输入。例如,片段着色器会将光栅化后的片段(以及片段的数据块)作为输入进行光照计算。除了图元组装和光栅化几个阶段是由硬件自动完成之外,管线的其他阶段管线都是可编程/可配置的。其中顶点着色器、曲面细分相关着色器、几何着色器和片段着色器是可编程的阶段,而混合测试是可高度配置的阶段。管线的可编程/可配置是渲染管理的另一个特点。因为早期的渲染管线采用的是立即渲染模式(Imme ...
图形学补完计划(一):MVP矩阵
参考:
https://sites.cs.ucsb.edu/~lingqi/teaching/games101.html
http://www.songho.ca/math/homogeneous/homogeneous.html
https://zhuanlan.zhihu.com/p/261097735
https://zhuanlan.zhihu.com/p/261097735
https://zhuanlan.zhihu.com/p/65969162
https://zhuanlan.zhihu.com/p/223033896
齐次坐标
齐次坐标的引入
问题:两条平行线可以相交于一点
在欧氏几何空间,同一平面的两条平行线不能相交,这是我们都熟悉的一种场景。然而,在透视空间里面,两条平行线可以相交,例如:火车轨道随着我们的视线越来越窄,最后两条平行线在无穷远处交于一点。
欧氏空间(或者笛卡尔空间)描述2D/3D几何非常适合,但是这种方法却不适合处理透视空间的问题(实际上,欧氏几何是透视几何的一个子集合),2维笛卡尔坐标可以表示为(x,y)。
如果一个点在无穷远处,这个 ...
C++ 补完计划(二):类的大小
本文转载自 C++类大小详尽讲解
C++ 类的大小
与类大小有关的因素:普通成员变量,虚函数,继承(单一继承,多重继承,重复继承,虚拟继承); 与类大小无关的因素:静态成员变量,静态成员函数及普通成员函数。
内存对齐
由于在分析类的大小时会经常涉及到内存对齐的概念,因此这里先总结一下相关的知识点。
内存对齐的原因: 关键在于CPU存取数据的效率问题。为了提高效率,计算机从内存中取数据是按照一个固定长度的。比如在32位机上,CPU每次都是取32bit数据的,也就是4字节;若不进行对齐,要取出两块地址中的数据,进行掩码和移位等操作,写入目标寄存器内存,效率很低。内存对齐一方面可以节省内存,一方面可以提升数据读取的速度;
内容: 内存对齐指的是C++结构体中的数据成员,其内存地址是否为其对齐字节大小的倍数。
对齐原则:
结构体变量的首地址能够被其最宽基本类型成员的对齐值所整除;
结构体内每一个成员的相对于起始地址的偏移量能够被该变量的大小整除;
结构体总体大小能够被最宽成员大小整除;如果不满足这些条件,编译器就会进行一个填充(padding)。
#pragma pac ...
GASDocumentation 案例项目分析(四)
前言
上一节我们分析了 FireGun 技能的整个流程,想必大家已经对 GAS 的使用有了一个初步的了解了,也大致知道了 GA、GE、GC 这些概念以及如何相互调用。本节就来继续分析另一个技能,Meteor。
Meteor
这个技能也是由纯蓝图创建的,技能整体流程包括目标确认、技能消耗、技能冷却、技能本体(陨石)、击中伤害与眩晕、击中效果(倒地)等组成,相比于 FireGun 要更为复杂。让我们逐一分析。
GA_Meteor_BP
这个蓝图就是 Meteor 技能的 GA 了,同样继承自 GDGameplayAbility。来分析蓝图中实现了哪些功能。
作为一个 GA,最重要的肯定还是重写 ActivateAbility。
首先还是从 ActorInfo 中获取了释放者的信息并且存在了 OwningHero 变量中。
其次是关于一些辅助信息显示的设置以及移动相机,在释放这种需要瞄准的技能时,移动相机是一个不错的做法,可以使视野开阔一些。
随后就是较为重要的瞄准部分了,这里先获取了 OwnerActor 即释放者的位置,再向前移动 200 个单位作为瞄准的初始位置。随后也启动了一个 ...
GASDocumentation 案例项目分析(三)
前言
上回说到,FireGun 这个类有一个名为 DamageGameplayEffect 的 GE 用于伤害计算以及击中特效播放,并且最终通过 Projectile->DamageEffectSpecHandle 的形式将该 GE 传递给了 Projectile。不难想象最终一定会由子弹本身的碰撞等事件来执行该 GE 以计算伤害(DamageExecCalc)及播放 GC。
12UPROPERTY(BlueprintReadOnly, EditAnywhere)TSubclassOf<UGameplayEffect> DamageGameplayEffect;
上一节主要分析了前者,即 GDDamageExecCalculation 的实现,本节就从 GameplayCue(GC)开始分析。
GameplayCue
首先来看一下文档中关于 GC 的解释:
GASDocumentation_Chinese:GameplayCue
GameplayCue(GC) 执行非游戏逻辑相关的功能, 像音效, 粒子效果, 镜头抖动等等。 GameplayCue 一般是可同步(除 ...
GASDocumentation 案例项目分析(二)
前言
上一节我们分析了 GASDocumentation 中与 GAS 相关的一些类的设计,本节就开始分析具体技能的实现。
技能的实现
查看 BP_HeroCharacter 蓝图,会发现在 Abilities.CharacterAbilities 下挂载了 7 个技能,上一节也分析过,CharacterAbilities 会在开局就全部赋予玩家,让我们一一分析。
Jump
项目中,为了演示非实例化的技能是如何使用的,把 Jump 也作为一个技能配置了,这个技能是 C++ 实现的。查看相应的类:
123456789101112131415161718192021222324252627282930313233343536/** * Makes the Character try to jump using the standard Character->Jump. * This is an example of a non-instanced ability. */UCLASS()class GASDOCUMENTATION_API UGDGA_CharacterJump : ...
GASDocumentation 案例项目分析(一)
前言
终于准备开新坑啦!终于使用了一次正常封面 在 STL 系列基本写完之后就摸了挺久的,其实这段时间也没有闲着,把 MP-TPS 的那个教程基本看完了,现在只剩第一部分的联机插件没有实现,准备最近开始继续更新 MP-TPS 系列,把这个项目的内容好好总结一下。
说回正题,目前的准备是将 GAS 结合到这个项目中,因此有必要好好学习一下 GAS 系统。但是总所周知,GAS 系统虽功能强大,学习曲线却异常陡峭,本来打算通过看 ActionRPG 项目的方式来学习 GAS,奈何这个项目本身也十分复杂。最后,在机缘巧合之下终于找到了这个项目———— GASDocumentation 以及某位好心人翻译的中文版 GASdocumentation_Chinese,感谢这些开源贡献者。
GASDocumentation 这个项目提供了十分完善的 GAS 文档,包含了 GAS 系统的各个模块的详细介绍,虽说没有细到分析源码的地步,但作为入门阶段的百科全书已经十分优秀了。除此之外,该项目还自带了一个同名的 UE4 工程,简单展示了 GAS 的使用方法,可以说是无比良心了。
相比于 ActionRPG, ...
从零开始的 STL 实现记录:Adapter-2
前言
上一节介绍了 iterator adapter 的内容,本节将介绍 adapter 家族的最后一部分成员:functor adapter。
functor adapter 是所有配接器中数量最庞大的一类,配接灵活程度非常高,通过它们之间的绑定、组合与修饰,几乎可以创造出各种表达式。
如同 container adapters 内藏了一个 container member 一样、或是像 reverse iterator (adapters)内藏了一个 iterator mermber 一样、或是像 stream iterator(adapters)内藏了一个 pointer to stream 一样,或是像 insert iterator (adapters)内藏了一个 pointer to container (并因而得以取其 iterator)一样,每一个 function adapters 也内藏了一个member object,其型别等同于它所要配接的对象(那个对象当然是一个“可配接的仿函数”,adaptable functor)。当 function adapter 有了 ...
从零开始的 STL 实现记录:Adapter-1
前言
配接器(adapters)在 STL 组件的灵活组合运用功能上,扮演着轴承、转换器的角色。Adapter 这个概念,事实上是一种设计模式。 《Design Patterns》一书中对 adapter 样式的定义如下:将一个类的接口转换为另一个类的接口,使原本因接口不兼容而不能合作的类,可以一起运作。
STL 中所提供的配接器,按照配接的对象可以分为三类:
改变 Container 接口的配接器:Containers Adapter
改变 Iterator 接口的配接器:Iterators Adapter
改变 Functor 接口的配接器:Functors Adapter
其中,container Adapter 已经在前面介绍 stack & queue 中介绍过,这两个容器都是通过修饰 deque 接口的方式呈现出另一种容器的样子,这里就不再介绍了。本节将重点介绍 Iterator Adapter 的内容。
Iterator Adapter
STL 提供了许多应用于迭代器身上的配接器,包括 insert iterators、reverse iterat ...