快速上手WebGL,代码+图解手把手教你使用WebGL一步步实现热力图

这篇具有很好参考价值的文章主要介绍了快速上手WebGL,代码+图解手把手教你使用WebGL一步步实现热力图。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

大家好,我是南木元元,热衷分享有趣实用的文章。

热力图

项目中需要绘制热力图,热力图其实就是数值大小用颜色来进行区分,每个点的数值需根据颜色映射表(调色板)映射为指定颜色。需要3个数值字段,可绘制在平行坐标系中(2个数值字段分别确定x、y轴,1个数值字段确定着色)。效果如下:
webgl-heatmap,# webgl,webgl
其实就是对每个点赋予指定颜色,echarts和canvas都很容易实现热力图(使用createImageData)的效果,由于之前学习过WebGL,于是就想着用webgl来实现热力图的效果。

  • 如何使用webgl来进行绘制呢?

热力图是由一个个彩色的点构成,所以,只需要思考如何使用webgl绘制出一个个彩色的点,那么就自然能形成热力图的效果。而webgl中有顶点着色器和片元着色器,一个用于计算顶点位置,一个用于计算颜色值,所以,关键就是把数据传个这两个着色器。

WebGL绘制多个点

缓冲区对象

webgl中绘制一个点很方便,代码如下:

  //顶点着色器
  const VERTEX_SHADER_SOURCE = `
    void main() {
      gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
      gl_PointSize = 10.0;
    }  
  `
  //片元着色器
  const FRAGMENT_SHADER_SOURCE = `
    void main() {
      gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
    }   
  `
  //创建着色器
  const program = initShader(gl, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE)
  gl.drawArrays(gl.POINTS, 0, 1)

如果想同时绘制多个点,就需要用到它所提供的缓冲区对象,它可以一次性向顶点着色器传入多个顶点的数据。

attribute变量

attribute用来存储顶点着色器中每个顶点的输入,包括顶点位置坐标、纹理坐标和颜色等信息,但是只能用于顶点着色器。
缓冲是程序发送给GPU的数据,attribute用来从缓冲中获取所需数据,并将它提供给顶点着色器。

使用缓冲区

缓冲区对象是WebGL中的一块存储区,可以在缓冲区对象中保存想要绘制的所有顶点数据。先创建一个缓冲区,然后向其中写入顶点数据,就能一次性向顶点着色其传入多个顶点的attribute变量的数据。
webgl-heatmap,# webgl,webgl

首先需要定义所有要向缓冲区对象写入的数据。

const vertices = new Float32Array([
  -0.5, 0.5,
  -0.5, -0.5,
  0.5, 0.5
])

然后使用使用缓冲区对象向顶点着色器传入多个顶点的数据,主要有五步:
1.创建缓冲区对象

const vertexBuffer = gl.createBuffer();

2.绑定缓冲区对象

gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);

3.向缓冲区对象中写入数据

gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

4.将缓冲区对象分配给一个attribute变量

gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);

5.激活attribute变量

gl.enableVertexAttribArray(a_Position);
  • 使用缓冲区代码
// 获取attribute变量位置
const a_Position = gl.getAttribLocation(gl.program, 'a_Position');
if (a_Position < 0) {
  console.log('Failed to get the storage location of a_Position');
  return;
}
// 向缓冲区对象写入的数据
const vertices = new Float32Array([
  -0.5, 0.5,
  -0.5, -0.5,
  0.5, 0.5
])
const vertexBuffer = gl.createBuffer();//创建缓冲区对象
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);// 绑定缓冲区对象到gl.ARRAY_BUFFER上,gl.ARRAY_BUFFER表示缓冲区对象中包含了顶点数据
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);// 将数据写入缓冲区对象,gl.STATIC_DRAW代表只向缓冲区写入一次数据
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0); // 调用顶点缓冲,将缓冲数据传给a_Position
gl.enableVertexAttribArray(a_Position);// 激活a_Position使用缓冲数组

  • 着色器代码

在着色器内,一般命名以gl_开头的变量是着色器的内置变量。变量声明一般包含<存储限定符><数据类型><变量名称>,下面代码中,attribute表示存储限定符,vec是数据类型,a_Position为变量名称。

const vs_source = `
  attribute vec4 a_Position;
  void main() {
    gl_Position = a_Position;
    gl_PointSize = 10.0;
  }
`;
// 片元着色器
const fs_source = `
  void main() {
    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
  }
`;
  • 完整代码
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>webgl绘制多个点</title>
</head>

<body>
  <canvas id="canvas" width="400" height="400"></canvas>
  <script>
    // 顶点着色器
    const vs_source = `
      attribute vec4 a_Position;
      void main() {
        gl_Position = a_Position;
        gl_PointSize = 10.0;
      }
    `;
    // 片元着色器
    const fs_source = `
      void main() {
        gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
      }
    `;
    const canvas = document.getElementById('canvas');
    const gl = canvas.getContext('webgl');
  
    function initShader() {
      // 创建shader
      const vs_shader = gl.createShader(gl.VERTEX_SHADER);
      gl.shaderSource(vs_shader, vs_source);
      gl.compileShader(vs_shader);
      if (!gl.getShaderParameter(vs_shader, gl.COMPILE_STATUS)) {
        const error = gl.getShaderInfoLog(vs_shader);
        console.log('Failed to compile vs_shader:' + error);
        gl.deleteShader(vs_shader);
        return;
      }
      const fs_shader = gl.createShader(gl.FRAGMENT_SHADER);
      gl.shaderSource(fs_shader, fs_source);
      gl.compileShader(fs_shader);
      if (!gl.getShaderParameter(fs_shader, gl.COMPILE_STATUS)) {
        const error = gl.getShaderInfoLog(fs_shader);
        console.log('Failed to compile fs_shader:' + error);
        gl.deleteShader(fs_shader);
        return;
      }
  
      // 创建program
      const program = gl.createProgram();
      gl.attachShader(program, vs_shader);
      gl.attachShader(program, fs_shader);
      gl.linkProgram(program);
      if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
        const error = gl.getProgramInfoLog(program);
        console.log('无法链接程序对象:' + error);
        gl.deleteProgram(program);
        gl.deleteShader(fs_shader);
        gl.deleteShader(vs_shader);
        return;
      }
      gl.useProgram(program);
      gl.program = program;

      // 获取attribute变量位置
      const a_Position = gl.getAttribLocation(gl.program, 'a_Position');
      if (a_Position < 0) {
        console.log('Failed to get the storage location of a_Position');
        return;
      }
      // 向缓冲区对象写入的数据
      const vertices = new Float32Array([
        -0.5, 0.5,
        -0.5, -0.5,
        0.5, 0.5
      ])
      const vertexBuffer = gl.createBuffer();//创建缓冲区对象
      gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);// 绑定缓冲区对象到gl.ARRAY_BUFFER上,gl.ARRAY_BUFFER表示缓冲区对象中包含了顶点数据
      gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);// 将数据写入缓冲区对象,gl.STATIC_DRAW代表只向缓冲区写入一次数据
      gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0); // 调用顶点缓冲,将缓冲数据传给a_Position
      gl.enableVertexAttribArray(a_Position);// 激活a_Position使用缓冲数组
    }
  
    initShader();
    
    gl.clearColor(0.0, 0.0, 0.0, 1.0);
    gl.clear(gl.COLOR_BUFFER_BIT);
    gl.drawArrays(gl.POINTS, 0, 3);//绘制3个点
  </script>
</body>
</html>
  • 效果

webgl-heatmap,# webgl,webgl

WebGL绘制多个彩色点

接下来就是彩色点的绘制,需要传入每个点的颜色数据。

varying 可变量

varying一般同时存在顶点着色器和片元着色器中,它的作用是从顶点着色器向片元着色器传输数据。

// 顶点着色器
const vs_source = `
  attribute vec4 a_Position;
  attribute float a_PointSize;
  attribute vec4 a_Color;
  varying vec4 v_Color;
  void main() {
    gl_Position = a_Position;
    gl_PointSize = a_PointSize;
    v_Color = a_Color;
  }
`;
// 片元着色器
const fs_source = `
  precision mediump float;
  varying vec4 v_Color;
  void main() {
    gl_FragColor = v_Color;
  }
`;

上面,顶点着色器通过a_Position、a_PointSize分别接收并设置顶点的位置和大小,通过a_Color从程序获取颜色并通过v_Color传递给片元着色器。
片元着色器,首先设置了float为中等精度,然后通过v_Color接收来自顶点着色器的颜色并将其设置给内置变量gl_FragColor,其中通过内置变量gl_FragColor来确定顶点像素颜色。

读取缓冲区

缓冲区数据,7个为一组,前两个数据代表顶点位置,第3个代码顶点大小,第4-7个就代表顶点的颜色。

const vertices = new Float32Array([
  -0.5, 0.5, 10.0, 1.0, 0.0, 0.0, 1.0,
  -0.5, -0.5, 20.0, 0.0, 1.0, 0.0, 1.0,
  0.5, 0.5, 30.0, 0.0, 0.0, 1.0, 1.0
])
  • 如何读取出相应的顶点位置、大小以及颜色数据?

gl.vertexAttribPointer()可以指定读取缓冲的规则。
webgl-heatmap,# webgl,webgl
设置缓冲读取规则和启用缓冲对象

//设置缓冲读取规则
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, SIZE * 7, 0); // 将缓冲数据中一组7个数据中的前2个数据传给a_Position
gl.vertexAttribPointer(a_PointSize, 1, gl.FLOAT, false, SIZE * 7, SIZE * 2); // 将缓冲数据中一组7个数据中的第3(偏移2个数据取1一个)个数据传给a_PointSize
gl.vertexAttribPointer(a_Color, 4, gl.FLOAT, false, SIZE * 7, SIZE * 3); //将缓冲数据中一组7个数据中的第4-7(偏移3个数据取4个)个数据传给a_Color
//启用缓冲对象
gl.enableVertexAttribArray(a_Position);// 激活a_Position使用缓冲数组
gl.enableVertexAttribArray(a_PointSize);// 激活a_Position使用缓冲数组
gl.enableVertexAttribArray(a_Color);// 激活a_Color使用缓冲数组
  • 效果

绘制出了3个不同大小、不同颜色的点。
webgl-heatmap,# webgl,webgl

热力图的绘制

接下来热力图的绘制就很简单了,只将每个点的位置信息和颜色值使用缓冲区传给着色器就可以。
可以如下来定义缓冲数据,6个为一组,前2个代表位置,后4个代表颜色(每个点的颜色是根据颜色映射表进行计算得到的)。

const vertices = new Float32Array([
  -0.5, 0.5, 1.0, 0.0, 0.0, 1.0,
  -0.5, -0.5,  0.0, 1.0, 0.0, 1.0,
  0.5, 0.5,  0.0, 0.0, 1.0, 1.0
  ......
])

结语

🔥如果此文对你有帮助的话,欢迎💗关注、👍点赞、⭐收藏、✍️评论,支持一下博主~文章来源地址https://www.toymoban.com/news/detail-799576.html

到了这里,关于快速上手WebGL,代码+图解手把手教你使用WebGL一步步实现热力图的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【荣耀帐号服务】手把手教你快速web接入

    荣耀帐号开放服务基于OAuth2.0,Web应用可以获取用户授权凭证, 实现授权登录功能, 可以实现浏览器Web授权登录接入或者手机H5授权登录接入荣耀帐号。 1) 用户在应用网站上选择荣耀帐号登录 2) 应用服务器构造 /oauth2/v3/authorize 链接, 向荣耀帐号服务器发起授权请求 3) 荣耀帐号

    2024年02月10日
    浏览(39)
  • 手机怎么扫描照片成电子版?手把手教你快速搞定

    手机怎么把照片给扫描成电子版呢?大家在办公的过程中,经常会使用或者是收到纸质版的文件或合同,正常情况下使用当然是没问题,但当我们在外身边没有电脑,而这时需要把手头上的纸质版文件给转换成电子版给客户发过去,这时候怎么办呢?其实我们只需要利用好自

    2024年02月13日
    浏览(49)
  • 手把手教你用代码画架构图

    作者:京东物流 覃玉杰 本文将给大家介绍一种简洁明了软件架构可视化模型——C4模型,并手把手教大家如何使用 代码 绘制出精美的C4架构图。 阅读本文之后,读者画的架构图将会是这样的: 注:该图例仅作绘图示例使用,不确保其完整性、可行性。 C4是软件架构可视化

    2024年02月04日
    浏览(49)
  • SDXL 1.0出图效果直逼Midjourney!手把手教你快速体验!

    最近,Stability AI正式推出了全新的SDXL 1.0版本。经过我的实际测试,与之前的1.5版本相比,XL的效果有了巨大的提升,可以说是全方位的超越。不仅在理解提示词方面表现出色,而且图片的构图、颜色渲染和画面细腻程度都有了很大的进步,实际出图效果堪比Midjourney。此外,

    2024年02月14日
    浏览(51)
  • 手把手教你如何快速定位bug,如何编写测试用例,快来观摩......

    手把手教你如何快速定位bug,如何编写测试用例,快来观摩......手把手教你如何快速定位bug,如何编写测试用例,快来观摩......作为一名测试人员如果连常见的系统问题都不知道如何分析,频繁将前端人员问题指派给后端人员,后端人员问题指派给前端人员,那么在团队里你在开发

    2024年01月20日
    浏览(55)
  • 手把手教你:gitee的注册以及代码的提交(上)

    个人主页(找往期文章包括但不限于本期文章中不懂的知识点):我要学编程(ಥ_ಥ)-CSDN博客 目录 gitee的介绍  gitee的注册 提交代码到gitee 安装git和图形化界面工具  在gitee上创建远程仓库。 clone远程仓库到本地电脑 git的三板斧  add commit  push   首先,我们得了解什么是git

    2024年02月22日
    浏览(53)
  • 手把手教你快速在生产环境搭建Doris集群附集群启停管理脚本

    组件分布规划 节点 node4 node5 node6 node7 node8 Node9 Node10 Node11 服务 FE(follower) BE FE(follower) BE FE(follower) BE FE(observer) BE BE Broker BE Broker BE BE Ip 192.168.22.34 192.168.22.35 192.168.22.36 192.168.22.37 192.168.22.20 192.168.22.16 192.168.22.17 192.168.22.18 根据自己集群的软硬件配置,选择合适的版本

    2024年02月02日
    浏览(50)
  • 手把手教你通过PaddleHub快速实现输入中/英文本生成图像(Stable Diffusion)

    近来,基于Diffusion的文图生成模型比较火,用户输入一句话,模型就可以生成一副对应的图像,还是很有意思的。本文记录了通过PaddleHub快速实现上述任务的过程,以供参考。 1、安装PaddlePaddle PaddleHub底层依赖于百度自研的开源框架PaddlePaddle,可以根据官方提供的方式来快速

    2024年01月17日
    浏览(49)
  • 手把手教你使用phpstudy本地快速搭建网站,并外网访问【无公网IP】

    本教程为快速在本地环境下搭建web网站,同时实现可在外网环境下访问!! 使用工具 phpstudy(本地搭建web网站) cpolar内网穿透(将网站发布到公网可访问) 1. 本地搭建web网站 1.1 下载phpstudy后解压并安装 官网下载:https://www.xp.cn/download.html 安装后的效果,如图: 点击,一键

    2024年02月08日
    浏览(49)
  • 手把手教你SAM(segment anything)官方代码本地调用

    更新一下如何下载官方本地github代码并在本地进行调用,更新的比较晚,截止发布前已经有28.1k的star了。接下来教大家如何分割一切!   首先我们可以下载SAM在官方的代码链接:https://github.com/facebookresearch/segment-anything 下载好之后需要配置一下SAM需要的环境,用pycharm打开配置

    2024年02月05日
    浏览(54)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包