Skip to content

RoyObject3D

RoyObject3D是引擎侧所表达的最小绘制单元,以RoyMeshComponent为例,会产生一个或者多个RoyObject3D对象。RoyMeshComponent是一个网格模型,这个网格模型可能分成不同的部分,比如一个门,有门板还有门把手,那么实际中至少会产生两个RoyObject3D对象。所以RoyMeshComponent持有了RoyObject3D对象的一个列表。

RoyObject3D持有渲染资源RoyMesh和RoyMaterial,同时明确以何种图元绘制数据。

除了RoyMeshComponent以外,所有想在渲染中产生渲染单元的组件,都会持有RoyObject3D对象或其列表,比如线条绘制的组件RoyWireframeComponent,逻辑侧进行了批次合并的组件RoyMeshBatchComponent等。

RoyObject3D的存在还为批次合并提供了更加灵活的操作可能。比如场景中通过各种不同的组件添加了100个RoyObject3D对象,绘制需要100个批次。那么在底层很容将这些RoyObject3D进行分类,比如RoyMesh相同的分一组,在分组基础上RoyMaterial相同的再次分组,形成一个个小的集合。那么可以针对这些小的集合进行批次合并,生成新的RoyObject3D对象用于绘制。可能执行合并批次之后只有10个合并的RoyObject3D对象,这样批次就从100减少到10。从这个角度上看,RoyObject3D是可以渲染的,但并不是创建出来就一定会被渲染,有可能添加到某个代理对象中,和其他类似的RoyObject3D整合,再做出渲染动作。

说到合批,如何划分集合,如何达到批次和顶点数的平衡,这里就会有很多策略,目前引擎主要提供了以下策略,大概了解就好:

  • 在业务侧就合并好,通过RoyMeshBatchComponent直接形成RoyObject3D对象,这种对业务的要求比较高,一般来说不太推荐这种方式,除非你非常清楚你的行为。在这种行为下,产生的渲染卡顿,一般引擎底层都无能为力。
  • 业务侧不做合并,交给引擎策略来进行,策略有以下几种:
    • RoyInstanceHelper:通过硬件实例化的方式来批量绘制,要求几何体和材质模板都相同,仅空间位置和若干材质参数不同。
    • RoyBatchHelper:引擎侧将某一个RoySceneNode及其子孩子上挂接的所有组件而产生的RoyObject3D进行几何体合并。要求材质相同,空间位置可不同
    • 在上面两种策略之上的策略,即使材质不同,以TextureArray的方式进行再次抽离封装,这种可以忽略diffuse贴图不同的限制,达到最大程度的压缩,但也是双刃剑要根据实际的应用场景来决定是否开启。

以上是引擎内部的实现,对于业务层的开发者来说,无需太过深入,仅做了解即可。

对于RoyObject3D的属性,其在RoyProtocal中的结构体对应,摘要如下:

typescript
/**
 * Interface for serializing and deserializing RoyObject3D data
 */
interface RoyObject3DData extends RoyTransDataInfo {
    /** name*/
    name: string;
    /** Reference of parent scene of this object */
    parentSceneName: string;
    /** Reference of parent scene node of this object */
    parentSceneNode: string;
    /** Reference of parent component of this object */
    parentMeshComp: string;
    /** Whether mouse interaction is enabled for this object */
    mouseEnabled?: boolean;
    /** Whether frustum culling is enabled for this object */
    cullEnabled?: boolean;
    /** The primitive type of the object */
    primitiveType?: string;
    /** The index offset of the object */
    idxOffset: number;
    /** The index count of the object */
    idxCount: number;
    /** Reference of material of the object */
    material: string;
    /** The priority of the object */
    royPriority?: string;
    /** Whether the object casts shadows */
    castShadow?: boolean;
    /** Whether the object receives shadows */
    receiveShadow?: boolean;
    /** The visible layer of the object */
    visibleLayer?: number;
    /** The light mask of the object */
    lightMask?: number;
    /** Whether draft normals are excluded for this object */
    excludeDraftNormal?: boolean;
    /** Whether mouse interaction is enabled for this object when it is invisible */
    mouseEnabledOnInvisible?: boolean;
    /** The priority of mouse interaction for this object */
    mousePriority?: number;
    /** The draft ID of the object */
    draftID?: number;
    /** The batch matrix of the object */
    batchMatrix?: number[];
    /** The batch count of the object */
    batchCount?: number;
}