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渲染模块的Texture

2. WebGL中的Texture

以下大致是一个最简的Texture的WebGL绘制代码(完整代码和数据见文末附录):

// 加载纹理坐标到GPU
const textureCoordinates = new Float32Array([
-1.0, 0.0,
2.0, 0.0,
0.5, 2.0
]);
const textureCoordinatesBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, textureCoordinatesBuffer);
gl.bufferData(gl.ARRAY_BUFFER, textureCoordinates, gl.STATIC_DRAW);
// 设置纹理坐标属性
textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord");
gl.enableVertexAttribArray(textureCoordAttribute);
gl.vertexAttribPointer(textureCoordAttribute, 2, gl.FLOAT, false, 0, 0);
// 加载图片,图片加载后创建纹理
const image = new Image();
image.src = './cubetexture.png';
image.onload = function () {
// 创建并绑定纹理对象
const texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
// 设置纹理参数
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
// 生成纹理数据
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
gl.generateMipmap(gl.TEXTURE_2D);
// 激活纹理并绘制
gl.activeTexture(gl.TEXTURE0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLES, 0, 3);
}

WebGL或者说OpenGL中,纹理(Texture)通常是贴在物体表面的二维图片

参考上述代码,WebGL中纹理使用流程大致如下:

  • 加载图片数据
  • 创建纹理对象 gl.createTexture()
  • 绑定纹理对象gl.bindTexture()
  • 设置纹理参数gl.texParameteri()
  • 使用图片数据生成纹理gl.texImage2D()、gl.generateMipmap()
  • 设置纹理坐标gl.createBuffer()...
  • 在顶点着色器中传递纹理
  • 在片段着色器中采用纹理
  • (绘制时)激活纹理并绑定纹理gl.activeTexture()

纹理参数gl.texParameteri()主要是设置采样方式、平铺方式等,具体可以参考:WebGLRenderingContext.texParameteri() - Web API 接口参考 | MDN (mozilla.org)

上述代码中使用到的gl.pixelStorei()用于图像预处理的函数,具体可以参考:WebGLRenderingContext.pixelStorei() - Web API 接口参考 | MDN (mozilla.org)

使用图片数据生成纹理的gl.texImage2D()方法的重载方法较多,目的无非就是实现各种图片数据的加载,具体可以参考:WebGLRenderingContext.bindTexture() - Web API 接口参考 | MDN (mozilla.org)

gl.generateMipmap()会为当前绑定的纹理自动生成所有需要的多级渐远纹理

更详细的流程和函数解释可以参考:纹理 - LearnOpenGL CN (learnopengl-cn.github.io)

3. Cesium中的Texture

Cesium源码中,对Texture进行了一些封装:

function Texture(options) {
// ...
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(textureTarget, texture);
gl.pixelStorei(gl.UNPACK_ALIGNMENT, unpackAlignment);
// Source: ImageData, HTMLImageElement, HTMLCanvasElement, or HTMLVideoElement
gl.texImage2D(textureTarget, 0, internalFormat, pixelFormat, PixelDatatype.toWebGLConstant(pixelDatatype, context), source);
gl.bindTexture(textureTarget, null); this._texture = texture;
this.sampler = defined(options.sampler) ? options.sampler : new Sampler();
} Texture.prototype.generateMipmap = function (hint) {
// ...
gl.hint(gl.GENERATE_MIPMAP_HINT, hint);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(target, this._texture);
gl.generateMipmap(target);
gl.bindTexture(target, null);
};

Texture还封装了以下函数:

Texture.fromFramebuffer = function (options)
Texture.prototype.copyFrom = function (options)
Texture.prototype.copyFromFramebuffer = function(xOffset,yOffset,framebufferXOffset,framebufferYOffset,width,height)
Texture.prototype.isDestroyed = function ()
Texture.prototype.isDestroyed = function ()

另外,还有TextureCache,用来缓存Texture,虽然目前在源码中似乎没怎么使用:

function TextureCache() {
this._textures = {};
this._numberOfTextures = 0;
this._texturesToRelease = {};
} TextureCache.prototype.getTexture = function (keyword) {
const cachedTexture = this._textures[keyword];
return cachedTexture.texture;
};

在Cesium源码中,可以看到纹理基本都是直接new Texture(),例如ImageryLayer.js

ImageryLayer.prototype._createTextureWebGL = function (context, imagery) {
const sampler = new Sampler({
minificationFilter: this.minificationFilter,
magnificationFilter: this.magnificationFilter,
}); const image = imagery.image; return new Texture({
context: context,
source: image,
pixelFormat: this._imageryProvider.hasAlphaChannel
? PixelFormat.RGBA
: PixelFormat.RGB,
sampler: sampler,
});
};

4. 参考资料

[1]Using textures in WebGL - Web API 接口参考 | MDN (mozilla.org)

[2]纹理 - LearnOpenGL CN (learnopengl-cn.github.io)

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

[4]webgl 12.Texture (纹理) - 简书 (jianshu.com)

[5]CesiumJS 2022^ 源码解读 5 - 着色器相关的封装设计 - 岭南灯火 - 博客园 (cnblogs.com)

5. 附录

包含Texture的WebGL绘制代码:

<canvas id="canvas"></canvas>
<script>
const vertexSource = `
attribute vec3 aPos;
attribute vec2 aTextureCoord;
varying highp vec2 vTextureCoord;
void main()
{
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
vTextureCoord = aTextureCoord;
}
`
const fragmentSource = `
varying highp vec2 vTextureCoord;
uniform sampler2D uSampler;
void main()
{
gl_FragColor = texture2D(uSampler, vTextureCoord);
}
`
const canvas = document.getElementById('canvas');
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;
const gl = canvas.getContext('webgl2'); 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.useProgram(shaderProgram); gl.clearColor(0.2, 0.3, 0.3, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT); // 加载纹理坐标到GPU
const textureCoordinates = new Float32Array([
-1.0, 0.0,
2.0, 0.0,
0.5, 2.0
]);
const textureCoordinatesBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, textureCoordinatesBuffer);
gl.bufferData(gl.ARRAY_BUFFER, textureCoordinates, gl.STATIC_DRAW);
// 设置纹理坐标属性
textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord");
gl.enableVertexAttribArray(textureCoordAttribute);
gl.vertexAttribPointer(textureCoordAttribute, 2, gl.FLOAT, false, 0, 0); const image = new Image();
image.src = './cubetexture.png';
image.onload = function () {
// 创建并绑定纹理对象
const texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
// 设置纹理参数
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
// 生成纹理数据
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
gl.generateMipmap(gl.TEXTURE_2D); // const sampler = gl.getUniformLocation(shaderProgram, "uSampler");
// gl.uniform1i(sampler, 0); gl.activeTexture(gl.TEXTURE0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLES, 0, 3);
}
</script>

其中,图片cubetexture.png下载自:webgl-examples/cubetexture.png at main · mdn/webgl-examples · GitHub

Cesium渲染模块之Texture的更多相关文章

  1. Cesium渲染模块之概述

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

  2. Cesium渲染模块之VAO

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

  3. Cesium渲染模块之Buffer

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

  4. Cesium渲染模块之Shader

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

  5. Cesium渲染模块之Command

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

  6. Cesium原理篇:6 Renderer模块(2: Texture)

    Texture也是WebGL中重要的概念,使用起来也很简单.但有句话叫大道至简,如果真的想要用好纹理,里面的水其实也是很深的.下面我们来一探究竟. 下面是WebGL中创建一个纹理的最简过程: var ...

  7. (原)Unreal渲染模块 源码和实例分析说明

    @author:白袍小道 说明 1.由于小道就三境武夫而已,而UE渲染部分不仅管理挺大,而且牵扯技术和内容驳杂,所以才有这篇梳理. 2.尽量会按书籍和资料,源码,小模块的调试和搬山(就是敲键盘)..等 ...

  8. Cesium渲染调度

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

  9. (原)Unreal渲染模块 管线 - 着色器(1)

    @author: 白袍小道 转载悄悄说明下 随缘查看,施主开心就好 说明: 本篇继续Unreal搬山部分的渲染模块的Shader部分, 主要牵扯模块RenderCore, ShaderCore, RH ...

  10. (原)Unreal渲染模块 管线 - 程序和场景查询

    @author: 白袍小道 查看随意,转载随缘     第一部分: 这里主要关心加速算法,和该阶段相关的UE模块的结构和组件的处理. What-HOW-Why-HOW-What(嘿嘿,老规矩) 1.渲 ...

随机推荐

  1. Linux-编译源码时所需提前安装的常用依赖包列表

    编译源码时所需提前安装的常用依赖包列表: yum -y install gcc gcc-c++ autoconf libjpeg libjpeg-devel libpng libpng-devel f ...

  2. sensitive word 敏感词(脏词) 如何忽略无意义的字符?达到更好的过滤效果?

    忽略字符 说明 我们的敏感词一般都是比较连续的,比如 傻帽 那就有大聪明发现,可以在中间加一些字符,比如[傻!@#$帽]跳过检测,但是骂人等攻击力不减. 那么,如何应对这些类似的场景呢? 我们可以指定 ...

  3. Ubuntu20.04安装记录

    在Ubuntu下将iso文件刻录到U盘, 可以使用系统自带的Startup Disk Creator. 分区方式 使用整个硬盘, 一个512G SSD, 使用默认的分区方式, 会创建一个512M的EF ...

  4. 快速傅里叶变换(FFT)和小波分析在信号处理上的应用

    1前言 1.1傅里叶变换 函数f(t)为一元连续函数,其傅里叶变换定义为: F(w)的傅里叶逆变换定义为: 其中,i为虚数单位.由欧拉公式: 任意绝对可积的连续函数f(t),都可以用三角函数表示,由于 ...

  5. el-dialog关闭后重置表单和校验提示

    问题说明 最近测试反馈操作某新增/修改表单,点击[取消]或[关闭]窗口后再次点击[新增]或[修改]发现校验提示仍然存在! 问题原因 项目采用Vue+ElementUI,修改表单的窗口控件采用el-di ...

  6. 案例分享:Qt激光加工焊接设备信息化软件研发(西门子PLC,mysql数据库,用户权限控制,界面设计,参数定制,播放器,二维图,rgv小车,期限控制,参数调试等)

    需求   1.键鼠控制,承担ui界面设计,布局兼容分辨率1024x768 ~ 1920x1080.  2.权限控制:三种权限,分为管理员(可以定制模块界面,修改产品名称等定制化软件和其他权限,同时具备 ...

  7. 在矩池云安装使用PaddleHub 和 PaddlePaddle

    之前在安装 PaddleHub 导入的时候遇到各种错误,不是这个包没这个模块,就是哪个包没这个属性 ...很头痛,网上也没有 PaddleHub 和 PaddlePaddle 对应的版本,只能自己慢慢 ...

  8. 07、Etcd 中Raft算法简介

    本篇内容主要来源于自己学习的视频,如有侵权,请联系删除,谢谢. 思考: etcd是如何基于Raft来实现高可用.数据强-致性的? 1.什么是Raft算法 Raft 算法是现在分布式系统开发首选的共识算 ...

  9. 【Azure 存储服务】Azure Blob下面是否可以创建子文件夹

    问题描述 如何在Azure Storage Account(存储账户) 门户上为 Container 创建子文件夹? 问题解决 经验证,没有办法在门户上直接创建文件夹,不过可以使用Azure Stor ...

  10. Java //数组的反转

    1 //数组的反转 2 //方式一 3 System.out.println("数组的反转"); 4 5 // for(int i = 0; i <arr.length/2; ...