外部渲染器

AMD: require(["geoscene/views/3d/externalRenderers"], (externalRenderers) => { /* 代码 */ });
ESM: import * as externalRenderers from "@geoscene/core/views/3d/externalRenderers";
对象: geoscene/views/3d/externalRenderers
起始版本: GeoScene API for JavaScript 4.0

SceneView 使用 WebGL 在屏幕上呈现地图/场景。 GeoScene API for JavaScript 提供了一个低级接口来访问 SceneView 的 WebGL 上下文,因此可以创建与场景交互的自定义可视化,其方式与内置图层的交互方式相同。 开发者既可以直接编写 WebGL 代码,也可以与第三方 WebGL 库集成。

注意事项

这个接口是实验性的。 在产品中使用之前,请仔细阅读以下信息:

  • 无法从 SceneView 内部实现细节中屏蔽此接口的用户。 因此,此接口应被视为 不稳定,并且会在即将发布的 GeoScene API for JavaScript 次要版本中发生变化
  • 由于 WebGL 和硬件加速 3D 渲染的复杂性,此界面只能由具有 WebGL 或 OpenGL 经验的专家开发人员使用。

    • WebGL 使用不当不仅会破坏自定义渲染,还会破坏 SceneView 本身的渲染。
    • GeoScene 不对自定义渲染代码中与 WebGL 渲染相关的问题或使用自定义渲染代码时在 SceneView 渲染中出现的问题提供任何支持。
  • 只有在特定条件下才能与第三方库集成。 具体来说,第三方库必须能够在与 SceneView 相同的 WebGL 上下文上工作,并且能够在每一帧中设置 WebGL 状态的相关部分。
  • 我们不鼓励同时使用多个自定义渲染器,尤其是当由多方开发时。

用法

外部渲染器必须注册到 SceneView 实例:

require(["geoscene/Map",
         "geoscene/views/SceneView",
         "geoscene/views/3d/externalRenderers"],
  function(Map, SceneView, externalRenderers) {
    let view = new SceneView({
      map: new Map({
        basemap: "tianditu-image",
        ground: "world-elevation"
      }),
      container: "viewDiv"
    });

    externalRenderers.add(view, myExternalRenderer);
  }
);

externalRenderers.add() 的第二个参数是一个对象,它必须至少包含 setuprender 两个方法:

let myExternalRenderer = {
  setup: function(context) {
    // Executed once after the external renderer is added to a view. You can use this function to allocate all static
    // WebGL resources (shaders, buffers, etc.)
  },
  render: function(context) {
    // Executed in every frame to draw geometry to the canvas. Tasks done in this function:
    // * Update the state of dynamic resources
    // * Set the WebGL state as needed for rendering
    // * Issue WebGL draw calls
  }
}

传递给外部渲染器对象的所有方法的 context 变量包含对 WebGL 的引用上下文,以及渲染所需的其他信息: RenderContext。 您可以直接在 WebGL 上下文中执行 WebGL 命令:

let myExternalRenderer = {
  vbo: null,
  setup: function(context) {
    this.vbo = context.gl.createBuffer();
    context.gl.bindBuffer(gl.ARRAY_BUFFER, this.vbo);
    let positions = new Float32Array([0, 0, 0,   1, 0, 0,   0, 1, 0]);
    context.gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW)
  },
  render: function(context) {
    // bind a shader program etc.
    context.gl.bindBuffer(gl.ARRAY_BUFFER, this.vbo);
    context.gl.drawArrays(gl.TRIANGLES, 0, 3);
  }
}

请求重绘

SceneView 仅在视图发生更改时渲染帧,例如当相机移动或有新数据可供显示时。 帧总是从头开始重新绘制,这意味着在绘制的每一帧中都会调用外部渲染器。 

如果外部渲染器需要重新绘制视图,例如因为数据已更改,它必须调用 externalRenderers.requestRender(view)。 这将触发要渲染的单个帧。 对于连续渲染,例如在动画期间,必须在渲染器内的每一帧中调用 externalRenderers.requestRender(view)

let myExternalRenderer = {
  render: function(context) {
    // update WebGL resources and execute draw calls
    externalRenderers.requestRender(view);
  }
}

管理 WebGL 状态

GeoScene API for JavaScript 在调用 setuprender 时保证所有 WebGL 状态变量都根据 WebGL 规范设置为各自的默认值。 唯一的例外是 gl.FRAMEBUFFER_BINDING 设置为内部使用的帧缓冲区。 有关更多详细信息,请参阅关于绑定正确渲染目标的部分。 作为回报,接口的用户需要在将控制权返回给 API 之前将 WebGL 上下文恢复到相同的状态。 不这样做可能会导致未定义的行为。 为方便起见,在传递给 setuprendercontext 参数上提供了一个 resetWebGLState() 函数 。 可以调用此函数来完全重置所有 WebGL 状态。 由于此函数保守地设置所有 WebGL 状态,因此可能会产生性能开销; 因此,我们建议用户跟踪被修改的特定 WebGL 状态,并手动重置该部分状态。 

绑定正确的渲染目标

在内部,SceneView 渲染到中间渲染目标,而不是 WebGL 上下文提供的默认帧缓冲区。 在调用 setuprender 时,此渲染目标已经绑定,并且将对正确的缓冲区进行绘图调用。 但是,如果您通过调用 gl.bindFramebuffer()绑定另一个帧缓冲区,请注意随后对 gl.bindFramebuffer(null) 的调用将不会绑定 GeoScene API for JavaScript 预期的正确渲染目标。 因此,之后发出的 WebGL 绘制调用不会显示在屏幕上。 相反,函数 bindRenderTarget() 在传递给 setuprenderRenderContext 参数上提供,它将绑定正确的颜色和深度缓冲区。

坐标系

在使用外部渲染器接口时,尤其是在 WebGL 的上下文中,必须在 SceneView 的内部渲染坐标系中指定坐标。 这个坐标系取决于视图的 viewingMode

  • 本地  查看模式下,它等于视图的空间参考定义的坐标系。
  • 全球查看模式下,它是一个 ECEF 坐标系,其中 X 轴指向 0°N 0°E,Y 轴指向 0°N 90°E,Z 轴指向北极。 虚拟地球被绘制成一个半径为 6378137 的完美球体,所以坐标系的单位应该是米。

externalRenderers-global-coordinate-system

您可以使用  toRenderCoordinates() 和 fromRenderCoordinates() 在渲染坐标系之间进行转换,而不必担心  viewingMode 和确切的坐标系定义。

精度问题

在全球场景中,32 位浮点算法的精度对于超越全球规模(即国家规模到城市规模)的可视化来说是不够的。 当将视图缩放到超过一定比例时,几何图形会出现摆动或抖动,并且通常会出现移位。 这同样适用于几何远离坐标系原点的局部场景。

通常,您应该确保在 JavaScript 中完成的所有算术都是以双精度完成的。 普通 JavaScript 算术就是这种情况,但您应该特别避免使用  Float32Array,除非您可以排除精度问题。

但是,WebGL 不支持 64 位浮点运算。 解决此限制的一种简单方法是渲染具有本地来源的场景:

  • 选择一个本地原点位置,大约在数据的中心。
  • 在将其传递到 WebGL 之前,从所有位置数据(顶点数据、制服等)中减去本地原点位置。
  • 通过原点平移视图变换矩阵(将视图变换矩阵预乘以原点平移矩阵)

这种技术将导致数据在局部坐标系中呈现,从而避免将数据放置在正确位置所需的大量数字。 如果数据覆盖大范围且细节丰富,则需要多个本地来源。 请注意,本地原点必须以 32 位浮点数精确表示,最好通过将本地原点本身存储为 Float32Array 来实现。

方法概述

名称 返回类型 总结 对象
更多信息

将外部渲染器添加到视图。

更多信息externalRenderers
更多信息

请贝尼特斯弗尔松场景视图构件使用特定网页图像呈现。

更多信息externalRenderers
Number[]|Float32Array更多信息

将位置从内部渲染坐标系转换为输出空间参考。

更多信息externalRenderers
RenderCamera更多信息

获取视图的当前相机的渲染表示。

更多信息externalRenderers
更多信息

从视图中移除一个外部渲染器。

更多信息externalRenderers
Number[]|Float32Array更多信息

计算一个 4x4 仿射变换矩阵,该矩阵构成从局部笛卡尔坐标系到虚拟世界坐标系的线性坐标变换。

更多信息externalRenderers
更多信息

请求重绘视图。

更多信息externalRenderers
Number[]|Float32Array更多信息

将位置从给定的空间参考转换到内部渲染坐标系。

更多信息externalRenderers

方法详情

add(view, renderer)static

向视图中添加一个外部渲染器。 外部渲染器是由一个对象,该对象包含一些方法和属性定义界定 ExternalRenderer

参数:
view SceneView

附加外部渲染器的视图。

renderer ExternalRenderer

外部渲染器。

forceWebGLContext(version)static

请求 SceneView 使用特定的 WebGL 版本进行渲染。 在创建视图之前调用此函数。 默认情况下,SceneView 在支持它的平台上使用 WebGL 2。 我们建议在未来的实现中使用 WebGL 2。

参数:
version Number

所需的上下文版本。

fromRenderCoordinates(view, srcCoordinates, srcStart, destCoordinates, destStart, destSpatialReference, count){Number[]|Float32Array}static

将位置从内部渲染坐标系转换为输出空间参考。 允许的输出空间参考是有限的,取决于 viewingMode:

  • global 模式下,它可以是 Web Mercator 或 WGS84。
  • local 模式下,它必须匹配 view.spatialReference,并且对该函数的调用只是将坐标从srcCoordinates 复制到 destCoordinates

如果不满足这些条件,则不会向 destCoordinates 写入任何内容,并且该函数返回 null

参数:
view SceneView

与输入视图坐标。

srcCoordinates Number[]|Float32Array

一个或多个向量的线性数组,被解释为 XYZ 坐标。 例如,两个位置向量将表示为 [x1, y1, z1, x2, y2, z2] 。 这必须至少包含 srcStart + 3 * count 个元素。

srcStart Number

srcCoordinates 中的索引坐标将从其开始读取。

destCoordinates Number[]|Float32Array

对结果将在其中写入数组的引用。

destStart Number

destCoordinates 中的索引坐标将在其中开始写。

destSpatialReference SpatialReference

空间输出的参考坐标。当 null 时,使用 view.spatialReference

count Number

要转换的顶点的数量。

返回:
类型 描述
Number[] | Float32Array 如果操作成功,则返回对 destCoordinates 的引用,否则返回 null
例子:
let cameraPositionGeographic = new Array(3);
externalRenderers.fromRenderCoordinates(view,
  context.camera.eye, 0,
  cameraPositionGeographic, 0, SpatialReference.WGS84,
1);
getRenderCamera(view){RenderCamera}static

获取视图的当前相机的渲染表示。 这与在渲染上下文中为外部渲染器传递的相机相同。

参数:
view SceneView

从中获取渲染相机的视图。

返回:
类型 描述
RenderCamera 返回一个渲染相机实例。
remove(view, renderer)static

从视图中移除外部渲染器。

参数:
view SceneView

要从中删除外部渲染器的视图。

renderer ExternalRenderer

外部渲染器。

renderCoordinateTransformAt(view, origin, srcSpatialReference, dest){Number[]|Float32Array}static

计算一个 4x4 仿射变换矩阵,该矩阵构成从局部笛卡尔坐标系到虚拟世界坐标系的线性坐标变换。 例如,此矩阵可用于将 3D 模型的顶点转换为渲染坐标系。

局部笛卡尔系统由其原点和以下轴定义定义:

  • X: 东
  • Y: 北
  • Z: 高度

externalRenderers-renderCoordinateTransformAt

view.viewingMode全球时,线性变换不考虑地球曲率或其他非线性投影方面。因此,生成的坐标只会在局部笛卡尔坐标系.原点周围的一个小区域内显示正确。

允许空间取决来源viewingMode 参考:

  • 全球模式下,它可以是 Web Mercator 或 WGS84。
  • 局部模式下,它必须匹配 view.spatialReference

如果不满足这些条件,则不会向 dest 写入任何内容,并且该函数将返回 null

参数:
view SceneView

将使用转换的视图。

本地笛卡尔坐标系中原点的全局坐标。

srcSpatialReference SpatialReference
optional

原点坐标的空间参考。 如果未定义,则改为使用 view.spatialReference

optional

对将存储 16 个矩阵元素的数组的引用。 生成的矩阵遵循 OpenGL 约定,其中平移分量占据第 13、14 和 15 个元素。 如果未定义,则返回一个新创建的矩阵。

 返回:
类型 描述
Number[] | Float32Array 如果操作成功,则返回对 dest的引用;否则返回 null
例子:
// places a tetrahedron in New York
let verticesLocal = [[10, 10, 10], [10, −10, −10], [−10, 10, −10], [−10, −10, 10]],
  transformation = new Array(16),
  geographicCoordinates = [
  //  lon     lat   elevation
      -74,   40.71,    10]

externalRenderers.renderCoordinateTransformAt(view, geographicCoordinates, SpatialReference.WGS84, transformation);

let verticesGlobal = verticesLocal.map(function(vertexLocal) {
  // transform the coordinates with the computed transformation (using the synthax of glMatrix, see http://glmatrix.net)
  return vec3.transformMat4(new Array(3), vertexLocal, transformation);
});
requestRender(view)static

视图重绘请求。

参数:
view SceneView

外部渲染器附加的视图。

toRenderCoordinates(view, srcCoordinates, srcStart, srcSpatialReference, destCoordinates, destStart, count){Number[]|Float32Array}static

将位置从给定的空间参考转换到内部渲染坐标系。 允许的输入空间参考是有限的,取决于 viewingMode

  •  全局 模式下,它可以是 Web Mercator 或 WGS84。
  • 局部模式下,它必须匹配 view.spatialReference; 对该函数的调用只是将坐标从 srcCoordinates 复制到 destCoordinates

如果不满足这些条件,没有向 destCoordinates  写入任何内容,并且该函数返回 null

参数:
view SceneView

将在其中使用坐标的视图。

srcCoordinates Number[]|Float32Array

一个或多个向量的线性数组,被解释为 XYZ 坐标。 例如,两个位置向量将表示为 [x1, y1, z1, x2, y2, z2]。 这必须至少包含 srcStart + 3 * count个元素。


srcStart Number

srcCoordinates 开始读的坐标中的索引。

srcSpatialReference SpatialReference

输入坐标的空间参考。 如果为 null,则改用 view.spatialReference

destCoordinates Number[]|Float32Array

对将写入结果的数组的引用。

destStart Number

对开始写入坐标的 destCoordinates 中的索引。

count Number

要变换的顶点数。

返回:
类别 描述
Number[] | Float32Array 如果操作成功,则返回对 destCoordinates 的引用,否则返回 null
例子:
// A linear list of coordinate triples
let geographicCoordinates = [
  //  lon     lat   elevation
    -117.19, 34.05,   414,
     47.39,   8.51,   408];

// Allocate storage for the result
let renderCoordinates = new Array(6);

externalRenderers.toRenderCoordinates(view,
  geographicCoordinates, 0, SpatialReference.WGS84,
  renderCoordinates, 0,
2);

类型定义

ColorAndIntensity Object

RGB 颜色值和强度值的元组。

属性:
color Vec3

值介于 0 和 1 之间的 RGB 颜色。

intensity Number

标量强度值,应根据该值缩放颜色以进行合成。

ExternalRenderer Object

使用回调和属性定义外部渲染器。

属性:
optional

通常在将外部渲染器添加到视图后或 SceneView 准备就绪时调用一次。 如果就绪状态循环,则可能会再次调用它,例如当将不同的 Map 分配给视图时。 接收 RenderContext 类型的单个参数。

optional

在每一帧中调用以执行状态更新和绘制调用。 接收 RenderContext 类型的单个参数。

optional

当从视图中移除外部渲染器时调用,或者当视图的就绪状态变为 false 时调用。 接收 RenderContext 类型的单个参数。

RenderCamera Object

RenderContext 中传递给渲染器回调的相机对象。 这与相机不同。 所有属性都是只读的,并根据内部渲染坐标系定义(请参阅本页顶部的坐标系部分)。

向量(Vec3Vec4)以数组的形式呈现。 矩阵 ( Mat4 ) 呈现为具有 16 个元素的线性数组,遵循 OpenGL 约定,其中平移分量占据第 13、14 和 15 个元素。

属性:
viewMatrix Mat4

将坐标从世界空间转换到相机空间的 4x4 矩阵。

viewInverseTransposeMatrix Mat4

viewMatrix 的逆转置,用于将法线从世界空间转换到相机空间。

projectionMatrix Mat4

一个4x4的矩阵,它定义透视投影变换。

eye Vec3

内部笛卡尔渲染坐标系中的摄像机的位置。

center Vec3

摄像机目标点("看")内部笛卡尔渲染坐标系中的位置。

up Vec3

摄像机载体。

near Number

到近裁剪面的距离。

far Number

到远平面的距离。

fovX Number

水平视图的字段。

fovY Number

垂直视图的字段。

pixelRatio Number

渲染像素比率。 这可用于调整屏幕尺寸,以便在以 HiDPI 呈现时正确匹配 CSS 像素尺寸。

viewport Vec4

视区(x、y、宽度、高度)。

RenderContext Object

该对象作为参数传递给每次调用以 setuprender 外部渲染器。

属性:

WebGL 渲染上下文。

camera RenderCamera

用于渲染当前帧的相机。

sunLight SunLight

 SceneView  用于渲染当前帧的光照。

resetWebGLState Function

提供了一个方便的功能,用于在使用后完全重置 WebGL 状态。

bindRenderTarget Function

绑定外部渲染器应该渲染到的颜色和深度缓冲区。

RenderContextCallback(context)

使用渲染上下文调用的回调(用于外部渲染器的设置和渲染阶段)。

参数:
context RenderContext
optional

渲染上下文。

SunLight Object

描述 SceneView 使用的光照,源自其太阳光照模型。 它由一个定向朗伯( diffuse )项和一个常数( ambient )项组成,应该在 Phong 反射模型 的意义上进行处理。

属性:
direction Vec3

渲染坐标中的入射光方向。

漫射光的颜色和强度。

环境光的颜色和强度。

Your browser is no longer supported. Please upgrade your browser for the best experience. See our browser deprecation post for more details.