文章

Games104(目录、架构分层、构建运行,源码解读)

课程目录

课程分为3部分,共22节课

  • 架构概述
    • 导论
    • 分层
    • 渲染中的数学
  • 各核心系统原理
    • 大气和云
    • 渲染管线
    • 后处理
    • 动画技术
    • 物理系统
    • 粒子
    • 工具链
    • gameplay
    • 网络
  • 前沿领域简述
    • 动态GI
    • GPU
  • piccolo源码解读:
    • 核心:如何下载源码、如何构建运行、文件夹解读、核心流程、如何添加库、如何添加component
    • 深入反射系统解读:构建流程、generated文件解读、修改MotorComponent
    • 深入渲染系统解读:渲染流程、pass流程,修改shader,如何renderdoc调试、如何添加vignette暗角pass

架构分层

  • 1
  • gameplay->editor->runtime(function->resource->core->platform)->三方库->操作系统->驱动->硬件
  • 为什么分层:
    • 让不同部门专注于特定层优化
    • 遵守封装,降低耦合度
  • editor
    • 工具层editor:编辑器_用户交互界面,允许其他人使用工具开发游戏
      • 编辑器:世界、资产文件、世界层级、属性、菜单、工具、材质、节点、动画……
      • 代码量是最大的
      • 和其他GCC工具(maya,max……)统称为工具层
  • runtime
    • 功能层function:不同子系统,是中间层
      • 子系统分类:渲染、动画、UI,物理,IO,玩家,相机,逻辑,输入
      • 每帧更新:logic(相机,控制器,动画,物理……),render(相机,裁剪,场景渲染,后处理,呈现)
      • 让gameplay层方便扩展API
      • 必不可少的多线程
    • 资源层resource:资源管理,是中间层
      • 离线资源导入:
        • 预处理加载资源:
          • 资源分类:纹理,骨骼,模型,音频,动画,关卡地图,材质,数据文件,脚本,字体……
          • 资源resource到资产asset转换:转换可以被GPU处理的格式、提取有用的数据、压缩
          • 作用:提高运行时访问速度
        • 统一访问方式:通过统一抽象层(继承体系),访问所有类型的元资产(asset的各种数据)
        • 复合资产文件:涵盖所有资源
        • 为asset映射路径:path
        • 全局唯一标识符:GUID
      • 运行管理:
        • 资产系统:通过path动态的加载卸载asset(不同资源有不同生命周期,延迟加载(在运行到某节点加载),垃圾回收:不需要的asset要即时释放)
    • 核心层core:功能的内核,提供各个功能系统所需的各种工具和功能
      • 数学:强调运算效率,可以接受近似结果
      • 数据结构:c++数据结构不易直接使用,需要专门写一层封装,因为容易造成内存浪费
      • 内存管理:优化点:1.把数据集中存放;2.按照顺序结构排列;3.批处理分配和撤销
    • 平台层platform:对接不同平台,使游戏开发不受平台差异影响
      • 图形API:RHI渲染硬件接口,多个GPU架构以及SDK
      • 文件系统:路径(正斜杠、反斜杠),环境变量,目录遍历
      • 操作系统
      • 输入输出设备
      • SDK
  • 引擎常用三方库:
    • 窗口输入:glfw
    • 数学:glm
    • GUI:imgui
    • 模型加载:tinygltf、tinyobjloader、Assimp
    • 日志:spdlog
    • 纹理:stb_image、ktx
    • 序列化:cereal、json11、yaml-cpp
    • 物理:JoltPhysics、Box2D
    • vulkan资源管理:vma
    • Vulkan内存分配库:vulkanmemoryallocator
    • 控件:ImGuizmo
    • 随机数生成器:random
    • 反射:rttr
    • cereal:json
    • 实体组件:eventpp、entt
    • vulkan SDK
    • 矢量字体:msdf-atlas-gen
    • 文件系统监控:filewatch
    • 嵌入C#脚本支持:mono

构建运行

  • cmake . -B build 生成工程文件
  • cmake –build build 构建
    • vs中:(需要将PiccoloEditor设置为开始项目)
      • JobSystemThreadPool.cpp(115,27): error C3688: invalid literal suffix ‘us’; literal operator or literal operator template ‘operator ““us’ not found
        • us微妙,编译器无法识别
        • 加入头文件#include <chrono> using namespace std::chrono_literals;
      • LINK : fatal error LNK1104: cannot open file ‘....\3rdparty\JoltPhysics\Build\Debug\Jolt.lib’
        • 是因为JoltPhysics这个项目开启了“将警告视为错误”,因此也就没有生成Jolt.lib文件,链接时也就找不到这个文件
        • 把这个project的属性,C/C++ ->General->Treat Warnings As Errors设置为No即可
  • bin/PiccoloEditor 运行
  • 1

源码解读

piccolo引擎共有9个迭代版本,编程语言:c++/C,图形API:vulkan,版本管理工具:git,构建工具:cmake,平台支持:windows/linux/macOS,代码量:31481行代码

runtime文件夹内存分布

1741076271724

function > core > resource > engine > platform

流程解读_简述:

:draw.io放在/assets/img/blog/Games104/文件夹下

  • 1
  • 核心流程
  • 1
  • 构建流程
  • 1
  • generated文件解读

文件解读_简述:

  • 以‘ . ‘开头的(.github,.gitlab,.clang-format,.clang-tidy,.gitignore)文件,是各个工具的配置文件
  • cmakelists.txt是cmake的配置文件
  • LICENSE授权,README、releasenotes自述
  • scripts和build + 平台 开头的bat批处理文件,为了方便构建写的脚本文件(生成工程 + 构建)
  • engine:
    • 3rdparty 第3方库的源码/2进制文件
      • glfw 管理窗口、图形API上下文、输入和事件循环 的跨平台库
      • glm 数学库
      • imgui 用户ui库
      • json11 数据序列化库
      • spdlog 日志库
      • stb 实用工具库
      • tinyobjloader 轻量级OBJ模型加载器
      • vulkanmemoryallocator Vulkan内存分配库(简化GPU内存管理)
      • vulkanSDK 图形APISDK
    • bin: 包含parser解析器文件,在构建时,解析c++文件,根据template模板文件生成功能性代码(_generated序列化文件)
    • template:c++模板文件
    • asset引擎启动时需要的资产,资产文件夹映射的位置
      • json是序列化文件(这些都是手动编写的)(粒子、渲染(天空纹理、颜色,环境光,相机,定向光)、世界、关卡、玩家、动画、控制器、材质(玩家,黄金,银,白),栅栏,地面,楼梯,墙……)
      • 资产:图片(jpg、png、hdr、tga),模型(obj)
    • configs引擎启动时需要的文件
      • 1
      • PiccoloEditor.ini:
        • 要在main中输入,最终会被config_manager解析
        • resource路径在editor/resource下,这里包含piccolo图标icon资源
    • shader引擎启动需要的shader
    • jolt-asset:物理库相关的shader
    • source源码
      • _generated存放paser解析生成的文件
        • reflection(都已.reflection.gen.h扩展名结尾)
          • all_reflection.h核心文件:#include所有.reflection.gen.h文件,提供TypeMetaRegister::metaRegister()函数,会调用这些文件的主注册函数,它会被Engine的startEngine和shutdownEngine调用
          • 分为三个部分:
            • Piccolo::Reflection::TypeFieldReflectionOparator::Type……Operator类、
              • 基础函数(3个):获取类名(返回类名),通过json构造(Serializer::read),转化为json(Serializer::write)
              • 基类函数(1个):获取基类的反射实例
              • 字段函数(5个):被META标记的成员,取字段名(返回成员名)、字段类型名、设置、获取、是否是数组(如果是std::vector容器会返回true)
            • TypeWrapperRegister_……: 次注册函数
              • 把以上所有函数,创建分别创建ClassFunctionTuple、MethodFunctionTuple、FieldFunctionTuple类型指针,组成tuple,注册到FIELD/Method/BASE_CLASS map中(reflection.cpp)
            • 主注册函数(调用次注册函数):如果一个文件有多个类,主注册函数仍为1个
        • serializer(都已.serializer.gen.h扩展名结尾)
      • meta_parser:paser解析器源码
      • precompile:包含camke脚本和配置文件,使得cmake在构建前使用parser解析源码
      • test用于存放测试代码
      • editor编辑器
        • resource编辑器相关资源
        • include头文件
          • axis:位移旋转缩放 继承RenderEntity
          • editor_file_service:获取父节点指针,检查文件数组,获取根节点
          • editor_global_context:初始化,清理,包含场景管理,输入,窗口,引擎
          • editor_input_manager:按键,重置,光标按下,滚轮,鼠标点击,窗口关闭,更新光标轴, 获取窗口位置、大小
          • editor_scene_manager:获取旋转对象的id、矩阵,获取编辑器轴模式
          • EditorUI继承window_ui并重写方法
          • editor编辑器核心,初始化,运行,清理
        • source源文件
          • main核心入口点
            • PiccoloEngine,PiccoloEditor,对它们分别初始化,
            • 对editor运行(这里会调用engine的运行),最后清理
      • runtime运行时
        • engine引擎核心
          • 函数:
            • 公开:
              • 初始化(空定义),清理(空定义)
              • 开始,反射系统注册元数据,global_context开始系统
              • 结束,global_context结束系统,反射系统取消注册元数据
              • 运行,global_context中的window_system,当窗口没有关闭就会一直运行,计算DeltaTime时差(利用chrono库),每帧
              • 每帧更新:逻辑、计算FPS、交换逻辑和渲染的数据、渲染,其他的不易划分到逻辑渲染中(物理世界,时间轮询,窗口标题)
              • 退出,
            • 私有:
              • 每帧逻辑更新:global_context中的world_manager更新tick,global_context中的input_system更新
              • 每帧渲染更新:global_context中的render_system更新
              • 计算fps
              • 获取fps
          • 友元:editor
        • platform平台层:
          • 文件系统 file_service,获取文件路径名(其他文件使用时#include)
          • 路径 path:获取相对路径、路径段、文件扩展名、文件名(其他文件使用时#include)
        • core核心层:
          • 基础 base :宏(日志(log_system的log),睡眠,转换为字面值,断言)、哈希函数(以便获取随机值)
          • 颜色 color:rgb成员的类
          • 数学库 math
            • vec2、vec3、vec4、matrix3、matrix4、transform(SRT)、random、quaternion四元数、math(Radian弧度、Angle角度、Degree度),axis_aligned轴对齐AABB包围盒、math_marcos宏(最小最大……),math_headers所有math头文件的汇总
          • 日志 log
            • log_system,日志等级的枚举(调试,信息,警告,错误,极为严重的错误),spdlog库的logger成员,打印日志根据等级和信息,回调抛出异常
          • 元数据 meta
            • 概念:
              • 反射:运行时(指令)对 对象数据(元数据)访问/修改值 的行为
              • 元数据:
                • 通过反射能够访问到的所有数据
                • 常见有:
                  • 是否为类类型、指针、const、enum
                  • 类名,父类信息,实现接口,继承访问修饰符
                  • field字段名,字段类型,访问修饰符,字段注释,是否为静态,
                  • 方法名,返回类型,参数(类型,名字,注释),抛出的异常,访问修饰符
                  • 对齐要求,对象大小,成员偏移量
              • 使用成员不属于反射:因为它是在编译器就确定了访问谁 怎样修改,而非运行时查询
              • 类的get/set不属于反射
              • 反射实现:java,c#都有反射语言特性,c++没有提供,要实现反射能力,需要自定义反射系统
              • 序列化:
                • 将对象转换为可存储的格式(JSON、XML……),以便重新转换为对象
                • 使用场景:保存/加载场景
                • 本质使用反射机制,序列化(利用反射读取对象元数据 → 保存),反序列化(读取保存的元数据 → 利用反射重建对象)
                • 优势:轻量,解耦
            • 反射
              • reflection_register,元数据注册(在engine开始时会调用),取消注册(在engine结束时会调用)
              • reflection:
                • C++反射系统,很多头文件都使用它
                • 宏(CLASS/STRUCT标记需要反射的类,REFLECTION_BODY反射支持私有成员,META标记需要反射的成员)
                • 元数据存储结构
                  • TypeMetaRegisterinterface,管理所有TypeMeta
                  • TypeMeta描述单个类型元数据
                  • metadata包括field,array,class三类
                • 访问器:FieldAccessor字段、MethodAccessor方法、ArrayAccessor数组
            • 序列化器serializer:将C++对象序列化为JSON,将JSON反序列化为C++对象
            • meta_example使用示例:普通类,有继承关系的类
        • resource资源层:
          • 资产系统 asset_manager
            • 在global_context创建,函数会被各个模块调用,是序列化器的接口
            • 加载(反序列化):应传递json路径,读取文件写入到string,传给json11库,由Serializer读取
            • 保存(序列化):通过Serializer写入到输出文件
            • 获取path:filesystem::absolute
          • 配置系统 config_manager:
            • 在global_context初始化,负责管理path
            • 公有方法:
              • 初始化:根据实参的路径,读取文件,getline读取每行,如果找到=号,就substr提取字串,将path赋值给member成员
              • 获取根目录、资产目录、最小/大图标路径,字体路径、世界路径、渲染资源路径、粒子资源路径
            • 私有成员:
              • filesystem::path各个路径
          • 元数据 res_type
            • 全局数据 global(应用于所有物体)
              • 粒子数据 global_particle:发射周期、次数、步长、生命……
              • 渲染数据 global_rendering:地图边界,定向光,天空盒,天空颜色,环境光色,相机
            • 通用数据 common
              • 世界 world:名字,路径,默认关卡路径
              • 关卡 level:玩家名字,重力值,
              • 对象 object:类型名,组件名
            • 组件数据 components
              • 动画 animation:变换,骨骼路径,混合状态,帧位置(0——1),
              • 相机 camera:fov,垂直偏移,光标旋转,速度,参数
              • 粒子发射器 emitter:局部变换,速度,大小,类型,生命,颜色
              • 网格 mesh:变换,材质,子网格
              • 运动 motor:速度,跳跃高度,最大速度,冲刺速度
              • 刚体 rigid_body:全局变换,形状类型,包围盒
            • 其他数据 data
              • 动画片段 animation_clip:名字,关键帧位置,旋转位置,总帧,通道
              • 动画骨骼节点 animation_skeleton_node_map:转换
              • 基本形状 basic_shape:半径,高度
              • 动画混合状态 blend_state:片段数量,混合路径,混合高度,
              • 相机配置 camera_config:位置,目标,上向量,zf距离
              • 材质 material:基础色、法线纹理、粗糙度纹理、不透明度纹理、自发光纹理 路径
              • 网格数据 mesh_data:vbo,ibo,骨骼绑定
              • 骨骼 skeleton_data:名字,索引,父索引
              • 骨骼掩膜 skeleton_mask:骨骼文件路径,是否启用
        • function功能层:
          • 框架framework:运行时功能核心框架
            • 世界管理器 world_manager
              • 公有函数:
                • 初始化,清理,保存、重新加载当前关卡,获取当前激活关卡,获取当前激活物理场景
                • 每帧:
                  • 如果不存在world就加载世界
                  • 对active_level调用tick
              • 私有函数
                • 加载世界:
                  • asset_manager加载json文件,获取世界资源
                  • 加载关卡
                  • 找到默认关卡,设置为当前激活的关卡
                • 加载关卡:根据path调用level的加载,并添加到哈希中保存
              • 私有成员:世界是否加载,世界url,世界资源,关卡哈希,当前激活的关卡,关卡调试者
            • 关卡 level:
              • LevelDebugger:负责关卡调试,显示所有物体所有骨骼、一个物体所有骨骼、对象的包围盒……
              • level
                • 公有函数:
                  • 加载:
                    • 根据asset_manager加载关卡元数据
                    • physics_manager创建物理场景
                    • 粒子发射器重置
                    • 循环对象列表,创建对象
                    • 创建Character
                  • 每帧:遍历所有gobject(game object)、Character、physics_scene,调用tick
                  • 卸载,保存,获取所有对象、所有对象ID、当前激活的角色、关卡路径、创建对象、删除对象、物理场景
                • 私有函数:清理
                • 私有变量:是否加载,关卡url,GObject哈希,Character,PhysicsScene
            • 游戏对象 object
              • game object(gobject):
                • 本身没有任何功能,只有挂载了component才有功能
                • 加载,保存:读写objet及component资源
                • 获取id,获取名字,是否有组件
                • 每帧:遍历所有components,调用tick
              • object_id_allocator:对象分配器,分配id
            • 组件component全都继承自 component.h 中的 Component 类,目前组件包括:
              • 动画 animation
                • 包含骨骼
                • tick:对骨骼应用动画
              • 相机 camera
                • 相机上前左三向量确定视口方向
                • tick:根据input计算的数值对相机进行更新(character + offset)
              • 网格 mesh
                • 根据attach的object的transform与animation进行更新
                • raw_mesh:
                  • 静态网格
                    • primitive类型,包括point, line, triangle, quad,以及
                    • indice与vectex buffer(位置,法线,切线,纹理坐标)格式
                    • 材质纹理:基础色,金属度,粗糙度,法线
              • 运动 motor
                • tick:根据输入(鼠标键盘)计算当前帧的姿态数据
              • 粒子 particle
              • 刚体 rigidbody:物理
              • 变换 transform:
                • 对rigidbody更新
          • 子系统
            • 动画 animation
              • animation_loader.h 加载动画帧、骨骼数据、动画骨骼、
              • animation_system.h 加载骨骼、动画、动画骨骼、混合
              • node.h :获取名字、父物体、位置缩放旋转
              • skeleton.h:构建,重置,获取骨骼数量
              • utilities.h :查找根据 索引/名字
            • 角色 character
              • character.h 获取id,设置/获取 位置旋转
            • 控制器 controller
              • character_controller.h 移动
            • 全局上下文global_context
              • global_context
                • 在Engine中开始和结束系统,管理所有子系统(引擎需要的模块)、管理器(逻辑上需要的模块)
                • 公有方法:
                  • 开始系统:接受path(用于传给config_manager),对各个成员指针make_shared构造对象,并初始化
                  • 结束系统
                    • 先调用各自指针的clear清理子资源,再调用reset释放内存并置nullptr
                • 私有成员:包括所有子系统的指针(日志、输入、文件、资产、配置、世界、物理、窗口、渲染、粒子、调式绘制、渲染调式配置)
            • 输入 input
              • input_system.h
                • 初始化,每帧,清理,重置游戏命令
                • GLFW提供的输入基础定义,editorMode与GameMode分别有着不同的定义,轴向的转动用视口的光标移动与相机fov进行计算
            • 粒子 particle
              • emitter_id_allocator.h 分配,重置
              • particle_common.h 位置、速度、大小、生命
              • particle_desc.h 粒子发射器,位置、速度、大小、生命、颜色、类型、旋转……
              • particle_manager.h 粒子pass,创建粒子发射器
            • 物理 physics
              • utils单元:获取层数量,数据类型转换
              • physics_config:数据(身体数量,屏障数量,重力)
              • physics_manager:创建物理场景
              • physics_scene:获取重力,创建刚体,更新刚体全局位置,光线捕获,是否覆盖,获取形状
            • UI ui
              • window_ui抽象基类,初始化,预处理渲染
            • 渲染 render
              • 接口
                • RHI:渲染硬件接口,抽象基类,都使用RHI……类型,接口被各个文件调用,其中init被render_system调用
                  • 公开函数
                    • 初始化流程: 调用各个私有函数
                    • create / allocate vulkan对象
                    • command(cmd开头的,sync……)都封装为函数
                    • get:函数返回vulkan对象,都使用RHI类型
                    • write:BeginCommandBuffer,submit……
                    • destory:销毁各种vulkan对象
                    • memory:映射……
                • RHI—struct:跨平台通用类型,核心类型,都使用RHI……开头
                • vulkan
                  • vma:定义宏
                  • resource:定义vulkan对象(仅对核心对象)封装(托管/包装),提供set、get接口,继承自RHI类型
                  • rhi
                    • vulkan API,核心,继承自RHI并重写函数
                    • 数据类型转换:使用RHI……对象时,转换为Vulkan……,再getResource获取Vk……对象(以便赋值给Vk……对象) / setResource设置(以便设置RHI的值)
                    • 公开函数:
                      • 重写基类
                    • 公开成员:
                      • vulkan对象,PFN_ 函数指针
                    • 私有函数
                      • instance,validation_Layer,windowsurface,physicalDevies,Device,CommandPool,CommandBuffer,DescriptorPool,SyncPrimitives,Swapchain,SwapchainImageViews,FramebufferImageAndView,Allocator
                      • 验证层,队列索引,查询设备支持,选择交换链格式……
                    • 私有成员
                      • 某些vulkan对象:格式,尺寸,信息,呈现模式……
                  • util
                    • 创建:着色器模块,buffer和memory、copy,创建image和imageView、cubemap、mipmap、layout、sampler
                    • 销毁:……上面
              • debugDraw调式渲染器,绘制各种基础mesh
                • debug_draw_primitive图元:
                  • 各种图元继承自Primitive基类,包含时间类型(无限时间,一帧)、生命时长、填充模式(线框、实心)、是否有深度测试、是否超时、设置时间、是否已渲染、Vertex数据、Description、图元type(点、线、三角形、矩形、盒体、圆柱体、球体、胶囊体、文本)
                • debug_draw_group
                  • 数据:
                    • 组的名字
                    • 包含各类图元的list链表
                  • 添加各类图元的函数:创建图元,并根据形参填充图元的属性,将图元添加到相应的list
                  • 清理:清理所有数据
                  • 移除死亡的图元:用iteration遍历每个list,如果某个图元超出自身生命时长就erase
                  • 合并两个group:对g1的每个list的尾部都insert g2的list
                  • 获取数量:返回list的数量,通过迭代计数
                  • 写入数据:给一个vector,往这里写入顶点数据
                • debug_draw_context
                  • 包含vector管理所有group
                  • 获取/创建group:如果有此名字的组,就直接获取,否则创建并返回
                  • 移除死亡的图元:调用每个group的移除死亡的图元
                • debug_draw_manager
                  • 核心,主要负责:cmdBindVertexBuffer,clear,beginRenderPass,BindPipeline,drawcall,EndRenderPass
                  • 数据:RHI、buffer,pipline、context、font、 视图投影矩阵、图元数据start end的offset
                  • 函数:初始化、设置管线、预处理管线数据、销毁、清理、每帧、更新重建swapchain、获取/创建group、绘制、交换数据到渲染,渲染调试对象,预处理渲染缓冲、绘制点线三角形盒体、绘制边框对象
                • debug_draw_pipeline
                  • 主要负责:创建renderpass,Framebuffer,DescriptorLayout,Pipeline
                  • 数据:pipeline类型(图元类型)、描述符布局、渲染管线、帧缓冲、rhi
                  • 函数:
                    • 初始化
                    • 销毁、获取pipline、获取帧缓冲、重建交换链、设置(附件、交换链、渲染通道、描述符布局、管线)
                • debug_draw_buffer
                  • 主要负责:创建buffer,memory,DescriptorSet
                  • 数据:描述layout、set,vbo、ubo、ubod的buffer、memory,rhi、ubo(视图投影矩阵),ubo动态缓冲(模型矩阵、颜色),font,计数器
                  • 函数:初始化、销毁、每帧、清理、清理缓冲、顶点缓冲、ubo缓冲、ubo动态缓冲,顶点缓冲偏移、ubo动态缓冲偏移、分配、获取(顶点缓冲,描述符、图元类型的buffer、图元类型的顶点缓冲的大小)、设置/预处理/更新描述集、加载缓冲
                  • 内存分配器,管理GPU资产
                • debug_draw_font:需要创建图像显示字体
              • passes 核心在camera pass 包含主场景渲染、后处理相关的子pass、还有light相关的pass(都继承自RenderPass)
                • color_grading_pass.h
                  • 将rgb的色彩空间,转换到32*32*32的3D色彩空间中
                  • 初始化
                    • 设置描述符布局
                      • 这里有上一次tonemap subpass 的输出、调色纹理
                    • 设置pipline
                    • 设置描述符集
                    • 更新帧缓冲
                  • draw:cmd的命令,包括drawcall
                • combine_ui_pass.h
                • directional_light_pass.h定向光
                • fxaa_pass.h抗锯齿FXAA
                • main_camera_pass.h主相机
                  • 初始化:(在render_pipeline中初始化)
                    • 设置附件
                      • 对帧缓冲附件:gbuffer、backup、后期处理、深度、交换链图像、自定义附件
                      • 设置format
                      • 创建image和imageview
                    • 设置render pass(包含各个subpass)
                      • 根据AttachmentDescription,SubpassDescription,SubpassDependency,创建RenderPass
                    • 设置描述符布局
                      • 创建DescriptorSetLayout:mesh、global、material、skybox、axis、gbuffer
                    • 设置pipline
                      • 创建GraphicsPipeline:mesh gbuffer,deferred lighting,mesh lighting,skybox,draw axis
                    • 设置描述符集
                      • :ModelGlobal、Skybox、Axis、GbufferLighting
                      • 首先allocateDescriptorSet
                      • DescriptorSet和buffer绑定
                      • 设置帧缓冲描述符集
                    • 设置交换链帧缓冲
                      • createFramebuffer
                  • 前向draw,
                    • 跳过一些subpass,这是关于延迟渲染的(gbuffer)
                    • 主场景:drawMeshLighting所有网格体,skybox,particle
                    • 后期处理:对其余各个子subpass调用draw(tone mapping, color grading, fxaa, axis, ui)
                  • 延迟draw,首先drawMeshGbuffer,然后再做上述流程
                • particle_pass.h粒子
                • pick_pass.h 拾取色
                • point_light_pass.h 点光源
                • tone_mapping_pass.h 色调映射
                • ui_pass.h 用户UI
              • light.h :
                • 光源列表:
                • 点光源,环境光,定向光(平行光)
              • render_camera.h
                • 世界窗口的相机
                • 属性:相机类型(编辑器,运行时),位置旋转缩放、zf距离、fov,前上右轴,视图矩阵、投影矩阵
                • 函数:获取和设置 属性
              • render_common.h
                • 渲染相关数据:都以结构体形式存在
                  • 存储缓冲:定向光,点光源,存储缓冲,点/平行光源阴影,粒子……
                  • 网格,材质
              • render_debug_config.h ,
                • 调式相关配置:
                • 是否展示骨骼、骨骼名字、运行时相机信息、包围盒
              • render_entity.h :
                • go相关的数据
                  • id,模型矩阵
                  • 网格:网格资产id,是否启用顶点混合,关键材质,包围盒
                  • 材质:材质资产id,混合,基础色,粗糙度,金属度,自发光颜色,法线缩放,不透明强度
              • render_guid_allocator.h
                • 全局唯一标识符分配器,本质使用双向映射
                • m_elements_guid_map: 元素 → GUID 的映射
                • m_guid_elements_map: GUID → 元素的映射
                • 从1开始顺序分配GUID,重用已释放的GUID,保证同一元素多次分配返回相同GUID
                • allocGuid(): 为元素分配GUID
                • freeGuid()/freeElement(): 释放GUID
                • getGuidRelatedElement(): 通过GUID查找元素
                • getElementGuid(): 通过元素查找GUID
              • render_helper.h
                • 包围盒:BoundingBox、BoundingSphere
                • 视锥体:Frustum
              • render_mesh.h,
                • 对于VBO数据结构体(位置,法线,切线,纹理坐标,骨骼索引,骨骼权重),
                • Descriptions
              • render_object.h
                • 游戏对象
                • id、相关描述:网格、材质、变换、发光、骨骼绑定、骨骼动画
              • render_pass_base.h
                • 渲染通道基类:
                • 初始化,设置信息,数据
              • render_pass.h
                • 渲染通道:继承base,是所有pass的基类
                • 两个enum:帧缓冲附件、subpass
                • 资源指针,描述(输入输出数据在shader中的布局),管线信息,这个pass可视物体(一个pass可能仅会用到其中一部分og)
              • render_pipeline_base.h
                • 渲染管线基类:
                • 清理,初始化,数据,前向/延迟渲染
                • 各个pass的指针
              • render_pipeline.h
                • 渲染管线
                • 初始化:初始化各个pass
                • 拾取网格体的GUID,重置交换链
                • 前向渲染
                  • fence
                  • reset CommandPool
                  • BeginCommandBuffer
                  • drawcall
                    • 定向光阴影->draw
                    • 点光源阴影->draw
                    • particle->draw
                    • MainCameraPass->drawcall(内部各个subpass)
                    • debugdraw->draw
                  • endcommandbuffer
                  • submit
                  • Present
                • 延迟渲染
              • render_resource_base.h
                • 资产基类:
                • 更新游戏对象渲染资产、加载纹理、hash、材质、静态网格
              • render_resource.h :
                • 全局渲染资源 + 渲染资源管理器(负责所有GPU资源的管理)
                • 全局渲染资产:
                  • IBL资产(brdfLUT、环境贴图、预滤波环境贴图,它们三个组成IBL贴图)(image, imageView, sampler, allocation)(宽高、格式),颜色渐变(LUT图像),存储缓冲
                • 渲染资源:
                  • 函数:
                    • 上传:全局渲染资源:加载各种texture data,利用RHI创建图像
                    • 上传:游戏对象渲染资源、预帧缓冲、实体网格、实体材质
                  • 成员:全局渲染资源、render_common定义的所有数据,其中mesh和material上传需要有description描述符
              • render_scene.h
                • 场景:用于管理所有场景对象(光源,实体)
                • 清理,更新可视对象,获取分配器,删除对象
              • render_swap_context.h:
                • 从logical模块获取的渲染所需的数据(每帧render其他模块都从swap_context获取数据,首次初始化时从json获取),使用了两个缓冲区(swapchain有三个image,因此只需两个),目的是同步logical和render,防止数据竞争
                • 渲染数据:
                  • 数据
                    • 关卡资产描述:天空盒环境贴图、镜面贴图,颜色渐变
                    • 相机:fov,相机类型、视图矩阵
                    • 游戏对象:游戏对象的deque(双端队列),添加和删除的go
                    • 粒子:发射器,需要tick的发射器,更新发射器变换
                  • 函数
                    • 添加阻挡物
                    • 删除游戏对象
                    • 添加新的粒子发射器
                    • 添加帧粒子发射器
                    • 更新粒子发射器变换
                • 函数:
                  • 获取逻辑、渲染数据:根据索引从总数据数组获取,外部模块根据它获取和设置
                  • 交换 逻辑、渲染 数据
                    • 在engine中调用,外部更新logical数据,swap(将逻辑变为渲染),使用渲染数据 渲染
                    • 重置渲染数据,swap 索引
                  • 重置各种数据:对渲染数据 清理
                  • 是否准备交换:任意数据有值
                • 成员:逻辑、渲染 索引,总数据数组
              • render_system.h
                • 渲染器,渲染子系统的核心,在global_context中初始化
                • 初始化
                  • 获取config_manager、asset_manager、window_system
                  • 创建RHI并初始化
                  • 获取数据:(从json)
                    • config_manager获取渲染资源path
                    • 通过asset_manager读取json文件并加载 全局渲染数据
                  • 创建resource中的贴图、相机、场景中的光照、管线,将这个全局渲染数据中 相应资源数据 加载到对应对象中
                • 函数:
                  • 每帧
                    • 获取数据(从swap_context)
                      • 从logical层获取更新的数据,也就是获取渲染所需的数据
                      • 根据获取的数据,更新到各个system管理的模块中
                    • 准备渲染命令上下文(command_buffer)
                    • resource更新帧缓冲(pass共用数据:VP,相机,环境光,点光源)
                    • scene更新可视的物体(按照数据分类,筛选所需的数据)
                    • pipeline预处理数据(对每个pass,更新自身成员数据)
                    • 调用main_camera_pass中的:forwardRender / deferredRender
                  • 清理,交换逻辑渲染数据,获取交换资源,获取相机、RHI(返回成员),设置管线类型、初始化UI、更新视口大小、获取点击网格的GUID、通过网格ID获取对象ID,获取,获取视口大小,创建、设置可视、选择 轴,
                • 包含各个子模块指针:RHI,相机,场景,资源,管线
              • render_type.h 自定义RHI通用类型,目的跨平台,都以RHI……开头
              • window_system.h:注册 按键,字符,鼠标,光标,滚轮,推拽,窗口大小,窗口关闭
本文由作者按照 CC BY 4.0 进行授权
本页总访问量