2022-10-23-GAMES104现代游戏引擎-Lecture22-GPU Driven Geometry Pipeline - Nanite

Lecture22 GPU Driven Geometry Pipeline - Nanite Research Background 传统渲染管线 CPU发起Draw Call,GPU准备State、进入漫长的Pipeline CPU、GPU不同步 存在大量的算力浪费 现代游戏Draw Call越来越复杂,已经成为现代渲染管线瓶颈 “曙光”: Compute Shader:不再需要在CPU、GPU之间来回传递数据,直接在GPU中执行通用计算 Draw-Indirect Graphics API:一次Draw Call绘制多个Mesh GPU Driven Render Pipeline 将场景完整load到显存中,完全由GPU处理:DrawPrimitive -> DrawScene @《刺客信条:大革命》 Mesh Cluster Rendering 将Mesh分成同样三角形数量的Cluster,便于交给GPU做裁剪等计算 不可见的Cluster不渲染;Culling流程: 尽可能裁剪掉不可见的三角形 将可见的三角形组成同一个Buffer GPU Driven Pipeline CPU端: 根据材质不同组合Instance 根据相机距离LoD 打包交给GPU做后续处理 GPU Instance Culling Instance Culling 将(64个)Cluster组成一个Chunk,再次Culling,以加速 GPU Cluster Culling Chunk -> Cluster -> Triangle 一步步裁剪,将视锥外、背面的全部裁剪 Index Buffer Compaction 将可见三角形的依次写入备用Index Buffer 三角形顶点顺序不统一时,可能导致前后帧三角形顶点顺序不一致,由于Z-Buffer精度有限,导致Z-Fighting问题 => 硬件Multi-Indirect Draw Call或可解决此问题 对高精度的Mesh效率非常高 Codec Triangle Visibility in Cube : Backface Culling 每个Cluster存储每个三角形对两个方向的可见性 利用这一数据快速做Backface Culling Occlusion Culling for Camera and Shadow 利用前一帧Z-Buffer的方法: 取当前帧的一部分(如300个)近处大Mesh作为可能的Occluder渲染Z-Buffer 将上一帧的深度重投影到当前帧,用于补充当前帧Z-Buffer空缺处 保守估计Culling Instance -> Chunk -> Cluster -> Triangle 问题:高速移动物体存在一定Artifact Two-Phase Occlusion Culling 快速绘制通过上一帧的Z-Buffer Test的Instance的当前帧Z-Buffer 再利用当前帧不完整的Z-Buffer,测试剩余所有Instance,选出可见者 更加准确 Fast Occlusion for Shadow Shadow中生成深度时对几何细节量敏感 对每个Cascade,将上一帧相机深度重投影至当前帧Shadow深度,并混合上一帧Shadow深度 只有摄影机可见区域内需要生成阴影:只对相机可见的Instance生成Shadow的Z-Buffer Visibility Buffer Forward Rendering:所有互相遮挡、透明的物体需要做重复计算 Deferred Shading:用G-Buffer存储可见Pixel的各种数据,只对G-Buffer做光照计算 G-Buffer的存储、IO开销大 复杂场景下,因为难以判断可见性,在生成G-Buffer时产生Over draw,多次绘制同一像素时开销大 Visibility Buffer: 第一遍渲染时,只在Buffer中存储: (Alpha masked bit, DrawID, PrimitiveID, MaterialID, …) 根据各种ID读取对应贴图,再做重心坐标插值着色 几乎没有Over Draw Cache Miss率低 Pipeline Visibility Buffer + Deferred Shading 一般来说,草丛等复杂细节情况可直接用Visibility Buffer渲染,主角等主要内容Gather到G-Buffer再渲染 注意点:MIPMAP采样时的插值平滑问题 Virtual Geometry - Nanite Overview Virtual Texture Idea:将场景中所有贴图加载到内存中开销非常大,能否只加载可见部分且LoD后精度的贴图 所有材质加载到同一张“大贴图”中,并对整个贴图做MIPMAP 预烘焙这张“大贴图”,并做MIPMAP 根据View区域动态加载所需的部分 Idea of Nanite Virtual Geometry like Virtual Texture 挑战:几何数据是非Uniform的、互相之间可能没有关联性、Mesh数据难以Filter(SDF、Voxel、Point Cloud可以Filter) Voxel ?...

2022-10-23-GAMES104现代游戏引擎-Lecture21-Dynamic Global Illumination and Lumen

Lecture21 Dynamic Global Illumination and Lumen Part I Dynamic Global Illumination Global Illumination - 略 Reflective Shadow Maps, RSM - 略 低分辨率间接光照加速: 计算低分辨率间接光照 对全分辨率图像的每个像素 获得周围四个低分辨率采样 通过法线和世界坐标位置判断,采样间差异过大时剔除 双线性插值 以全分辨率重新计算剔除的像素 Light Propagation Volumes, LPV - 略 Sparse Voxel Octree for Real-time Global Illumination, SVOGI 如何组织voxel的分布? 硬件保守光栅化:对很小的三角形,保证其至少有一个voxel 八叉树存储 Shading with Cone Tracing in Voxel Tree 着色点根据BRDF发射Diffuse和Specular的Cone 根据Cone尺寸查询树结构获取光照 - 非常适合Hierarchy结构存储的光照数据 NVIDIA的工作,GPU表达非常复杂 Voxelization Based Global Illumination, VXGI 更关注相机视锥内的区域、更关注近处的区域 Clipmap,voxel版的Mipmap 利用Clipmaps存储voxel数据 重心区域使用更高分辨率voxel 更适合Cone Tracing 建构简单、读取简单、GPU Friendly… Voxel Update:空间网格位置固定,只需要更新相机周围的Voxel Voxel具有Opacity(透明度),表征Voxel内有多少Surface可以阻挡光线,需要计算三个方向 对屏幕空间每个像素做Cone Tracing(Diffuse、Rough Specular、Fine Specular) 问题: 错误的遮挡关系,简单使用Opacity来表示 Light Leaking:遮挡物薄于Voxel时 Screen Space Global Illumination, SSGI Reuse screen space data <- Screen Space Reflection, SSR SSR:单根光线,构建反射 -> 多方向多根光线,构建GI 对Depth Buffer做Raymarching,Hierarchical Tracing 参考SSR笔记 Reuse近邻像素 做Cone Tracing,相当于对Tracing到的屏幕范围的像素做一次Filtering 优势:快,质量高,没有遮挡问题 问题:缺少屏外信息,重用近邻像素带来的错误Visibility 独特优势: 易于处理非常近的接近阴影 准确的Hit点计算 对场景复杂度不敏感 可以处理动态物体 Part II Lumen Real-time Ray Tracing的问题:...

2022-10-22-GAMES104现代游戏引擎-Lecture16-Gameplay Systems - Basic Artificial Intelligence

PS: Lecture17-20主要涉及[机器学习]、[网络架构]、[面向数据编程],与本人图形方向相离较多,故仅浏览学习,暂无笔记 Lecture16 Gameplay Systems - Basic Artificial Intelligence Navigation 三个步骤: Map Representation 地图表达 Walkable Area 需要考虑: Physical Collision Climbing Slope/Height Jumping Distance … 难以完全模拟人的可行路线,需要一定的限制,类似“空气墙”; AI Agents和Player的可行区域相同 Waypoint Network 路网,类似地铁线路图 寻找最近的路点 易于实现,快速寻路不够灵活,路网需要手工标注 Grid Square / Triangle / Hexagon 其中Square相对易于存储 易于实现、均匀数据结构、动态可更新 精确性依赖分辨率 密集网格降低寻路性能 内存消耗大 难以处理3D地图(桥梁、隧道等) Navigation Mesh 用简化的凸多边形表示场景 若出现凹多边形,寻路时可能跨越凹边出现在Mesh外区域 优势: 支持3D可行区域 精确 快速寻路 灵活选择起始地、目的地 动态 缺陷: 复杂的生成算法 不支持3D空间,例如空中飞行 Sparse Voxel Octree 空间八叉树 存储量大 寻路复杂 Path Finding 寻找路径 所有表达,都可归为图结构 即在图上找到一个路径,尽可能找到最优(短)路径 深度优先搜索 / 广度优先搜索 消耗比较高,广度优先适合找到最短路径...

2022-10-22-GAMES104现代游戏引擎-Lecture15-Gameplay Complexity and Building Blocks

Lecture15 Gameplay Complexity and Building Blocks Overview Gameplay的挑战 多个系统之间的合作 同一个游戏中Gameplay的多样性 快速迭代 Event Mechanism Hard Code写在函数中:无数的if/else、非常难以修改 Event/Message Mechanism:GO之间的“通讯协议” Publish-subscribe Pattern 发行-订阅设计模式 Event Definition 信息的定义 方法1:Event作为类设计 -> 不适合交给设计师修改 方法2:允许定义任意的Event 再通过代码渲染系统编译,但每次修改都需要重新编译过于麻烦 在引擎核心代码之外定义 dll注入 用脚本层语言实现 Callback Registration 响应注册 注册和调用不在同一处 –> 对象的生命周期和回调函数安全性问题 Strong Reference 强引用:引用关系绑定 Weak Reference 弱引用:引用关系弱,可手动进行逻辑判断,使用较多 Event Dispatching 信息分发 遍历每个GO,逐个分发调用函数 —— 效率过低 Immediate:发送消息立即调用函数 会打断前一任务,等待Callback执行后再继续 单次打断引发连锁Callback,易导致Callstack非常深,难以Debug 难以并行 Event Queue 把Event存储至队列,依次执行 Event Queue的序列化和反序列化 实现:利用反射,获取每个对象的描述结构 存储结构:Ring Buffer 不用重复申请新内存 Batching,将多个独立系统分开处理 问题: 无法保证多个系统间的执行顺序 => 保留一定的Immediate处理能力 同时具备Pre、Post、Immediate处理方式 有系统延迟,削弱动作游戏打击感 => 经常Hardcode绕过Delay Script System Game Logic 直接在游戏引擎代码内,使用编译语言编写 (C/C++) 每次修改Gameplay,需要重新编译游戏引擎 极难支持热更新 对设计师极不友好 脚本语言 Script System 支持快速迭代 易于学习、编写 支持热更新 沙盒运行,稳定、更少Crash 如何运行 基于虚拟机 Script Text -> [Compiler] -> Bytecode [Virtual Machine] 速度略慢 如何管理GO 强调效率:引擎内核管理,脚本触发引擎执行 编写难度大 执行过程非常复杂 直接交给脚本系统管理 脚本如何处理GO的生命周期:GC, Garbage Collection 优势:不需要手动管理对象生命周期,自动处理 问题:每次需要扫描内存,处理效率低 对于玩法相对简单的单机游戏,大多交给引擎管理; MMORPG等玩法非常复杂的游戏,大多脚本系统管理 架构 引擎调用脚本 eg....

2022-07-03-GAMES104现代游戏引擎-Lecture14-Tool Chains Applications & Advanced Topic

Lecture14 Tool Chains Applications & Advanced Topic Architecture of A World Editor A hub for everything to build the world Editor Viewport 运行一个完整游戏,“Editor Mode” 代码存在Editor Only -> 避免编译到最终游戏中 Everything is an Editable Object Objects Views Tree View Layer View Categories and groups 通过Schema系统编辑Object参数,参数编辑面板 Content Browser Editing Utilities in World Editor 鼠标选取 Ray casting 不需要缓存,支持同时选取多个物体 遍历性能差 RTT 在G-Buffer中存储Object ID 根据点击像素直接对应Object ID 其他Trick来选取无Mesh的Object Object Transform Editing Terrain Heightmap Texture 植被、水体等 Brush Height Brush 笔刷边缘的过渡、笔刷的可拓展性 Instance Brush eg....

2022-06-26-GAMES104现代游戏引擎-Lecture13-Tool Chains

Lecture13 Tool Chains 游戏引擎工具链的地位: 用户和引擎Runtime层的桥梁 引擎和DCC软件的桥梁:Asset Conditioning Pipeline 调和不同思维方式的平台:策划 / 美术 / 程序 GUI Immediate Mode 逐帧直接绘制,由引擎逻辑绘制,简单轻量直接 扩展性有限,性能有限,将业务压力交给了引擎逻辑 eg. Unity UGUI / Omniverse GUI / Piccolo GUI Retained Mode 将需要绘制的图形内容存储成Buffer,再交由GUI绘制 将引擎逻辑和GUI工具隔离,扩展性强,性能表现好 对开发者来说相对复杂 eg. Unreal UMG / WPF GUI / QT GUI Design Pattern MVC MVP:在MVC基础上的变化,View进一步与Model分离 MVVM:把Presenter换成ViewModel——用Binding将ViewModel和View绑定,用HTML/XAML等简单逻辑表示View 平台兼容性问题,eg. 在Windows下WPF表现较好 数据处理 Serialization and Deserialization 序列化与反序列化:文件、数据库、内存、网络之间的数据转换 存储数据 - Serialization 文件格式 最简单的数据格式:文本文件 易读易处理,但缺乏安全性 纯文本信息 eg. txt/obj/… -> 结构化 eg. XML/… -> 更简单的结构 eg. json/… eg....

2022-06-18-GAMES104现代游戏引擎-Lecture12-Effects

Lecture12 Effects Particle 一个粒子 @PBA 粒子形态 Billboard Particle 永远朝向相机的面片 Mesh Particle eg. 碎石 Ribbon Particle 光带 eg. 刀的尾迹 样条插值,一般用Catmull 粒子渲染 透明混合顺序 全局排序 精确但开销大 层级结构 系统 -> Emitter -> Within emitter 分辨率,性能开销爆炸 Low-Resolution Particles 低分辨率渲染粒子,再与普通画面混合 GPU粒子 定义Particle Pool 管理Dead list和Alive list 在Compute Shader上计算 Visualization Culling,管理Alive list Depth Buffer Sorting GPU并行Merge sort 双指针合并排序,读写会跳来跳去 优化:单指针遍历待写位置,找该写入的数值写入 Depth Buffer Collision 利用Depth Buffer做碰撞 Advanced Particle Animated Particle Mesh 动画可以编码成Texture:Particle Animation Texture 状态机可以通过切换贴图实现 Navigation Texture 从SDF计算Direction Texture(RG通道贴图) 实现群集运动的运动方向 eg....

2022-06-04-GAMES104现代游戏引擎-Lecture11-Physics System - Applications

Lecture11 Physics System - Applications Character Controller 一个反物理的系统:符合玩家感知 + 实现反物理运动 没有Character Controller时,大量Hack Kinematic Actor 不受物理规律控制 Push其他Actor Shape (人类角色时) Capsule 主要使用,一般设计两层 内层:碰撞 外层:防止角色与物体(墙面)太近 高速移动时容易卡进墙体 相机穿透导致看到墙后物体 Box Convex Collide with environment Sweep Test 判断 Sliding:撞到墙上时左右滑动 Auto Stepping:台阶 每帧尝试抬升高度前进 Slope 斜坡 坡度大于多少时,冲上去会滑下来 改变Controller形状/体积 eg.蹲下站起的变化 限制在环境大小不够时不可站起(eg.在隧道中) 更新前重叠测试,阻止形状更新 Push Objects (Dynamic Actors) Controller站在运动平台上时 不作处理就会平台动、Controller在原地 Ray Cast检测所站物体上,绑定,运动时也相对于平台 进一步精细:平台运动过快时的趔趄等 Ragdoll 不适用Ragdoll:播放死亡动画 => 死亡环境并不一定与动画一致 eg. 在悬崖边,悬空挂在坡面上甚至插入地形 用Rigid Body将关键的Joint连结起来 考虑Constraints 将Ragdoll中较少Joints的运动映射到Skeleton Animation Retargeting 三种Joints Active Joints:与Ragdoll相同的Joints,直接使用Ragdoll数据 Leaf Joints:一般不动,例如手掌脚掌 Intermediate Joints:Active Joints之间的Joints,利用邻近Active Joints插值 死亡动画到Ragdoll的过渡 一个问题:游戏中动画与物理的边界在哪里? Powered Ragdoll - Physics-Animation Blending 纯Ragdoll:效果不像人类 纯动画:循环播放,有模式感 两种混合 Cloth 传统:Bake动画,随着运动方向更换动画,移动端常用...

2022-05-25-GAMES104现代游戏引擎-Lecture10-Physics System - Basic Concepts

Lecture10 Physics System - Basic Concepts 物理的作用: + 物理直觉 + 动态环境,《彩六》破坏环境 + 环境交互,VR等《Alyx》 + 艺术效果,粒子、流体、布料 Physics Actors and Shapes Actor Static Actor 静态固定的,不受物理影响 Dynamic Actor 按照动力学原理运动的,受力/动量/冲量驱动 Trigger 根据碰撞触发Message从而产生Event Kinematic 反物理的自发运动(游戏设计师设计的运动) > Kinematic与受物理约束的Actor碰撞时,可能会产生“飞掉” Shape : 复杂形状物理计算过于复杂 Sphere Capsule 胶囊体 Box Convex Mesh 凸多面体 Trangle Mesh (一般只用于静态) Height Field !尽量使用简单的Shape(从前到后越来越复杂) Shape Properties Mass / Density 质量 / 密度 Center of Mass 质心 Friction / Restitution 摩擦力 / 弹力 (and more …) Forces Force eg....

2022-05-19-GAMES104现代游戏引擎-Lecture9-Animation System - Advanced

Lecture09 Animation System - Advanced Animation Blending LERP LERP / NLERP / SLERP 两个动画clip之间的LERP 权重 eg. 走路与跑步动画,依据运动速度切换 \[ {\rm weight_1=\dfrac{speed_{current}-speed_2}{speed_1-speed_2}}\\ {\rm weight_2=\dfrac{speed_{current}-speed_1}{speed_2-speed_1}}\\ \] 对齐时间线 eg.走路和跑步的步频不同,怎样对齐混合的帧 每一段动画为一步,对每一段动画时间线做归一化 Blend Space eg. 左右前后走/跑 1D Blend Space: eg. 左走、正走、右走三个动画,根据左右方向的速度插值(可以有分布不均匀的多个动画) 2D Blend Space: eg. 左右前后全部加入2D空间,由动画师指定动画位置 双线性插值 Delaunay Triangulation 常用 根据设置的动画点,生成三角形划分 在空间内一点,由周围三角形插值 插值利用重心坐标 Skeleton Masked Blending 针对只应用于半身或身体局部的动画,实现多种动画的混合 eg.各种姿态下的鼓掌 绘制一个Mask,只应用于部分Joints Additive Blending eg. 向着摄影机点头 存储动画的变化量,在基础动画上叠加一层动画 需要非常谨慎,易出现两个动画叠加后产生不自然的运动结果 Animation State Machine 状态机 两种核心元素 Node Clip Blend Space 脚本串接的单套动画系统 Translation 激活条件 Cross Fade Smooth transition 慢慢过渡,插值(各种插值曲线) Frozen transition 先停住动画A,再播放动画B 多层状态机 Animation Blend Tree 多层状态机在复杂动画中非常复杂 用树结构表示动画之间的Blend方式(LERP/Additive),类似表达式树 两种节点 Terminal Node 执行节点 (叶节点) Clip Blend Space ASM Non-terminal Node (非叶节点) LERP Blend Node Additive Blend Node Layered ASM to Blend Tree Blend Tree Control Parameters Variable 暴露变量,根据变量切换运动状态 eg....