Cesium渲染模块之Buffer
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
下的这些方法会很有用:
WebGLRenderingContext.bindBuffer()
WebGLRenderingContext.createBuffer()
WebGLRenderingContext.deleteBuffer()
WebGLRenderingContext.isBuffer()
- 更详细的内容可以参考:WebGLBuffer - Web API 接口参考 | MDN (mozilla.org)
示例代码中:
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
GLsizeiptr
(en-US) 设定 Buffer 对象的数据存储区大小
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)
Cesium渲染模块之Buffer的更多相关文章
- Cesium原理篇:6 Renderer模块(1: Buffer)
刚刚结束完地球切片的渲染调度后,打算介绍一下目前大家都很关注的3D Tiles方面的内容,但发现要讲3D Tiles,或者充分理解它,需要对DataSource,Primitive要有基础,而这要求对 ...
- Cesium原理篇:6 Renderer模块(1: Buffer)【转】
https://www.bbsmax.com/A/n2d9P1Q5Dv/ 刚刚结束完地球切片的渲染调度后,打算介绍一下目前大家都很关注的3D Tiles方面的内容,但发现要讲3D Tiles,或者充分 ...
- (原)Unreal渲染模块 管线 - 着色器(1)
@author: 白袍小道 转载悄悄说明下 随缘查看,施主开心就好 说明: 本篇继续Unreal搬山部分的渲染模块的Shader部分, 主要牵扯模块RenderCore, ShaderCore, RH ...
- (原)Unreal渲染模块 管线 - 程序和场景查询
@author: 白袍小道 查看随意,转载随缘 第一部分: 这里主要关心加速算法,和该阶段相关的UE模块的结构和组件的处理. What-HOW-Why-HOW-What(嘿嘿,老规矩) 1.渲 ...
- (原)Unreal渲染模块 源码和实例分析说明
@author:白袍小道 说明 1.由于小道就三境武夫而已,而UE渲染部分不仅管理挺大,而且牵扯技术和内容驳杂,所以才有这篇梳理. 2.尽量会按书籍和资料,源码,小模块的调试和搬山(就是敲键盘)..等 ...
- (原)Unreal 渲染模块 渲染流程
@author:白袍小道 浏览分享随缘,评论不喷亦可. 扯淡部分: 在temp中,乱七八糟的说了下大致的UE过程.下面我们还是稍微别那么任性,一步步来吧. UE渲染模块牵扯到场景遍历. ...
- (原)Unreal 渲染模块引言Temp
@author:白袍小道 引言 本文只在对Unreal渲染模块做一些详细的理解,务求能分析出个大概. 其中框架的思想和实现的过程,是非常值得学习和推敲一二的. 涉及资源系统,材 ...
- Django---Http协议简述和原理,HTTP请求码,HTTP请求格式和响应格式(重点),Django的安装与使用,Django项目的创建和运行(cmd和pycharm两种模式),Django的基础文件配置,Web框架的本质,服务器程序和应用程序(wsgiref服务端模块,jinja2模板渲染模块)的使用
Django---Http协议简述和原理,HTTP请求码,HTTP请求格式和响应格式(重点),Django的安装与使用,Django项目的创建和运行(cmd和pycharm两种模式),Django的基 ...
- DRF框架(一)——restful接口规范、基于规范下使用原生django接口查询和增加、原生Django CBV请求生命周期源码分析、drf请求生命周期源码分析、请求模块request、渲染模块render
DRF框架 全称:django-rest framework 知识点 1.接口:什么是接口.restful接口规范 2.CBV生命周期源码 - 基于restful规范下的CBV接口 3.请求组件 ...
- drf框架 - 请求模块 | 渲染模块
Postman接口工具 官方 https://www.getpostman.com/ get请求,携带参数采用Paramspost等请求,提交数据包可以采用三种方式:form-date.urlenc ...
随机推荐
- MySQL 性能压测工具-sysbench,从入门到自定义测试项
sysbench是一个开源的.基于LuaJIT(LuaJIT 是 Lua 的即时编译器,可将代码直接翻译成机器码,性能比原生 lua 要高) 的.可自定义脚本的多线程基准测试工具,也是目前用得最多的 ...
- Vue快速上门(1)-基础知识图文版
VUE家族系列: Vue快速上门(1)-基础知识 Vue快速上门(2)-模板语法 Vue快速上门(3)-组件与复用 01.基本概念 1.1.先了解下MVVM VUE是基于MVVM思想实现的,那什么是M ...
- linux 删除influxdb的某条数据
1.进入服务器,输入: influx 进入influxdb 2.继续输入: show databases 显示所有的数据库名称 3.继续输入: use database 使用某一个数据库 ps:此处的 ...
- 如何使用OpenCV+MMPEAG打开摄像头,显示的同时推送RTMP流。
注意,设置中: 代码详解: 1. char* outUrl = "rtmp://localhost/live/livestream"; 这个地址,是AMS(Adeobe Media ...
- 架构设计(四):CDN
架构设计(四):CDN 作者:Grey 原文地址: 博客园:架构设计(四):CDN CSDN:架构设计(四):CDN CDN 全称 Content delivery network ,即:内容分发网络 ...
- Win10下SDK Manager应用程序闪退问题的解决方法
SDK Manager闪退原因:未找到Java的正确路径 解决办法: 1.在压缩包中找到Android.bat文件,右键编辑 2.打开的Android文件内容,找到如图的几行代码 将上面的代码替换成: ...
- bitlocker加密如何找密钥解锁
步骤1:在其他设备上登录[微软账号],地址:https://account.microsoft.com 步骤2:找到[自己的设备],查看[Bitlocker]密钥登录进去能看到[设备],找要解锁的那台 ...
- 【转载】EXCEL VBA 工作表拆分
用VBA拆分工作表是一个不错的方法,特别是在处理大量数据的时候,能节省不少时间. 1.高级筛选: 筛选并复制到新工作表的关键代码如下: Range("Database").Ad ...
- Flutter异常监控 - 伍 | 关于异常监控框架设计的思考
前言 最近阅读 Catcher.BugSnag.Rollbar 三个 Flutter 异常监控开源框架,文章链接如下: Flutter 异常监控 - 壹 | 从 Zone 说起 Flutter 异常监 ...
- spark RPC超时造成任务异常 Attempted to get executor loss reason for executor id 17 at RPC address 192.168.48.172:59070, but got no response. Marking as slave lost.
日志信息如下 Attempted to get executor loss reason for executor id 17 at RPC address 192.168.48.172:59070, ...