《GAMES104-现代游戏引擎》学习笔记
分层
- 资源层
- 功能层
- 平台层
- 工具层
游戏世界构成
- game object
- component
- tick
- events
渲染
渲染方程的三点挑战
- 如何拿到所有光源
- 计算完毕后,反射出去的光会变成新的光源
- 2会把1变的更麻烦
BRDF
主流应用
PBR Specular Glossiness(SG模型)
- diffuse:三个通道控制rgb
- specular:三个通道控制菲涅尔。在不同金属中,对不同颜色的菲涅尔是不一样的
- glossiness:单通道,控制粗糙度
优点:
- 所有参数都可以由艺术家控制,且可被理解,可以做到像素级的控制
缺点:
- 过于自由,如果参数调错会很影响结果
PBR Metallic Roughness(MR模型)
- base color:rgb,设置就不用动了
- roughness:单通道,粗糙度
- metellic:单通道,金属度(金属流)。如果金属度低,不会进菲涅尔。
shadow
cascade shadow(csm级联阴影)
类似lod,远处的shadow精度变低
软阴影处理
- PCF(Percentage Closer Filter):用滤波的方法处理
- PCSS(Percentage Closer Soft Shadow):PCF的实现应用
- Variance Soft Shadow Map
AAA实战使用技术
- LightMap + LightProbe
- PBR + IBL
- Cascade shadow + VSSM
优点:
- 控制偏差不会太大
缺点:
- 非金属往金属过渡时,可能会出现小小的白边
地形
LOD技术
- adpative tessellation
- triangulated irregular network(TIN)
- 四叉树
3d采样构建技术
- marching cubes
地形材质过渡
- advanced texture splatting
主流方法
- virtual texture mipmap
植被渲染
- speed tree
- decorator rendering(装饰物渲染)
- decals (贴花)
大气
- radiative transfer equation(RTE/RTF)
- volume rendering equation(VRE)
散射
- precomputed atmospheric scattering
把大气的散射现象,全部转化为表格
噪声
- perlin noise:棉花絮
- worley noise:泡泡絮/细胞壁
渲染处理
环境光遮蔽(Ambient Occlusion)
表示对环境漫反射光的遮挡,和shadow区分,shadow是对目标光源光的遮挡
- screen space ambient occlusion
- SSAO+:法线方向半球面随机采样
- horizon-based ambient occlusion(HBAO)
- ground truth-based ambient occlusion(GTAO)
- ray-tracing ambient occlusion(RTAO)
雾效
- 高度指数雾:低于某个高度用雾效的最大值,高于的话指数递减
- voxel-based volumetric fog(体素化雾效)
灰度图参数
L = 0.299R + 0.587G + 0.114B
抗锯齿算法
- SSAA:四倍
- MSAA:四倍+优化
- FXAA:先找出边界,然后对边界单独处理
- TAA
Color Grading
HDR转换到LDR的方法
render pipeline
- G-Buffer
- depth
- normal
- albedo
- roughness
- V-Buffer (visibility buffer)
- depth
- primitiveID
- barycentrics
前向渲染
- shadowPass
- shading
- post-process
延迟渲染
- 先全部渲染一遍,G-Buffer
- 再处理光源,shading
tile-based rendering
切成一个个小块,可以把光源切割处理
cluster-based rendering
棱锥切割
动画
- 3d蒙皮动画
- 2d蒙皮动画(spine)
- 基于物理动画
- 布娃娃系统
- IK
- 衣料
蒙皮动画
皮肤上的每个点,对应各个joint的权重,根据joint的变化,算出skin的点的位置
- joint:关节
- bone:关节构建的刚体
- root joint:根节点(非传统意义的根节点),用来表示物体的位置、高度信息等
- pelvis joint:模型根节点,从这个节点衍生出其他节点,传统意义上是根节点
- bind point:绑定节点(6Dofs层面上的绑定),用于不同模型组合播放动画时保持一致的节点
动画混合
动画文件产出要求:必须循环,且完成一次循环,比如左脚迈起到左脚落下
混合帧:将两个动画归一化,然后找到对应位置的数据
- lerp blending:全身线性
- mask blending:半身线性(比如上半身)
- additive blending:只存变化量,在其他blending之后,在变化的东西加个差分
IK
- CCD
- FABRIK
- Jacobian Matrix:雅克比矩阵,长链条ik
表情动画
morph target animation
物理
物理形状
- spheres: 球形
- capsules: 胶囊
- boxes
- convex meshes: 凸包
- triangle meshes: 三角网格,用于静态建筑
- height fields: 用于地形
碰撞检测
- BVH
- Sort and Sweep
- GJK(games104 10 1:31:19)
- 闵可夫斯基差:A图形与(B图形中心对称图形),形成的组合图形,如果包含中心点的话,则两图形是相交的
- SAT:只要找到一个轴,两个凸包的投影可以分开,说明两物体不相交
Raycast
目标
- 射线所有的交点
- 最近的交点
- 是否有交点
角色控制器
角色是非物理模型,默认脚底的摩擦力无限大
- 双层box,里层用于碰撞判断,外层用于行走判断,比如防止角色离墙太近
- auto step(上台阶):每次前进时,code里把角色抬一下
- 上坡角度限时:大于某个角度时,会往下滑
- 角色高度变化时的处理
- 移动平台上的特殊处理:和平台绑定
衣料模拟
弹簧质点模型:用矩阵形状的弹簧模拟
需要计算的力:
- 重力
- 风力
- 运动时的空气阻力
- 周围弹簧的拉力(拉力需要衰减)
算法(前沿):
- PBD
- XPBD
布料自穿插
- 增加检测密度/增加衣服厚度
- SDF,在布料背面加有向距离场,穿过去的东西会弹回去
particle
形态
- billboard(广告牌):始终面向相机
- mesh:3d模型特效
- ribbon:拖尾特效
gameplay
event quene
环形队列:环形指针控制事件位置,避免频繁申请空间
AI——寻路
建模方式
- grid:用几何图形表达空间(比如六边形地图)
- way point:基本的图
- NavMesh(常用):用几何体表达空间
event分支管理:
- net event queue
- battle event queue
- animation event queue
ai决策算法
自上而下:
- 有限状态机
- 行为树
自下而上(目标导向):
- Hierarchical Tasks Network(层次任务网络)
- goal oriented action planning(目标导向行为规划)
- monte carlo tree search(蒙特卡洛树搜索)
- deep learning
HTN
primitive task:
- percondition
- action
- effect
compound task(复合任务):
- percondition
- method(task list)
网络同步
- 快照同步
- 帧同步
- 状态同步
快照同步
服务端模拟世界,客户端上传操作+同步服务端数据
帧同步
客户端上传操作/指令,服务端按照统一时间间隔接收数据,再统一时间间隔下发个所有客户端
优点:
- 公平
- 有效利用客户端算力,以及解放服务端压力
- 方便做游戏录屏
缺点:
- 保持同步很难(如果有一个人,其他人都要等)
- 防作弊要研究(比如全图挂)
- 长时间断线重连问题
bucket帧同步
定时收集数据 + 下发操作。网络不好的人操作不收集,保证网络好的玩家的游戏体验
断线处理——快照追帧
客户端每隔一定时间,保存一次快照(联网状态下)
如果断网后恢复了,获取网络最新快照和数据,客户端去快进的模拟,直到追上最新帧
比如,客户端9400f断网了,重连后服务端返回10000f,那客户端就去获取这600f的数据在本地快速模拟到10000f,而不用从0f开始
王者荣耀使用的方法
根据需要,服务端也可以保存快照。这样如果掉线时间太长的话,客户端可以直接同步服务端快照,而且服务端快照可以支持观战模式和回放功能。
tracing
1、保存数据快照
2、保存校验和(关键数据校验和/全量校验和)
debugging
1、比较不同客户端的校验和
2、客户端上传50帧的日志/快照
3、debug
状态同步
客户端上传和接收自己相关的状态,服务端总和这些状态后,整合模拟出完整的世界
流程:玩家1操作 -> 发给server -> server接收后验证+发给所有客户端 -> 其他客户端玩家1操作
预测和验证
因为变量要上传服务器后,才能操作,所以所有操作理论都有延迟,为了避免这个延迟,需要做预测和验证。
即上传服务端的同时,本地也模拟,模拟后的结果再和服务端结果做验证。
OW策略:RTT(延迟)=160ms, Half RTT = 80ms, frame = 16ms, 客户端会预测后面96ms的动作
高频提交
比如移动操作,客户端会存个buffer记录过去所有操作,当一段时间内检测不到替他输入时,会自动推一次。
浮点数误差
1、定点数引擎(研究方向)
2、随机数一致
内/外插值
内插值
优点:表现非常平滑
缺点:增加了额外的延迟
外插值
优点:不会增加平滑
缺点:碰撞检测会被延后
命中判定
服务端存储一段时间的快照,当玩家射击的时候,从快照中找到对应时间的数据(比如延迟是100ms,服务器就把时钟往前播100ms,找到那个时间点的数据),进行判断。
- 优势方:当人从掩体中突然冲出时,对方因为延迟还没看到我,而我能看到对方,会有先手优势
- 劣势方:当人进掩体时,我方视角是我已经进掩体了,但是对方视角我还在外面,如果这个时候对方打死了我,我方视角就是进掩体后被打死了
MMO架构
gateway
网关,内外网隔绝。主要做合法性检测,功能:加密、压缩、防攻击
网络延迟hack
- 加前摇,能给网络同步争取延迟同步时间
- 特效和结算分开,特效在玩家操作后立刻播放增加打击感
tgrading system
交易系统。要求高安全性、原子性且可回滚。
AOI(Area of Interest)
网络同步中,用于带宽优化,只同步自己周围的信息
方式:
- Direct Range Query,以自己为圆心固定半径的圆
- Spatial Grid,划格子,比如100*100米都是在格子里,然后同步时,发送add/leave协议同步
- Orthogonal Linked List,十字链表法,沿x和y轴找到固定范围内的集合,取交集更新
反作弊
内存值修改
原理:修改具体数据,比如ce、八门
- 敏感数据的值套个壳,即每次get/set新开辟一块内存
- 数据混淆
修改本地文件数据
- hash值校验,如果发现不对就踢下线
网络包截获
- 加密,使用非对称加密
软件注入
原理:设置一个钩子,调用引擎代码
- 扫描包体签名/扫描可疑服务/扫描可疑进程,检查内存中的游戏有没有被人改过,知名软件:VAC,easy
AI作弊(目前前沿)
原理:直接AI图像识别,然后注入鼠标操作
- 大数据分析行为模式,校验玩家操作是否特别离谱
编程架构
编程范式
oop的问题:
- 对象选择谁?比如战斗中,战斗代码是写在攻击者,还是被攻击者里?需要项目沟通统一
- 继承树深不见底,找一个方法麻烦
- 基类非常冗杂。大系统的基类(比如UE的Actor)东西非常多,很多东西是我当前不需要的
- 最大的问题:内存分配不连续。因为是面向对象,对象大概率不会一起分配空间,加上继承中的虚函数,各种指针和映射会进一步导致内存离散
- 测试不方便。改了基类后,所有子类都要测试。而且为了测这一个方法,我需要把整个对象都找环境构建起来
性能敏感编程
- 尽量不要多线程访问同一数据,数据一致性会导致多余的内存写入
- if-else分开处理。比如
for + if-else
,可以改成for + if
+for + else
的方式,避免不同分支增加内存读取时间 - AOS to SOA。把数据尽可能放在一起,而不是分散在对象里,确保遍历的时候,不是跳跃遍历的
// AOS
struct Particle {
Vector3 position;
Vector3 velocity;
Color color;
float age;
} Particle[N];
// SOA
struct Particles {
Vector3 position[N];
Vector3 velocity[N];
Color color[N];
float age[N];
} Particles;
unity DOTS
Data Oriented Tech Stack
三大板块:
- ECS
- C# Job System
- Burst Compiler
*unreal: lumen
基本思路:每一帧的渲染,用当前帧的渲染 + 上一帧渲染cache,叠加后产生
各种GI思路的集大成者
*unreal:nanite
实现曲面简化,用来做LOD的
优点1:简化后的曲面不会出现边对不齐的情况(即出现空洞)
优点2:GPU驱动的几何管线
其他名词记录
- 球谐函数(Spherical Harmonics)
- metahuman:一个前沿的表情系统
- CCD:continuous collision detection,连续运动碰撞检测
- voronoi算法:破坏模拟算法,算出破坏的各个区域
- DCC: digital content creator,第三方数据资产工具
- JIT:边运行边编译
- NTP算法:时钟同步算法
- DDGI、SSGI
- hardware ray tracing
其他记录
- ios平台不让热更。为了防止审核后注入其他未过审内容,所有版本都要提交ios审核
- 汇编重排。有的汇编正式版会不按照代码行数执行,做多线程assert时要有这个常识
相关链接
- vulkan-tutorial.com
- www.vulkan.org/learn