Appearance
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;
}