Cesium中级教程7 - Geometry and Appearances 几何图形和外观

Cesium中文网:http://cesiumcn.org/ | 国内快速访问:http://cesium.coinidea.com/javascript

本教程将向您介绍提供使用Primitive API的几何图形和外观系统。这是一个高级主题,用于扩展具备自定义网格、形状、体积和外观的CesiumJS,而不是面向通用的Cesium用户。若是您有兴趣学习如何在地球上绘制各类形状和体积,请查看建立实体教程。 CesiumJS可使用实体(如多边形和椭圆体)建立不一样的几何类型。例如,将如下代码复制并粘贴到Hello World Sandcastle示例中,以在球体上建立具备点模式的矩形:html

var viewer = new Cesium.Viewer('cesiumContainer');

viewer.entities.add({
    rectangle : {
        coordinates : Cesium.Rectangle.fromDegrees(-100.0, 20.0, -90.0, 30.0),
        material : new Cesium.StripeMaterialProperty({
            evenColor: Cesium.Color.WHITE,
            oddColor: Cesium.Color.BLUE,
            repeat: 5
        })
    }
});

在本教程中,咱们将深刻到遮光罩下,查看构成它们的几何图形和外观类型。几何图形定义了Primitive结构,即构成基本体的三角形、线或点。外观定义了Primitive的着色,包括其完整的GLSL顶点和面片着色,以及渲染状态。java

使用几何图形和外观的好处是:git

  • Performance(性能):在绘制大量Primitive(如美国每一个邮政编码的多边形)时,使用几何图形直接容许咱们将它们组合成单个几何图形,以减小CPU开销并更好地利用GPU。组合Primitive是在Web worker上完成的,以保持UI的响应性。
  • Flexibility(灵活):Primitive结合了几何图形和外观。经过分离它们,咱们能够独立地修改每个。咱们能够添加与许多不一样外观兼容的新几何图形,反之亦然。
  • Low-level access(低层级访问):外观提供接近金属的渲染访问,无需担忧直接使用Renderer的全部细节。外观使下列状况变得容易:
    • 写全部GLSL的顶点和面片着色器
    • 使用自定义渲染状态

固然也会有一些缺点:github

  • 直接使用几何图形和外观须要更多的代码和对图形更深刻的理解。实体处于适合映射应用程序的抽象级别;几何图形和外观的抽象级别更接近于传统的3D引擎
  • 组合几何图形对静态数据有效,对动态数据不必定有效。

让咱们使用几何图形和外观重写初始代码示例:canvas

var viewer = new Cesium.Viewer('cesiumContainer');
var scene = viewer.scene;

// original code
//viewer.entities.add({
//    rectangle : {
//        coordinates : Cesium.Rectangle.fromDegrees(-100.0, 20.0, -90.0, 30.0),
//        material : new Cesium.StripeMaterialProperty({
//            evenColor: Cesium.Color.WHITE,
//            oddColor: Cesium.Color.BLUE,
//            repeat: 5
//        })
//    }
//});

var instance = new Cesium.GeometryInstance({
  geometry : new Cesium.RectangleGeometry({
    rectangle : Cesium.Rectangle.fromDegrees(-100.0, 20.0, -90.0, 30.0),
    vertexFormat : Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT
  })
});

scene.primitives.add(new Cesium.Primitive({
  geometryInstances : instance,
  appearance : new Cesium.EllipsoidSurfaceAppearance({
    material : Cesium.Material.fromType('Stripe')
  })
}));

咱们使用Primitive(Primitive)代替矩形实体,它结合了几何图形和外观。如今,咱们将不区分GeometryGemometryInstance。实例不只是几何图形的实例,更是其的容器。app

为了建立矩形的几何图形,即覆盖矩形区域的三角形和适合球体曲率的三角形,咱们建立了一个RectangleGeometrydom

由于它在表面上,因此咱们可使用EllipsoidSurfaceAppearance。这经过假设几何图形在曲面上或在椭球体上方的恒定高度来节省内存。ide

Geometry types 几何图形类型

CesiumJS提供下列几何图形:性能

组合几何图形

当咱们使用一个Primitive绘制多个静态几何图形时,咱们看到了性能优点。例如,在一个Primitive中绘制两个矩形。

var viewer = new Cesium.Viewer('cesiumContainer');
var scene = viewer.scene;

var instance = new Cesium.GeometryInstance({
  geometry : new Cesium.RectangleGeometry({
    rectangle : Cesium.Rectangle.fromDegrees(-100.0, 20.0, -90.0, 30.0),
    vertexFormat : Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT
  })
});

var anotherInstance = new Cesium.GeometryInstance({
  geometry : new Cesium.RectangleGeometry({
    rectangle : Cesium.Rectangle.fromDegrees(-85.0, 20.0, -75.0, 30.0),
    vertexFormat : Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT
  })
});

scene.primitives.add(new Cesium.Primitive({
  geometryInstances : [instance, anotherInstance],
  appearance : new Cesium.EllipsoidSurfaceAppearance({
    material : Cesium.Material.fromType('Stripe')
  })
}));

咱们用不一样的矩形建立了另外一个实例,而后将这两个实例提供给Primitive。这将以相同的外观绘制两个实例。

有些外观容许每一个实例提供惟一的属性。例如,咱们可使用PerinstanceColorAppearance对每一个实例使用不一样的颜色进行着色。

var viewer = new Cesium.Viewer('cesiumContainer');
var scene = viewer.scene;

var instance = new Cesium.GeometryInstance({
  geometry : new Cesium.RectangleGeometry({
    rectangle : Cesium.Rectangle.fromDegrees(-100.0, 20.0, -90.0, 30.0),
    vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT
  }),
  attributes : {
    color : new Cesium.ColorGeometryInstanceAttribute(0.0, 0.0, 1.0, 0.8)
  }
});

var anotherInstance = new Cesium.GeometryInstance({
  geometry : new Cesium.RectangleGeometry({
    rectangle : Cesium.Rectangle.fromDegrees(-85.0, 20.0, -75.0, 30.0),
    vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT
  }),
  attributes : {
    color : new Cesium.ColorGeometryInstanceAttribute(1.0, 0.0, 0.0, 0.8)
  }
});

scene.primitives.add(new Cesium.Primitive({
  geometryInstances : [instance, anotherInstance],
  appearance : new Cesium.PerInstanceColorAppearance()
}));

每一个实例都有一个颜色属性。Primitive是用PerinstanceColorAppearance构造的,它使用每一个实例的颜色属性来肯定着色。

组合几何图形可使CesiumJS有效地绘制许多几何图形。下面的示例绘制2592个颜色独特的矩形。

var viewer = new Cesium.Viewer('cesiumContainer');
var scene = viewer.scene;

var instances = [];

for (var lon = -180.0; lon < 180.0; lon += 5.0) {
  for (var lat = -85.0; lat < 85.0; lat += 5.0) {
    instances.push(new Cesium.GeometryInstance({
      geometry : new Cesium.RectangleGeometry({
        rectangle : Cesium.Rectangle.fromDegrees(lon, lat, lon + 5.0, lat + 5.0),
        vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT
      }),
      attributes : {
        color : Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.fromRandom({alpha : 0.5}))
      }
    }));
  }
}

scene.primitives.add(new Cesium.Primitive({
  geometryInstances : instances,
  appearance : new Cesium.PerInstanceColorAppearance()
}));

Picking 拾取

实例合并后能够独立访问。为实例分配一个ID,并使用它来肯定是否使用Scene.Pick拾取该实例。

下面的示例建立一个带id的实例,并在单击该实例时将消息写入控制台。

var viewer = new Cesium.Viewer('cesiumContainer');
var scene = viewer.scene;

var instance = new Cesium.GeometryInstance({
  geometry : new Cesium.RectangleGeometry({
    rectangle : Cesium.Rectangle.fromDegrees(-100.0, 30.0, -90.0, 40.0),
    vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT
  }),
  id : 'my rectangle',
  attributes : {
    color : Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.RED)
  }
});

scene.primitives.add(new Cesium.Primitive({
  geometryInstances : instance,
  appearance : new Cesium.PerInstanceColorAppearance()
}));

var handler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
handler.setInputAction(function (movement) {
    var pick = scene.pick(movement.position);
    if (Cesium.defined(pick) && (pick.id === 'my rectangle')) {
      console.log('Mouse clicked rectangle.');
    }
  }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

使用id避免了在内存中,在Primitive构造以后,对整个实例的引用,包括几何图形。

Geometry instances 几何实例

实例可用于在场景的不一样部分定位、缩放和旋转相同的几何体。这是可能的,由于多个实例能够引用相同的Geometry,而且每一个实例能够具备不一样的modelMatrix。这容许咱们只计算一次几何图形,并屡次重复使用它。

如下示例建立一个EllipsoidGeometry和两个实例。每一个实例引用相同的椭球几何体,但使用不一样的modelMatrix放置它,致使一个椭球位于另外一个椭球之上。

var viewer = new Cesium.Viewer('cesiumContainer');
var scene = viewer.scene;

var ellipsoidGeometry = new Cesium.EllipsoidGeometry({
    vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT,
    radii : new Cesium.Cartesian3(300000.0, 200000.0, 150000.0)
});

var cyanEllipsoidInstance = new Cesium.GeometryInstance({
    geometry : ellipsoidGeometry,
    modelMatrix : Cesium.Matrix4.multiplyByTranslation(
        Cesium.Transforms.eastNorthUpToFixedFrame(Cesium.Cartesian3.fromDegrees(-100.0, 40.0)),
        new Cesium.Cartesian3(0.0, 0.0, 150000.0),
        new Cesium.Matrix4()
    ),
    attributes : {
        color : Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.CYAN)
    }
});

var orangeEllipsoidInstance = new Cesium.GeometryInstance({
    geometry : ellipsoidGeometry,
    modelMatrix : Cesium.Matrix4.multiplyByTranslation(
        Cesium.Transforms.eastNorthUpToFixedFrame(Cesium.Cartesian3.fromDegrees(-100.0, 40.0)),
        new Cesium.Cartesian3(0.0, 0.0, 450000.0),
        new Cesium.Matrix4()
    ),
    attributes : {
        color : Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.ORANGE)
    }
});

scene.primitives.add(new Cesium.Primitive({
    geometryInstances : [cyanEllipsoidInstance, orangeEllipsoidInstance],
    appearance : new Cesium.PerInstanceColorAppearance({
        translucent : false,
        closed : true
    })
}));

Updating per-instance attributes 更新实例属性

将几何图形添加到Primitive后,更新几何图形的每一个实例属性以更改可视化效果。每一个实例的属性包括:

  • Color: ColorGeometryInstanceAttribute决定了颜色实例。Primitive必须具备PerInstanceColorAppearance。
  • Show:boolean类型决定实例是否可见。全部实例都具备该属性。

下列展现了如何改变几何实例的颜色:

var viewer = new Cesium.Viewer('cesiumContainer');
var scene = viewer.scene;

var circleInstance = new Cesium.GeometryInstance({
    geometry : new Cesium.CircleGeometry({
        center : Cesium.Cartesian3.fromDegrees(-95.0, 43.0),
        radius : 250000.0,
        vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT
    }),
    attributes : {
        color : Cesium.ColorGeometryInstanceAttribute.fromColor(new Cesium.Color(1.0, 0.0, 0.0, 0.5))
    },
    id: 'circle'
});
var primitive = new Cesium.Primitive({
    geometryInstances : circleInstance,
    appearance : new Cesium.PerInstanceColorAppearance({
        translucent : false,
        closed : true
    })
});
scene.primitives.add(primitive);

setInterval(function() {
    var attributes = primitive.getGeometryInstanceAttributes('circle');
    attributes.color = Cesium.ColorGeometryInstanceAttribute.toValue(Cesium.Color.fromRandom({alpha : 1.0}));
},2000);

几何图形实例的属性能够被primitive使用primitive.getGeometryInstanceAttributes检索。attirbutes的属性能够直接被改变。

外观

几何定义结构。primitive的另外一个关键属性,appearance,定义了primitive的纹理,即单个像素的颜色。primitive能够有多个几何实例,但只能有一个外观。根据外观的类型,外观将具备定义着色的主体的material

CesiumJS具备下列外观:

外观定义了绘制Primitive时在GPU上执行的完整GLSL顶点和面片着色器。外观还定义了完整的渲染状态,它控制绘制primitvie时GPU的状态。咱们能够直接定义渲染状态,也可使用更高级的属性,如“闭合(closed)”和“半透明(translucent)”,外观将转换为渲染状态。例如:

// Perhaps for an opaque box that the viewer will not enter.
//  - Backface culled and depth tested.  No blending.

var appearance  = new Cesium.PerInstanceColorAppearance({
  translucent : false,
  closed : true
});

// This appearance is the same as above
var anotherAppearance  = new Cesium.PerInstanceColorAppearance({
  renderState : {
    depthTest : {
      enabled : true
    },
    cull : {
      enabled : true,
      face : Cesium.CullFace.BACK
    }
  }
});

建立外观后,不能更改其renderState属性,但能够更改其material。咱们还能够更改primitive的appearnace属性。

大多数外观还具备flatfaceForward属性,这些属性间接控制GLSL着色器。

  • flat:平面阴影。不要考虑照明。
  • faceForward:照明时,翻转法线,使其始终面向观众。回避背面的黑色区域,例如墙的内侧。

Geometry and appearance compatibility 几何图形和外观兼容

并不是全部外观都适用于全部几何图形。例如,EllipsoidSurfaceAppearance外观不适用于WallGeometry几何图形,由于墙不在球体的表面上。

要使外观与几何图形兼容,它们必须具备匹配的顶点格式,这意味着几何图形必须具备外观所期待的输入数据。建立几何图形时能够提供vertexFormat

几何图形的vertexFormat肯定它是否能够与其余几何图形组合。两个几何图形没必要是相同的类型,但它们须要匹配的顶点格式。

为方便起见,外观要么具备vertexFormat属性,要么具备可做为几何体选项传入的VERTEX_FORMAT静态常量。

var geometry = new Ceisum.RectangleGeometry({
  vertexFormat : Ceisum.EllipsoidSurfaceAppearance.VERTEX_FORMAT
  // ...
});

var geometry2 = new Ceisum.RectangleGeometry({
  vertexFormat : Ceisum.PerInstanceColorAppearance.VERTEX_FORMAT
  // ...
});

var appearance = new Ceisum.MaterialAppearance(/* ... */);
var geometry3 = new Ceisum.RectangleGeometry({
  vertexFormat : appearance.vertexFormat
  // ...
});

Resources 资源

参考文档:

更多材料请访问:Fabric 更多将来计划,请访问:Geometry and Appearances Roadmap

Cesium中文网交流QQ群:807482793 Cesium中文网:http://cesiumcn.org/ | 国内快速访问:http://cesium.coinidea.com/

相关文章
相关标签/搜索