Primitive与Entity的区别

Primitive

        Primitive 是一种面向图形开发人员的底层 API,它提供了对 WebGL 图形的直接访问。它通常用于描述⼀组简单的图形几何体。例如,我们可以使用Primitive来绘制点、线、多边形、体积、⽂本等基本图形。每个Primitive实例都可以设置不同的属性,例如颜⾊、边框、宽度、⾼度等

Primitive通常由以下几个部分组成

1、几何数据:几何数据定义了Primitive图元的三维形状,通常由顶点和索引组成

2、材质:材质定义了Primitive图元的表面外观,包括颜色、纹理等。

3、着色器:着色器是用于计算Primitive图元每个像素的颜色值的程序,它可以根据几何数据和材质计算出最终的像素颜色

用法:

        使用Primitive创建圆并渲染到场景中,创建一个Primitive必须设置 geometry与  appearance  两个属性,才能在场景中渲染出来

        每个Geometry是通过GeometryInstance来进行实例化的,通过GeometryInstance对Geometry进行实例化,同一个Geometry可以被实例化多次。这对于展示大量数据时很有用,比如有10万个BoxGeometry需要被显示,只需要创建一个BoxGeometry,然后通过GeometryInstance来设置每一个的大小、位置、颜色等

优点:

1、灵活度高,因为Primitive由Geometry和Appearance构成,我们可以单独修改它们

2、性能好,使用Primitive可以将多个Geometry合并为一个大的Geometry来减少CPU的使用,利用GPU

3、自定义渲染强,我们有很大的可编程性,可以操作顶点着色器与片元着色器

4、更接近 WebGL,可以优化渲染流程以提高性能

5、更易于扩展,Primitive图元可以更方便地扩展到大型数据集,而Entity则会遇到性能瓶颈

缺点:

1、对于动态数据不友好,使用primitive组合多个geometry时无法更新geometry

2、更难使用,Primitive图元需要更复杂的代码来创建和管理,因此对开发人员的要求更高

3、较少的⾃动性和灵活性,因为需要⼿动处理许多问题,例如碰撞检测、 ⾼级光照和渲染技术等

4、更难调试,Primitive图元更难调试,因为它们通常包含大量几何数据和着色器代码

Entity

        Entity 提供了一种更加高级别的数据驱动 API,它简化了数据和可视化的管理。每个Entity 都可以代表一个现实世界中的对象,并且可以携带各种属性(如位置、速度、模型、纹理等),这些属性会自动映射到底层的Primitive 上 。它通常用于描述具有坐标位置的实际对象,例如⻜机、汽⻋、楼 房、⼈物等。每个Entity实例都有不同的属性,例如位置、姿态、缩放、颜⾊、贴图等,并且可以通过编程⽅式创建、修改、删除

        Entity的优点是⾮常灵活和易于使用。由于Entity是更⾼层次的概念,因此它可以⾃动处理许多与底层图 形和几何形状相关的复杂性,例如纹理贴图、光照、碰撞检测等。它还可以与其他Cesium组件集成,例 如事件处理、拾取和相机控制等。

用法:

特点:

1、易于使用:封装了大部分细节,使得开发者可以专注于应用逻辑而不是图形细节

2、一致性设计:API 设计一致,易于理解和记忆

3、动态属性支持:Entities 支持动态属性,这意味着可以轻松地在运行时更改对象的属性,如位置、颜色和形状等

4、性能略逊于 Primitive:虽然封装了细节,但在大规模数据渲染时可能会略逊于直接使用Primitive

        总的来说,Entity和Primitive都是Cesium中强⼤的图形概念。Entity最终会转为primitive来进行渲染。Entity是一个封装了primitive的高级抽象。在某些情况下,可以在程序中混合使用,已实现最佳性能和易用性。

何时选择 Primitive 或 Entity

使用 Entity:

1、当需要快速开发原型或简单的应用程序时

2、当应用不需要极端的性能优化时

3、当团队成员不熟悉底层图形编程时

4、如果需要描述具有复杂属性和⾏为的实际对象

5、如果应用需要动态更新模型的位置、旋转或颜色,那么使用Entity 就更加方便,因为我们可以直接修改Entity 的属性,而不需要直接操作Primitive

使用 Primitive:

1、当需要极致的性能优化时

2、当项目涉及复杂的图形效果或自定义渲染逻辑时

3、当团队中有经验丰富的图形程序员时

4、如果只需要绘制简单的几何体,那么我们可以使⽤Primitive来获得更好的性能和控制

5、当需要在一个应用中渲染大量静态模型,而这些模型不需要任何动态属性更新(比如位置、旋转)。在这种情况下,使用Primitive 将更为合适,因为它避免了Entity 中不必要的数据更新开销,从而提高了加载效率

<think>我们正在处理用户关于CesiumPrimitiveEntity在开启地形深度监测时的渲染层级关系的问题。用户的问题是:为什么开启地形深度监测时,Entity渲染在Primitive的下面? 根据提供的引用材料,我们可以总结如下: 1. Entity API是在Primitive API基础上封装的高级API,更易于使用,但底层仍然使用Primitive(引用[1][2][3])。 2. Primitive API是底层图形API,直接控制图形绘制,效率高,但使用复杂(引用[2][3])。 3. 当添加Entity时,Cesium会在底层创建对应的Primitive对象(引用[1])。 关于地形深度监测(terrain depth testing),这是Cesium中用于使物体地形表面正确融合的技术。开启地形深度监测后,物体会根据地形深度进行深度测试,从而正确地显示在地形之上或之下。 现在,回答用户的问题:为什么开启地形深度监测时,Entity渲染在Primitive的下面? 原因可能涉及Cesium的渲染顺序深度测试机制。在Cesium中,渲染顺序通常由多个因素决定,包括: - 渲染通道(例如,不透明物体、半透明物体) - 相机的距离(用于排序半透明物体) - 以及显式的渲染顺序设置 根据Cesium的渲染流程,地形本身是一个复杂的几何体,而PrimitiveEntity最终都会被转换为Primitive(或PrimitiveCollection)进行渲染。 在开启地形深度监测后,Cesium会为地形生成深度纹理(depth texture),然后其他需要地形进行深度测试的物体(如PrimitiveEntity)将使用这个深度纹理进行深度测试。 然而,EntityPrimitive在添加到场景中时,它们的渲染顺序可能不同。默认情况下,Entity的渲染顺序可能被设置为在地形之后渲染,而Primitive则可能被设置为在地形之前渲染(或者反过来)。具体来说: - Entity通常被设计为地形交互,因此默认情况下,Entity的图形(如点、线、面)会开启深度测试,并且可能被设置为在场景中的地形之后渲染,这样它们就可以正确地地形表面融合,即Entity会在地形之上(如果Entity的图形高度高于地形)或之下(如果低于地形)显示。 - 但是,用户观察到的现象是Entity渲染在Primitive的下面(即被Primitive遮挡),这通常是因为Primitive的渲染顺序设置在了Entity之前(即更早渲染),而Entity的渲染顺序设置在了后面(较晚渲染),同时开启了深度测试深度写入,导致后渲染的Entity如果Primitive有重叠,且深度值在Primitive之后,则会被遮挡。 另一种可能的解释是:Primitive在创建时,其深度测试深度写入的设置可能Entity不同。例如,Primitive可能默认关闭了深度写入(但开启了深度测试),这样它不会遮挡后面的物体,而Entity则可能默认开启了深度写入,导致在渲染顺序上,如果先渲染Primitive再渲染Entity,那么Entity会覆盖Primitive;反之,如果先渲染Entity再渲染Primitive,则Primitive会覆盖Entity。 但是,根据用户描述,开启地形深度监测时,EntityPrimitive下面(即被Primitive遮挡),说明在渲染顺序上,PrimitiveEntity之后渲染,并且Primitive的深度值更靠近相机(即位于Entity之上)。 然而,在Cesium中,渲染顺序并不是简单的按照添加顺序,而是由多个因素决定,包括: - 是否属于透明物体(半透明物体通常按从远到近的顺序渲染) - 显式设置的渲染顺序(例如,通过`primitive.depthFailAppearance`或`primitive.appearance`中的`renderState`设置深度测试深度写入,以及通过`primitive.zIndex`设置顺序) 值得注意的是,Entity在底层转换为Primitive时,可能会被添加到不同的PrimitiveCollection中。Cesium的渲染器会按照特定的顺序遍历这些集合。例如,地形本身在一个集合,而其他Primitive可能在另一个集合。Entity生成的Primitive通常被添加到`scene.primitives`集合中,而用户直接创建的Primitive也可能被添加到同一个集合或不同的集合(如`groundPrimitives`)。 在默认情况下,`scene.primitives`集合中的对象按照添加顺序渲染(除非设置了排序标志)。因此,如果先添加Entity(生成的Primitive),后添加用户创建的Primitive,那么用户创建的Primitive将在Entity之上渲染(因为后添加的Primitive默认在集合的后面,而集合的渲染顺序是从前往后,即先添加的先渲染,后添加的后渲染,后渲染的会覆盖先渲染的,如果深度测试通过)。 但是,用户观察到的是EntityPrimitive下面,也就是说EntityPrimitive遮挡。这可能是由于以下原因之一: 1. 渲染顺序:用户先添加了Primitive,然后添加了Entity,这样Entity(后添加)会渲染在Primitive(先添加)的上面(因为后添加的Primitive在集合中排在后面,后渲染)。但是,如果开启了深度测试,那么渲染顺序就不只是由添加顺序决定,还要看深度值。如果Primitive的深度值更小(离相机更近),那么即使先渲染Primitive,后渲染EntityEntity也会因为深度测试失败(被Primitive遮挡)而不被绘制。因此,遮挡关系主要由深度值决定,而不仅仅是渲染顺序。 2. 深度测试设置:Entity生成的Primitive可能开启了深度测试,而用户创建的Primitive可能没有开启深度测试,或者深度测试设置不同(例如,深度测试函数不同),导致渲染结果不同。 3. 地形深度监测的影响:开启地形深度监测后,所有物体不仅要地形深度进行比较,还要其他物体的深度进行比较。如果Entity的位置高度低于Primitive的位置高度,那么Entity就会在Primitive的下面(被遮挡)。但用户的问题中并没有明确两者在高度上的差异,所以假设它们在相同位置。 因此,我们需要更具体地分析开启地形深度监测时Cesium的渲染流程: - 地形深度监测开启后,Cesium会先渲染地形到深度纹理(深度预渲染阶段)。 - 然后,在渲染其他物体(如PrimitiveEntity)时,会使用这个深度纹理进行深度测试(即地形深度进行比较),同时也会进行物体之间的深度测试(通过深度缓冲区)。 在物体之间的深度测试中,深度值由物体在场景中的位置决定。所以,如果PrimitiveEntity在同一位置,那么它们的深度值相同,此时渲染顺序就很重要:后渲染的会覆盖先渲染的(如果深度测试函数是LEQUAL,则相同深度时,后渲染的通过测试并覆盖)。 但是,用户观察到EntityPrimitive下面,说明Entity被先渲染,然后Primitive被后渲染并且覆盖了Entity。这可能是由于: - 用户先添加了Entity(生成的Primitive),后添加了Primitive(用户创建的Primitive),所以Entity先渲染,Primitive后渲染,并且覆盖了Entity。 然而,用户的问题中描述的是“Entity渲染在Primitive的下面”,这上述解释一致:先添加的Entity(先渲染)被后添加的Primitive(后渲染)覆盖。 但是,为什么用户会特别提到“开启地形深度监测时”?可能是因为在没有开启地形深度监测时,所有物体都不地形进行深度测试,而物体之间的深度测试仍然存在。但是,开启地形深度监测后,由于地形深度纹理的影响,可能会导致物体在地形深度比较时被地形遮挡,而物体之间的遮挡关系并没有改变。所以,用户观察到的现象可能不是因为地形深度监测直接导致的,而是由于物体之间的深度测试渲染顺序。 然而,根据Cesium的官方文档源码,EntityPrimitive在开启地形深度监测时,它们的深度测试设置可能不同。特别是,Entity生成的Primitive在创建时可能会根据Entity的属性设置深度测试相关参数(如`depthTest``depthFail`等)。例如,Entity的线(如折线)可能会开启`depthFail`(深度测试失败时应用的外观),这样当线在地形下面时,会以不同的样式显示(如虚线)。 因此,可能的原因是在开启地形深度监测后,Entity生成的Primitive被设置为深度测试失败时使用特殊外观(即在地形以下的部分),而用户创建的Primitive可能没有设置,导致它始终显示在Entity之上(无论地形如何)。但这并不能直接解释为什么EntityPrimitive的下面(遮挡关系)。 另一种可能是,在开启地形深度监测后,Cesium调整了渲染顺序,将地形相关的Primitive(包括Entity生成的Primitive)放在地形深度测试的特定阶段,而用户创建的Primitive则被放在另一个阶段渲染。具体来说: - Cesium在渲染时,首先渲染不透明物体(包括地形),然后渲染半透明物体(按从远到近排序)。 - 对于需要地形深度测试的物体(如Entity),Cesium可能会将它们分为两类:一类是贴在地面上的(如点、线、面),另一类是浮在空中的(如广告牌、3D模型)。贴在地面上的物体会在渲染地形之后立即渲染,而浮在空中的物体则可能在地形渲染之后的其他阶段渲染。 但是,用户创建的Primitive可能被归类为不透明物体(如果它的外观是不透明的),而Entity生成的Primitive可能被归类为半透明物体(如果Entity设置了透明度),这样就会导致渲染顺序不同:不透明物体先渲染(包括地形用户创建的Primitive),然后半透明物体(Entity)后渲染,并且半透明物体只能在不透明物体的缝隙中显示(即被不透明物体遮挡的部分将不可见)。 综上所述,根本原因可能是: 1. 用户创建的PrimitiveEntity生成的Primitive在渲染顺序上不同(由于它们被添加到不同的集合,或者具有不同的渲染状态)。 2. 开启地形深度监测后,Entity生成的Primitive可能会被调整到特定的渲染阶段(如地形深度测试阶段),而用户创建的Primitive则可能被视为普通物体,在另一个阶段渲染,导致覆盖关系变化。 具体到Cesium源码,我们可以参考以下流程: - 在`Scene.js`的`render`函数中,渲染顺序大致如下: a. 天空盒、星空 b. 太阳、月亮 c. 不透明物体(包括地形、3D Tiles等) d. 半透明物体(按距离排序) Entity生成的Primitive(通过`PrimitiveCollection`)通常被添加到`scene.primitives`中,而地形则有自己的`globe`对象。在渲染不透明物体时,会先渲染地形,然后渲染`scene.primitives`中的不透明物体(按添加顺序),然后渲染半透明物体(按从远到近)。 如果用户创建的Primitive是不透明的,而Entity生成的Primitive是半透明的(比如设置了透明度),那么用户创建的Primitive会在半透明物体之前渲染,因此它可能会遮挡后面渲染的半透明Entity。 因此,如果用户看到的Entity是半透明的(或者部分透明),那么它会被归入半透明物体,而用户创建的Primitive如果不透明,则会在半透明物体之前渲染,从而遮挡Entity。 但是,如果两者都是不透明的,那么它们的渲染顺序就由添加顺序决定(在同一个集合中,先添加的先渲染,后添加的后渲染,后渲染的覆盖先渲染的)。 所以,用户观察到EntityPrimitive下面,可能是因为: - 用户先添加了Entity(生成的Primitive),然后添加了用户创建的Primitive(不透明),所以用户创建的Primitive后渲染,覆盖了Entity。 - 或者,用户创建的Primitive被添加到了`groundPrimitives`集合(这个集合在地形之后渲染,但在`scene.primitives`之前),而Entity被添加到`scene.primitives`,所以`groundPrimitives`中的Primitive会先于`scene.primitives`中的Entity渲染,导致Entity覆盖Primitive。但用户观察到的是Entity在下面,所以这种情况不符合。 因此,最可能的原因是添加顺序:先添加Entity,后添加Primitive,导致PrimitiveEntity之上渲染。 但是,用户的问题特别提到开启地形深度监测时出现这种情况。在没有开启地形深度监测时,物体之间的深度测试仍然存在,所以遮挡关系应该相同。那么为什么用户会注意到开启地形深度监测后才出现呢?可能是因为在没有开启地形深度监测时,EntityPrimitive都不地形进行深度测试,所以它们可能都显示在地形之上(即使高度低于地形),这样它们之间的遮挡关系可能被地形遮挡所掩盖。而开启地形深度监测后,EntityPrimitive都正确地地形进行深度测试,此时它们之间的遮挡关系就变得明显。 因此,结论是:开启地形深度监测后,EntityPrimitive的渲染层级关系(遮挡关系)主要由它们的添加顺序(在同一个集合中)深度值决定。如果用户先添加Entity,后添加Primitive,那么Primitive会覆盖Entity(即EntityPrimitive下面)。要改变这种关系,可以调整添加顺序,或者使用`primitive.show`属性控制显示,或者通过设置`depthFail`外观来处理深度测试失败的情况。 最后,回答用户问题:开启地形深度监测时,Entity渲染在Primitive的下面,可能是因为用户先添加了Entity,后添加了Primitive,导致PrimitiveEntity之上渲染。同时,由于Primitive的深度值可能更靠近相机(或者相同位置时由于后渲染而覆盖),从而遮挡了Entity。 建议用户检查添加顺序,并考虑调整添加顺序或设置Primitive的`depthFailAppearance`来改变显示效果。 生成相关问题: 1. 如何调整CesiumPrimitiveEntity的渲染顺序? 2. 地形深度监测对Cesium渲染性能有什么影响? 3. 如何设置Primitive的深度测试属性以避免被其他物体遮挡?</think>### CesiumEntityPrimitive的深度渲染层级分析 在Cesium中开启地形深度监测(`terrainDepthTesting`)时,Entity渲染在Primitive下方的根本原因在于两者的**渲染管线差异****深度测试机制**。以下是具体分析: #### 1. **渲染流程差异** - **Primitive API**:直接对接图形底层(如WebGL),通过`PrimitiveCollection`管理,其渲染顺序由添加到场景的顺序决定(后添加的覆盖先添加的)。开启地形深度监测后,Primitive会参**全局深度测试**,包括地形深度缓冲区。 - **Entity API**:Entity在底层被转换为Primitive(通过`EntityCluster`),但转换后的Primitive会被添加到**独立渲染队列**中[^1][^3]。该队列默认在原生Primitive之后渲染,导致Entity生成的图形被后渲染的Primitive覆盖。 #### 2. **深度测试机制的影响** - 开启地形深度监测后,Cesium会生成**地形深度纹理**(depth texture),所有图形需此纹理进行深度比较。 - Primitive直接使用深度纹理进行测试,其深度值计算基于**模型空间坐标**。 - Entity生成的图形需经过**额外的坐标转换**(因Entity绑定到时间动态数据),导致深度值计算延迟。当同一位置存在Primitive时,Entity的深度值可能被判定为“更远”[^2][^4]。 #### 3. **底层实现差异** ```mermaid graph LR A[Entity添加] --> B[EntityCluster转换为Primitive] B --> C{添加到专用队列} D[原生Primitive添加] --> E{添加到主队列} E -->|渲染顺序| F[主队列先渲染] C -->|渲染顺序| G[专用队列后渲染] F --> H[深度测试通过] G --> I[被先渲染的Primitive遮挡] ``` #### 解决方案(强制Entity在上层渲染) ```javascript // 方法1:调整Entity生成的Primitive渲染顺序 entity.primitive = new Cesium.Primitive({ appearance: /* ... */, renderState: { depthTest: { enabled: true, func: Cesium.DepthFunction.LESS_OR_EQUAL // 修改深度比较函数 } }, zIndex: 100 // 提高渲染层级 }); // 方法2:将Entity转换为Primitive并手动控制 const primitive = viewer.scene.primitives.add( Cesium.Primitive.fromEntity(entity) ); primitive.zIndex = 100; // 置于顶层 ``` > **关键结论**:Entity因封装层导致的渲染队列滞后深度计算延迟,使其在开启地形深度监测时易被Primitive遮挡。可通过直接操作底层Primitive的`zIndex`或修改深度测试函数强制调整层级[^3][^4]。 --- ### 相关问题 1. **如何优化CesiumEntityPrimitive混合渲染的性能?** 2. **地形深度监测开启后,如何调试深度测试失败的问题?** 3. **Entity API在哪些场景下不适合使用?应如何替代?** [^1]: 官方教材中提到,Primitive API主要适用于图形渲染开发者,Entity API则适用于数据驱动的可视化,而Entity API的底层则使用了Primitive API。 [^2]: CesiumPrimitiveEntity详细介绍。Cesium为开发者提供了丰富的图形绘制空间数据管理的API。 [^3]: entity是在primitive的基础上又进行了一次封装,对于开发者来说使用api更简单更容易。 [^4]: Cesium: Primitive vs EntityCesium | Primitive图元介绍及Entity对比。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值