UE4 渲染基础概念
UE4 渲染基础概念本文总结于ue4 4.9官方文档转载请注明文章出处,作者信息,原文链接场景基本对象UWorld : 世界,相当于一个包含了所有角色和组件的容器,世界中的关卡可以动态载入载出,游戏中的多个世界可以被设置为活动的ULevel : 关卡,世界的子集,用于包含和管理角色和组件的载入载出,关卡被存储于一个独立的 map 文件中USceneComponent : 能够被加载到场景中的对
UE4 渲染基础概念
本文总结于ue4 4.9官方文档
转载请注明文章出处,作者信息,原文链接
场景基本对象
- UWorld : 世界,相当于一个包含了所有角色和组件的容器,世界中的关卡可以动态载入载出,游戏中的多个世界可以被设置为活动的
- ULevel : 关卡,世界的子集,用于包含和管理角色和组件的载入载出,关卡被存储于一个独立的 map 文件中
- USceneComponent : 能够被加载到场景中的对象的基类,如灯光,网格,雾等
- UPrimitiveComponent: 所有能够被渲染的或可与物理交互的对象的基类,同时也扮演了最小粒度的可视化裁剪和保存渲染属性的角色(如投射阴影)与所有 UObjects 一样,游戏线程拥有所有变量和状态,渲染线程不应直接对其进行访问
- ULightComponent : 代表光源。渲染器负责计算和添加其对场景的贡献
- FScene : UWorld 的渲染器版本。对象仅在其被添加到 FScene(注册组件时调用)后才会存在于渲染器中。渲染线程拥有 FScene 中的所有状态,游戏线程无法直接对其进行修改
- FPrimitiveSceneProxy : UPrimitiveComponent 的渲染器版本,为渲染线程映射 UPrimitiveComponent 状态。存在于引擎模块中,用于划分为子类以支持不同类型的基元(骨架、刚体、BSP 等)。实现某些非常重要的函数,如 GetViewRelevance、DrawDynamicElements 等
- FPrimitiveSceneInfo : 内部渲染器状态(FRendererModule 实现专有),对应于 UPrimitiveComponent 和 FPrimitiveSceneProxy。存在于渲染器模块中,因此引擎看不到它
- FSceneView : 单个视图到一个 FScene 的引擎代表。视图可以通过对 FSceneRenderer::Render 的不同调用的不同视图来渲染(多编辑器视口)或通过对 FSceneRenderer::Render 的同一调用中的多个视图来渲染(分屏游戏)。为每个帧构建新视图
- FViewInfo : 渲染线程中描述View信息的对象,可以看成是view在渲染线程中的副本
- FSceneViewState : ViewState 存储有关在多个帧中需要的某个视图的私有渲染信息。在游戏中,每个 ULocalPlayer 都有一个视图状态
- FSceneRenderer : 每个帧都会被创建的类,用于封装跨帧的临时对象
材质基本对象
- FMaterial : 材质渲染接口,用于访问材质属性(如混合模式),及着色器容器,可根据具体平台和设置选择具体着色器版本
- UMaterial: 材质资源类,计算着色的材质属性,和设置混合模式等功能
- FMaterialResource :
UMaterial
的FMaterial
接口实现 - FMaterialRenderProxy : 材质对象在渲染线程的实现,用于渲染线程访问材质的各种属性,如各标量值,向量值,贴图参数等
- UMaterialInterface : 虚类,材质对象在游戏线程的接口,用于访问渲染线程的
FMaterialRenderProxy
对象,和资源对象UMaterial
- UMaterialInstanceConstant : 仅用于编辑器访问的
UMaterialInterface
实现,可以提供标量、向量、纹理和静态开关参数 - UMaterialInstanceDynamic : 运行时可被更改的
UMaterialInterface
实现,可以提供标量、向量、纹理参数,无法提供静态开关参数,且无法成为另一UMaterialInstance
的父项
场景渲染基本概念
- Primitive components and proxies
基本组件是可视性和相关性确定的基本单位。例如,遮蔽和视锥剔除都是按基元进行的。因此在设计系统时,考虑组件的大小十分重要。每个组件都有一个边界,用于多种操作,如剔除、阴影投射和光照影响确定。
组件只有在注册之后才会对场景(以及渲染器)可见。更改组件属性的游戏线程代码必须调用组件上的MarkRenderStateDirty()
,将更改传播到渲染线程。 - FPrimitiveSceneProxy and FPrimitiveSceneInfo
FPrimitiveSceneProxy
是UPrimitiveComponent
的渲染器版本,主要用于根据不同渲染目标类型将渲染目标归类,它存在与引擎模块中,在渲染通道中其某些函数会被调用,FPrimitiveSceneInfo
保存了每个UPrimitiveComponent
在渲染器内部的状态,为渲染器模块私有
下面按其所在的模块(引擎模块,渲染模块)列出了各种主类
Engine Module | Renderer Module |
---|---|
UWorld | FScene |
UPrimitiveComponent / FPrimitiveSceneProxy | FPrimitiveSceneInfo |
FSceneView | FViewInfo |
ULocalPlayer | FSceneViewState |
ULightComponent / FLightSceneProxy | FLightSceneInfo |
下面按其所在的线程(游戏线程,渲染线程)列出了各种主类
Engine Module | Renderer Module |
---|---|
UWorld | FScene |
UPrimitiveComponent | FPrimitiveSceneProxy / FPrimitiveSceneInfo |
FSceneView / FViewInfo | |
ULocalPlayer | FSceneViewState |
ULightComponent | FLightSceneProxy / FLightSceneInfo |
FPrimitiveSceneProxy 重要的渲染函数
- GetViewRelevance : 每帧开始的时候会在InitViews中被调用, 并返回一个初始化好的
FPrimitiveViewRelevance
对象,FPrimitiveViewRelevance
对象保存了渲染一些渲染标志信息如,改primitive是否支持光照,是否已经被绘制过了 等,一个Primitive有多个element, 每个element 都关联了自己的FPrimitiveViewRelevance对象,这表明,一个Primitive 可能既包含不透明的element,有包含透明的element,或者既包含静态的element又包含动态的element,它们并非相互排斥 - GetDynamicMeshElements : 该函数会收集所有的动态物体并在随后渲染
- DrawStaticElements : 绘制 primitive 的静态物体,静态图元仅当想关联的FPrimitiveViewRelevance对象声明为静态时被绘制
场景渲染顺序(Scene rendering order)
渲染器按照其希望将数据整合给渲染目标(render target)的顺序处理场景。例如,only Depth 的通道会比 Base 通道先渲染,先填充 Heirarchical Z (HiZ),从而降低基础通道(base pass)中的着色消耗。此顺序是按通道函数在 C++ 中调用的顺序静态决定的
渲染策略(Drawing Policies)
渲染策略(drawing policy)包含了通过通道特定的着色器渲染网格体(meshes)的逻辑, 它通过特定的FVertexFactory
接口来抽象网格(mesh)通过FMaterial
接口来抽象具体材质(material),在底层,一个渲染策略(drawing policy)拥有一系列的材质着色器,和一个 FVertexFactory对象,通过绑定FVertexFactory的顶点buffer和顶点着色器(mesh material shaders)到渲染硬件接口(Rendering Hardware Interface(RHI))并设置适当的着色参数,然后执行 RHI 绘制调用(RHI draw call)
绘制规则方法(Drawing Policy methods)
- Constructor : 从给定的顶点工厂(vertex factory)和材质着色器列表(material shader map)找出适当的着色器,并存储他们的引用。
- CreateBoundShaderState : 为绘制规则(Drawing Policy)创建绑定到RHI的着色器状态。
- Matches/Compare : 提供了排序该drawing policy和渲染列表(draw lists)中其他drawing policy的函数,Matches 必须比较 DrawShared 依赖的所有因素。
- DrawShared : 设置在从 Matches 返回 True 的绘制规则之间一致的 RHI 状态。例如,大多数绘制规则会为材质和顶点工厂排序,因此着色器参数只依赖可以设置的材质,并且可以绑定特定于该顶点工厂的顶点缓冲区。应尽可能在此处设置状态,而非在 SetMeshRenderState 设置,因为 DrawShared 在静态渲染路径中调用较少。
- SetMeshRenderState : 设置特定于此网格体的 RHI 状态,或 DrawShared 中未设置的状态。这比 DrawShared 调用的次数多得多,因此此处性能非常重要。
- DrawMesh : 实际发出 RHI 绘制调用。
渲染路径(Rendering paths)
UE4有静态渲染和动态渲染两个渲染路径,动态渲染路径可以被更灵活的控制但速度较慢,静态渲染路径(缓存尽可能靠近 RHI 级别的场景转换)速度较快,两条渲染路径的差异基本是在上层实现中,因为它们在底层都使用(Drawing polices)。 每个渲染批次(rendering pass | drawing policy)应该确保能够处理这两种渲染路径如果需要的话
动态渲染路径(Dynamic rendering path)
待查
静态渲染路径(Dynamic rendering path)
静态渲染路径通过静态渲染列表(static draw list)来实现, 所有场景中的网格(mesh)物体都会被添加到静态渲染列表中,在加入渲染列表时,渲染代理的DrawStaticElements
对象会收集FStaticMeshElements
对象,然后一个绘制策略(drawing policy)会被创建和保存,根据CrateBoundShaderState
的结果,这个新创建的渲染策略会被Compare
和Matches
函数进行排序并插入到渲染列表中的适当位置(参见 TStaticMeshDrawList::AddMesh
),在InitViews
函数中,一个包含了静态渲染列表中物体可视性的位数组(BitArray)会被初始化给TStaticMeshDrawList::DrawVisible
函数在具体绘制渲染列表的时候使用,DrawShared
只会在所有相同类型的渲染策略(Drawing Policy)被调用一次, 而 SetMeshRenderState
和DrawMesh
会在每次绘制FStaticMeshElement
(参见TStaticMeshDrawList::DrawElement
)的时候被调用
静态渲染路径会将大部分工作移动到链接阶段(attach time)来做,这对于加速场景转换(scene traversal)和缩短渲染时间很有意义,这样的话渲染线程渲染静态物体的时间可以提高3倍的效率,这样便可以放更多的静态物体到场景中,因为静态渲染列表会在链接阶段(attach time)将数据缓存,但也仅仅能够缓存与视口无关的状态(view independent stat),很少重新连接但经常需要渲染的单元(primitive)非常适合静态绘制列表
静态渲染路径可能会暴露出 bug,因为它每个状态桶只调用 DrawShared 一次。这些 bug 可能会很难发现,因为它们取决于场景中网格体的渲染顺序和连接顺序。特别的视图模式(如仅光照、无光照等)会强制所有基元使用动态路径,因此如果在强制动态渲染路径时 bug 消失,则其很可能是由于某绘制规则的 DrawShared 和/或 Matches 函数的错误实现而出现的。
总体渲染路径(High level Rendering order)
下面将说明从 FDeferredShadingSceneRenderer::Render 开始渲染一个帧时的简略控制流程
- GSceneRenderTargets.Allocate : 按需要重新分配全局场景渲染目标,使其对当前视图足够大。
- InitViews : 通过多种剔除方法为视图初始化基元可见性,设立此帧可见的动态阴影、按需要交叉阴影视锥与世界场景(对整个场景的阴影或预阴影)。
- PrePass / Depth only pass: RenderPrePass / FDepthDrawingPolicy 。渲染遮挡物,对景深缓冲区仅输出景深。该通道可以在多种模式下工作:禁用、仅遮蔽,或完全景深,具体取决于活动状态的功能的需要。该通道通常的用途是初始化 Hierarchical Z 以降低 Base 通道的着色消耗(Base 通道的像素着色器消耗非常大)。
- Base pass : RenderBasePass / TBasePassDrawingPolicy。渲染不透明和遮盖的材质,向 GBuffer 输出材质属性。光照图贡献和天空光照也会在此计算并加入场景颜色。
- Issue Occlusion Queries / BeginOcclusionTests : 提出将用于下一帧的 InitViews 的延迟遮蔽查询。这会通过渲染所查询物体周围的相邻的框、有时还会将相邻的框组合在一起以减少绘制调用来完成。
- Lighting : 阴影图将对各个光照渲染,光照贡献会累加到场景颜色,并使用标准延迟和平铺延迟着色。光照也会在透明光照体积中累加。
- Fog : 雾和大气在延迟通道中对不透明表面进行逐个像素计算。
- Translucency : 透明度累加到屏外渲染目标,在其中它应用了逐个顶点的雾化,因而可以整合到场景中。光照透明度在一个通道中计算最终光照以正确融合。
- Post Processing : 多种后期处理效果均通过 GBuffers 应用。透明度将合成到场景中。
着色器等级(shander feature level)
- SM5 : 通常对应于 D3D11 Shader Model 5,但由于 OpenGL 4.3 限制,仅有 16 种纹理可以使用。支持曲面细分、计算着色器和立方体贴图阵列。支持延迟着色路径。
- SM4 : 对应 D3D11 Shader Model 4,这与 SM5 基本相同,但没有曲面细分、计算着色器和立方体贴图阵列。支持延迟着色路径。不支持眼适应,因为其使用计算着色器。
- ES2 : 对应大多数 OpenGL ES2 移动设备支持的功能。使用削减向前着色路径。
更多推荐
所有评论(0)