本文内容
帧渲染
帧渲染流程描述了一个场景是如何从渲染组件(Render Components),通过 渲染管道接口(Render Pipeline Interface,RPI)中的渲染通道(Render Passes),到 渲染硬件接口(Render Hardware Interface,RHI)进行处理的。为方便查看,请参阅下面的 RPI 概述图。
渲染组件 → 特征处理器
Atom 渲染器接收并处理来自相关模拟的数据,并决定如何渲染这些数据。模拟是指 Atom 正在渲染项目的引擎(如 Atom Sample Viewer 和 Open 3D Engine)。每次渲染开始时,模拟都会向 Atom 发送数据。渲染组件(Render Components) 和特征处理器(Feature Processors) 处理这些数据流。渲染组件位于模拟中,负责将数据发送到相应的特征处理器。特征处理器位于渲染器中,负责存储渲染器绘制渲染组件所需的任何数据。特征处理器可以以它们认为合适的任何方式(如结构数组、数组结构、一对一、一对多等)存储数据** 例如,网格特征处理器存储网格实体的变换矩阵**。
当首次创建渲染组件时,它会注册其特征处理器,并接收一个唯一的识别索引(通常用数组表示)。该索引允许特征处理器在后续渲染中识别渲染组件。每次渲染时,渲染组件都会向特征处理器发送更新的数据。
*例如 动画网格组件将向动画网格特征处理器发送该帧动画的新骨骼矩阵。
特征处理器 → 绘制项、绘制数据包
此时,渲染组件会向特征处理器注册,在将索引交给渲染组件之前,特征处理器会创建相应的绘制项和绘制包。一个绘制项包含一次性渲染一个对象所需的数据。在某些情况下,需要多次渲染一个对象。例如,不透明对象应在预深度、阴影和前向遍历中渲染。与单个对象相关的绘制项集合称为绘制包。一个网格可能会创建多个绘图包(如 LOD 或具有不同材质的多个子网格)。如果对象更换着色器或材质,则可以重新创建绘图包。不过,由于这不是按帧更新,着色器和材质更新通常是通过更新和重新编译着色器资源组(SRG)来完成的。
编写新功能的开发人员必须实现自己版本的功能处理器和渲染组件。虽然绘制项和绘制包是通用的,适用于所有特征处理器,但特征处理器创建它们的方式可能会有所不同。
示例(续):当创建一个动画网格渲染组件时,它首先会向动画网格特征处理器注册。然后,它会创建相应的绘制包和绘制项,并向渲染组件交回一个唯一的标识索引。
绘制项 → 视图,绘制列表
当绘制项准备好被渲染时,它们需要首先被过滤到视图中,然后再被过滤到绘制列表中。此时,渲染组件已更新了地物处理器,地物处理器现在必须将其绘图数据包交给视图。视图代表渲染绘制项的视角。例如,大多数物体将通过主视图来观察,而有阴影的物体也必须通过阴影视图来观察。 为了找出特征处理器需要与哪些视图对话,它会使用View List Tag
从Scene
中查询 “视图”。每个视图都会使用空间剔除(渐缩测试)和Draw List Mask
剔除绘图数据包。这些掩码会从没有相关绘图列表的视图中过滤出绘图项目和绘图数据包。例如,阴影视图应剔除不包含任何阴影绘制项的绘制数据包。
当 “绘图包 ”被 “视图 ”接受时,其 “绘图项 ”会通过Draw List Context
在 “绘图列表 ”中进行过滤。绘制列表上下文是一个线程安全容器,用于在绘制列表中累积来自多个线程的绘制项。
示例(续):动画网格特征处理器将从 “场景 ”中查询主视图和阴影视图,并向这些视图提交绘制数据包。视图使用空间剔除和绘制列表遮罩剔除绘制数据包,然后将绘制数据包传递给绘制列表上下文。绘制列表上下文从绘制数据包中提取绘制项,并使用绘制列表掩码将其过滤到绘制列表中。阴影绘图项目将被过滤到阴影视图内的阴影绘图列表中。预深度和前向绘制项目将被过滤到主视图内的预深度和前向绘制列表中。
通道
通道是一组渲染工作,负责渲染绘图列表。当通行证渲染时,它会使用View List Tag
从其管道中查询视图(管道是通行证和视图的容器)。(管道是围绕通道和视图的一个容器),然后使用Draw List Tag
从绘图列表中查询这些视图。
通道还能为 RHI 后台创建作用域。作用域与通行证类似,只是它们存在于 RHI 中。当这些作用域被执行时,通行证将从它们查询的绘制列表中获取绘制项,并将其提交到 RHI 命令列表(一个渲染命令列表)中。在此基础上,RHI 完成帧的渲染。