Urho3D渲染

Urho3D的图形和渲染器子系统负责低级功能,如创建窗口、设置屏幕模式和管理GPU资源。渲染器执行3D视图的实际渲染,控制全局设置,并使用八叉树加速查询。渲染流程包括查询可见对象,构造渲染操作,按顺序执行渲染路径。文章还提到了优化技术,如遮挡测试和硬件实例化,以及如何处理GPU资源丢失。此外,讨论了额外的实例数据和不同渲染模式的使用情况。
摘要由CSDN通过智能技术生成

Urho3D中的大部分渲染功能都建立在两个子系统上,即图形和渲染器。

图形

图形实现了低级功能:

  • 创建窗口和渲染上下文
  • 设置屏幕模式
  • 跟踪GPU资源
  • 跟踪渲染上下文状态(当前渲染目标、顶点和索引缓冲区、纹理、着色器和渲染状态)
  • 加载着色器
  • 执行基本体渲染操作
  • 处理丢失的设备

    通过调用Graphics的SetMode()函数,可以同时设置屏幕分辨率、全屏/窗口、垂直同步和硬件多采样级别。在设置初始屏幕模式之前,还有一个实验选项,通过将其特定于操作系统的句柄传递给SetExternalWindow()来渲染现有窗口。

    设置初始屏幕模式时,Graphics会进行以下检查:

  • 对于Direct3D9,已检查着色器模型3.0支持。
  • 对于OpenGL,将首先检查3.2版支持,如果可用,则使用。作为备用方案,将检查带有EXT_framebuffer_object、EXT_packed_depth_template和EXT_texture_filter_各向同性扩展的2.0版本。ARB_instanced_arrays扩展也被检查,但不是必需的;它将在存在时启用硬件实例支持。
  • 是否支持硬件阴影映射?可以使用AMD和NVIDIA风格的阴影贴图。如果两者都不可用,则不会渲染阴影。
  • 是否支持灯光预处理和延迟渲染模式?这需要足够的多渲染目标支持和R32F纹理格式支持。

Renderer

   渲染器实现每帧3D视图的实际渲染,并控制全局设置,如纹理质量、材质质量、镜面照明和阴影贴图基础分辨率。

    要渲染,它需要一个具有八叉树组件的场景,以及一个不一定属于场景的摄影机。八叉树存储所有可见组件(从Drawable派生),以允许以加速方式查询它们。所需信息收集在Viewport对象中,该对象可以通过渲染器的SetViewport()函数指定。

   默认情况下有一个视口,但可以使用函数SetNumViewports()增加数量。视口应覆盖整个屏幕,否则可能会出现镜像大厅假象。通过指定零屏幕矩形,整个窗口将自动使用。视口将按升序渲染,因此,如果例如希望在主视口顶部有一个小的覆盖窗口,请将视口索引0用于主视图,将1用于覆盖。

   也可以为渲染目标纹理定义视口。有关详细信息,请参见辅助视图。

    每个视口定义用于渲染场景的命令序列,即渲染路径。默认情况下,bin/CoreData/RenderPath目录中存在前向、灯光预处理和延迟渲染路径,请参见SetDefaultRenderPath()为新视口设置默认值。如果未从命令行覆盖,则默认为正向渲染。一旦有大量的每像素灯光影响每个对象,延迟渲染模式将是有利的,但它们的缺点是缺少硬件多重采样,无法选择每种材质的照明模型。可以使用FXAA后处理边缘过滤器代替多采样抗锯齿,有关如何使用的示例,请参阅MultipleViewports示例应用程序(bin/Data/Scripts/09_MultipleViewports.as)。

  在每个帧上渲染每个视口的步骤大致如下:

  • 在八叉树中查询摄影机视图平截头体中的可见对象和灯光。
  • 检查每个可见光对对象的影响。如果灯光投射阴影,请在八叉树中查询阴影投射器对象。
  • 根据渲染路径命令序列中的场景过程,为可见对象构造渲染操作(批处理)。
  • 在帧末尾的渲染步骤期间执行渲染路径命令序列。
  • 如果场景具有调试渲染器组件,并且视口已启用调试渲染,则最后渲染调试几何体。可以使用SetDrawDebug()进行控制,默认设置为启用。

在默认渲染路径中,渲染操作按以下顺序进行:

  • 不透明几何体环境光过程,或延迟渲染模式下的G缓冲区过程。
  • 每个像素照明过程的不透明几何体。对于阴影投射灯光,首先渲染阴影贴图。
  • (仅限灯光预处理过程)不透明几何体材质过程,用于渲染具有累积每像素照明的对象。
  • 为自定义渲染排序(如skybox)发布不透明过程。
  • 折射几何体过程。
  • 透明几何体通过。透明的alpha混合对象根据距离排序,并从后向前渲染,以确保正确的混合。
  • alpha后传递,可用于应显示在所有其他内容之上的3D覆盖。

渲染组件

图形和UI库定义的渲染相关组件包括:

  • 八叉树Octree:用于加速可见性查询的Drawables空间分区。需要创建到场景(根节点。)
  • 相机Camera:描述用于渲染的视点,包括投影参数(FOV、近/远距离、透视/正交)
  • Drawable:任何可见对象的基类。
  • 静态模型StaticModel:非蒙皮几何体。可以根据距离进行LOD转换。
  • StaticModelGroup:渲染多个对象实例,同时将光作为一个单元进行消隐和接收。
  • 天空盒Skybox:StaticModel的一个子类,似乎总是保持不变。
  • 动画模型AnimatedModel:可以执行骨骼和顶点变形动画的蒙皮几何体。
  • 动画控制器AnimationController:自动向前驱动动画并控制动画淡入/淡出。
  • 广告牌组BillboardSet:一组面向摄影机的广告牌,可以具有不同的大小、旋转和纹理坐标。
  • 粒子发射器ParticleEmitter:BillboardSet的一个子类,用于发射粒子广告牌。
  • Ribbon轨迹RibbonTrail:创建对象后面的尾部几何体。
  • lighting灯光:照亮场景。可以选择投射阴影。
  • Terrain地形:渲染高度地图地形。
  • 自定义几何图形CustomGeometry:渲染运行时定义的未索引几何体。几何数据未通过网络序列化或复制。
  • 贴花集DecalSet:渲染对象顶部的贴花几何体。
  • Zone分区:定义分区体积内对象的环境光和雾设置。
  • Text3D:渲染到三维视图中的文本。

此外,还有Urho2D子库定义的2D可绘制组件。

优化

以下技术将用于减少渲染时CPU和GPU的工作量。默认情况下,它们都处于打开状态:

  • 软件光栅化遮挡:在八叉树中查询可见对象后,标记为遮挡的对象将在CPU上渲染到一个小的分层深度缓冲区,并将用于测试非遮挡的可见性。使用SetMaxOccluderTriangles()和SetOccluderSizeThreshold()配置遮挡渲染。遮挡测试将始终是多线程的,但是遮挡渲染默认情况下是单线程的,以允许在从前到后渲染时拒绝后续遮挡。。使用SetThreadOcclusion()也可以在渲染中启用线程,但在地形面片充当遮挡物的地形场景中,这实际上会表现得更差。
  • 硬件实例:具有相同几何体、材质和灯光的渲染操作将分组在一起,如果支持,将作为一个绘制调用执行。请注意,即使实例不可用,它们仍然可以从分组中受益,因为渲染状态只需要在渲染每个组之前检查和设置一次,从而降低了CPU成本。
  • 灯光模板遮罩:在前向渲染中,在由聚光灯或点光源照亮的对象被重新渲染之前,灯光的边界形状被渲染到模板缓冲区,以确保不处理灯光范围之外的像素。

请注意,在内容级别可能有更多的优化机会,例如,使用几何和材质LOD,将多个静态对象分组到一个对象中以减少绘制调用,最小化每个对象的子几何(子网格)数量以减少绘图调用,使用纹理图谱以避免渲染状态更改,使用压缩(和更小)纹理,以及设置对象、灯光和阴影的最大绘制距离。

重复使用视图准备

在某些应用程序中,如立体VR渲染,需要将稍微不同的世界视图渲染到不同的视口。通常,这会导致对每个视图重复视图准备过程(如上所述),这会对CPU性能造成成本。

为了消除重复视图准备成本,可以使用SetCullCamera()指示视口使用不同的摄影机进行剔除而不是渲染。当多个视口共享同一个剔除摄影机时,视图准备将仅执行一次。

要正常工作,剔除摄影机的平截头体应覆盖使用它渲染的所有视图,否则可能会出现丢失的对象。剔除摄影机不应使用自动纵横比模式,以确保您完全控制其视锥。

处理GPU资源丢失

   在Direct3D9和Android OpenGL ES 2.0上,由于应用程序窗口最小化到背景,可能会丢失渲染上下文(因此GPU资源)。此外,为了解决可能的GPU驱动程序错误,在更改屏幕模式或在全屏和窗口之间切换时,桌面OpenGL上下文将自动销毁并重新创建。因此,在所有图形API上,必须做好丢失GPU资源的准备。

   从文件加载的纹理以及启用了阴影的顶点和索引缓冲区将自动恢复其内容,其余部分必须手动恢复。在Direct3D9上,非动态(托管)纹理和缓冲区永远不会丢失,因为运行时会自动将它们备份到系统内存中。

   有关检测数据丢失的信息,请参见VertexBuffer、IndexBuffer、Texture2D、TextureCube和Texture3D类中的IsDataLost()函数。内置类(如Model、BillboardSet和Font)已经处理了其内部GPU资源的数据丢失,因此只需要对自定义缓冲区和纹理进行检查。尤其要注意尝试使用丢失后未初始化数据的索引缓冲区进行渲染,因为这可能会由于引用不存在的(垃圾)顶点而导致GPU驱动程序内部崩溃。

定义额外的实例数据

渲染系统自身提供的唯一每实例数据是对象的世界变换矩阵。如果要在自定义Drawable子类中定义额外的每个实例数据,请执行以下步骤:

  • 调用SetNumExtraInstancingBufferElements()。这定义了实例化数据将包含的额外Vector4的数量(除了变换矩阵之外)。
  • 自定义Drawable的SourceBatch结构需要指向额外的数据。请参见instancingData_成员。对于不需要定义额外数据的对象,允许使用空指针;请注意,在这种情况下,实例化顶点缓冲区将包含未定义的数据。
  • 由于非实例化渲染将无法访问额外数据,因此应禁用GEOM_STATIC绘图的非实例化渲染。使用参数1调用SetMinInstances()以完成此操作。
  • 在顶点着色器中使用额外的数据作为纹理坐标7(纹理坐标4-6是变换矩阵)

更多详情

另请参见顶点缓冲区、材质、着色器、灯光和阴影、渲染路径、骨骼动画、粒子系统、区域和辅助视图。

请参见渲染模式,以了解有关前向、灯光预处理和延迟渲染模式的详细讨论。

请参见渲染API之间的差异,了解直接使用低级渲染功能时需要注意的事项。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乘小舟舟,游大世界

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值