1. 引言

Cesium是一款三维地球和地图可视化开源JavaScript库,使用WebGL来进行硬件加速图形,使用时不需要任何插件支持,基于Apache2.0许可的开源程序,可以免费用于商业和非商业用途

Cesium官网:Cesium: The Platform for 3D Geospatial

Cesium GitHub站点:CesiumGS/cesium: An open-source JavaScript library for world-class 3D globes and maps (github.com)

API文档:Index - Cesium Documentation

通过阅读源码,理清代码逻辑,有助于扩展与开发,笔者主要参考了以下两个系列的文章

渲染是前端可视化的核心,本文描述Cesium渲染模块的Buffer

2. WebGL中的Buffer

以下大致是一个最简的WebGL绘制代码:

<canvas id="canvas"></canvas>
<script>
const vertexSource = `
attribute vec3 aPos; void main()
{
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
}
`
const fragmentSource = `
void main()
{
gl_FragColor = vec4(1.0, 0.5, 0.2, 1.0);
}
`
const canvas = document.getElementById('canvas');
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;
const gl = canvas.getContext('webgl2');
if (!gl) {
alert('WebGL not supported');
} const vertices = new Float32Array([
-0.5, -0.5, 0.0,
0.5, -0.5, 0.0,
0.0, 0.5, 0.0,
]);
const vbo = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW); const vao = gl.createVertexArray();
gl.bindVertexArray(vao);
gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(0) const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexSource);
gl.compileShader(vertexShader); const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentSource);
gl.compileShader(fragmentShader); const shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram); gl.clearColor(0.2, 0.3, 0.3, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT); gl.useProgram(shaderProgram);
gl.drawArrays(gl.TRIANGLES, 0, 3); </script>

其中,vbo是顶点缓冲对象(Vertex Buffer Objects, VBO),主要用来储存顶点数据:

const vertices = new Float32Array([
-0.5, -0.5, 0.0,
0.5, -0.5, 0.0,
0.0, 0.5, 0.0,
]);
const vbo = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

WebGLBuffer 接口属于 WebGL API 的一部分,表示一个不透明的缓冲区对象,储存诸如顶点或着色之类的数据

WebGLBuffer 对象没有定义任何自己的方法或属性,且内容不能被直接访问。当使用 WebGLBuffer 对象时, WebGLRenderingContext 下的这些方法会很有用:

示例代码中:

createBuffer() 方法可创建并初始化一个用于储存顶点数据或着色数据的WebGLBuffer对象

bindBuffer(target, buffer) 方法将给定的WebGLBuffer绑定到目标,参数:

  • target

    GLenum (en-US) 指定绑定点 (target)。可能的值:

    • gl.ARRAY_BUFFER: 包含顶点属性的 Buffer,如顶点坐标,纹理坐标数据或顶点颜色数据。
    • gl.ELEMENT_ARRAY_BUFFER: 用于元素索引的 Buffer
  • buffer

    要绑定的 WebGLBuffer

bufferData(target, size, usage) 方法创建并初始化了 Buffer 对象的数据存储区,参数:

  • target

    GLenum (en-US) 指定 Buffer 绑定点(目标)。可取以下值:

    • gl.ARRAY_BUFFER: 包含顶点属性的 Buffer,如顶点坐标,纹理坐标数据或顶点颜色数据。
    • gl.ELEMENT_ARRAY_BUFFER: 用于元素索引的 Buffer
  • size

  • usage

    GLenum (en-US) 指定数据存储区的使用方法。可取以下值:

    • gl.STATIC_DRAW: 缓冲区的内容可能经常使用,而不会经常更改。内容被写入缓冲区,但不被读取。
    • gl.DYNAMIC_DRAW: 缓冲区的内容可能经常被使用,并且经常更改。内容被写入缓冲区,但不被读取。
    • gl.STREAM_DRAW: 缓冲区的内容可能不会经常使用。内容被写入缓冲区,但不被读取

以上大致就是WebGL中Buffer(VBO)的用法

3. Cesium中的Buffer

Cesium中,对WebGL的Buffer进行了封装:

function Buffer(options) {
const gl = options.context._gl;
gl.bindBuffer(bufferTarget, buffer);
gl.bufferData(bufferTarget, hasArray ? typedArray : sizeInBytes, usage);
gl.bindBuffer(bufferTarget, null);
} Buffer.createVertexBuffer = function (options) {
return new Buffer({
context: options.context,
bufferTarget: WebGLConstants.ARRAY_BUFFER,
typedArray: options.typedArray,
sizeInBytes: options.sizeInBytes,
usage: options.usage,
});
}; Buffer.createIndexBuffer = function (options) {
const buffer = new Buffer({
// ...
});
return buffer;
};

Buffer类的构造函数只是一次简单的封装,Buffer.createVertexBuffer函数可以更为快速的构建Buffer,搜索源码就会发现大多也是使用Buffer.createVertexBuffer创建Buffer,比如GeoJsonLoader.js

// ...
// Create GPU buffers
const positionBuffer = Buffer.createVertexBuffer({
typedArray: positionsTypedArray,
context: frameState.context,
usage: BufferUsage.STATIC_DRAW,
});
positionBuffer.vertexArrayDestroyable = false; const featureIdBuffer = Buffer.createVertexBuffer({
typedArray: featureIdsTypedArray,
context: frameState.context,
usage: BufferUsage.STATIC_DRAW,
});
featureIdBuffer.vertexArrayDestroyable = false; const indexBuffer = Buffer.createIndexBuffer({
typedArray: indicesTypedArray,
context: frameState.context,
usage: BufferUsage.STATIC_DRAW,
indexDatatype: indexDatatype,
});
indexBuffer.vertexArrayDestroyable = false;
// ...

使用Buffer.createVertexBuffer创建指定数据大小而数据未确定的VBO的例子:

// Example 1. Create a dynamic vertex buffer 16 bytes in size.
const buffer = Buffer.createVertexBuffer({
context : context,
sizeInBytes : 16,
usage : BufferUsage.DYNAMIC_DRAW
});

使用Buffer.createVertexBuffer创建数据确定的VBO的例子:

// Example 2. Create a dynamic vertex buffer from three floating-point values.
// The data copied to the vertex buffer is considered raw bytes until it is
// interpreted as vertices using a vertex array.
const positionBuffer = buffer.createVertexBuffer({
context : context,
typedArray : new Float32Array([0, 0, 0]),
usage : BufferUsage.STATIC_DRAW
});

使用Buffer.createIndexBuffer创建指定数据大小而数据未确定的IBO的例子:

// Example 1. Create a stream index buffer of unsigned shorts that is
// 16 bytes in size.
const buffer = Buffer.createIndexBuffer({
context : context,
sizeInBytes : 16,
usage : BufferUsage.STREAM_DRAW,
indexDatatype : IndexDatatype.UNSIGNED_SHORT
});

使用Buffer.createIndexBuffer创建数据确定的IBO的例子:

// Example 2. Create a static index buffer containing three unsigned shorts.
const buffer = Buffer.createIndexBuffer({
context : context,
typedArray : new Uint16Array([0, 1, 2]),
usage : BufferUsage.STATIC_DRAW,
indexDatatype : IndexDatatype.UNSIGNED_SHORT
});

此外,Buffer封装的函数有:

Buffer.prototype.copyFromArrayView = function (arrayView, offsetInBytes)
Buffer.prototype.copyFromBuffer = function (
readBuffer,
readOffset,
writeOffset,
sizeInBytes
)
Buffer.prototype.getBufferData = function (
arrayView,
sourceOffset,
destinationOffset,
length
)
Buffer.prototype.isDestroyed
Buffer.prototype.destroy

4. 参考资料

[1]Cesium原理篇:6 Renderer模块(1: Buffer) - fu*k - 博客园 (cnblogs.com)

[2]WebGLRenderingContext - Web API 接口参考 | MDN (mozilla.org)

[3]Cesium渲染模块之概述 - 当时明月在曾照彩云归 - 博客园 (cnblogs.com)

最新文章

  1. win2003+sql2005配置
  2. IE6不支持min-heightt和min-width的解决办法
  3. linux下svn 搭建
  4. valuestack,stackContext,ActionContext.之间的关系以及如何存取数值的
  5. Cube Mapping
  6. 线程和NSThread 、 NSOperation
  7. Android View绘制流程
  8. WPF中的换行符
  9. EventBus通信
  10. 报表Reporting S而vice是 错误的解决
  11. SQL查询今天、昨天、7天内、30天
  12. myeclipse 中clean的作用
  13. NET Core应用中使用缓存
  14. [转]Docker学习之四:使用docker安装mysql
  15. 获取Bing每日图片API接口
  16. 下拉加载更多DEMO(js实现)
  17. conda 管理 python 版本
  18. Oracle 通过出生日期计算年龄
  19. 高性能CSS
  20. 定义JQuery插件

热门文章

  1. 【笔面试题目】Java集合相关的面试题-List、Map、Set等
  2. flutter系列之:flutter中的变形金刚Transform
  3. swiper3踩坑
  4. 关于JavaScript每句结尾是否需要添加分号问题
  5. 如何通过 C#/VB.NET 将 PDF 转为 Word
  6. 物联网 IOT 设备如何脱离信息孤岛?
  7. DevSecOps 需要知道的十大 K8s 安全风险及建议
  8. 乾坤大挪移,如何将同步阻塞(sync)三方库包转换为异步非阻塞(async)模式?Python3.10实现。
  9. 在 C# 9 中使用 foreach 扩展
  10. 第一次Kaggle比赛心得