一起学 WebGL:动态绘制点

news/2024/5/10 17:34:15/文章来源:https://blog.csdn.net/fe_watermelon/article/details/130027257

大家好,我是前端西瓜哥。上一篇文章讲解了如何绘制一个点。但这个点的信息是写死在渲染器源码中的,也就是硬编码。

这是系列文章,如果你是初学者,你需要看上一篇文章才好理解这节课的内容。

《一起学 WebGL:绘制一个点》

如果我们要频繁地改变点的位置去绘制,根据我们之前学到的知识点,那只能通过替换整个着色器代码字符串,不断地编译的方式去修改了,非常不便。

这节课我们会通过 JavaScript 给着色器动态提供数据,而不需要重新编译着色器。

静态绘制点

先贴上上篇文章的静态写法。

demo 地址:

https://codesandbox.io/s/webgl-hui-zhi-yi-ge-dian-2-bpwz8p

/*** wegbl 绘制一个点*//** @type {HTMLCanvasElement} */
const canvas = document.querySelector("canvas");
const gl = canvas.getContext("webgl");const vertexShaderSrc = `
attrs 
void main() {gl_Position = vec4(0.0, 0.0, 0.0, 1.0);gl_PointSize = 20.0;
}
`;const fragmentShaderSrc = `
void main() {gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`;/**** 渲染器生成处理 ****/
// 创建顶点渲染器
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexShaderSrc);
gl.compileShader(vertexShader);
// 创建片元渲染器
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentShaderSrc);
gl.compileShader(fragmentShader);
// 程序对象
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);
gl.program = program;/** 画布绘制 **/
// 清空画布,并指定颜色
gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
// 绘制点
gl.drawArrays(gl.POINTS, 0, 1);

渲染结果:

外部传递点的位置信息

下面我们希望顶点着色器的点的坐标可以通过 JavaScript 动态地修改。

加入 attribute 变量

修改顶点着色器的代码:

const vertexShaderSrc = `
attribute vec4 a_Position;
void main() {gl_Position = a_Position;gl_PointSize = 20.0;
}
`;

这里西瓜哥我将原本的 vec4 类型的写死的颜色值,换成了一个变量 a_Position。attribute 是存储限定符,表示变量是 attribute 类型,它用于描述顶点数据,值可以通过外部传递被修改。后面我们从外部拿到这个变量,传入我们想要的值。

vec4 则是变量类型,表示一个有四个分量的矢量。

变量通常会用 a_ 作为前缀,表示该变量是 attribute 类型。

外部修改 attribute

然后是在 JavaScript 代码中获取这个 a_Position 变量,并传一个值给它。

const a_Position = gl.getAttribLocation(gl.program, "a_Position");
gl.vertexAttrib3f(a_Position, 0, 0.5, 0);

第一行 gl.getAttribLocation 方法的作用,是从 gl.program 程序对象中,取出一个名为 “a_Position” 的 attribute 变量的地址。如果找到,会返回一个大于等于 0 的值,找不到会返回 -1。

第二行,gl.vertexAttrib3f 就是根据地址给 a_Position 变量赋予值。a_Position 是 4 个浮点数组成的矢量类型,我们这里并没有传 4 个值,只传了 3 个。最后一个值对坐标系来说并无意义,但在矩阵变换时会用到,不提供会被自动填充为默认的 1.0。

你也可以用 gl.vertexAttrib4f 提供完成的 4 个浮点数,或者用 gl.vertexAttrib1fgl.vertexAttrib2f 提供第一个或前两个浮点数。缺少的 y、z 默认会用 0.0,z 则使用 1.0。

这里我们给 y 设置了 0.5,渲染结果为:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IWGvk6Gy-1680927888376)(https://fe-watermelon.oss-cn-shenzhen.aliyuncs.com/image-20230408103759064.png)]

关于坐标系的文章

《一起学 WebGL:坐标系》

补充一下 WebGL 的坐标系图示:

完整代码:

/*** wegbl 绘制一个点*//** @type {HTMLCanvasElement} */
const canvas = document.querySelector("canvas");
const gl = canvas.getContext("webgl");const vertexShaderSrc = `
attribute vec4 a_Position;
void main() {gl_Position = a_Position;gl_PointSize = 20.0;
}
`;const fragmentShaderSrc = `
void main() {gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`;/**** 渲染器生成处理 ****/
// 创建顶点渲染器
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexShaderSrc);
gl.compileShader(vertexShader);
// 创建片元渲染器
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentShaderSrc);
gl.compileShader(fragmentShader);
// 程序对象
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);
gl.program = program;/** 修改着色器的 attribute */
const a_Position = gl.getAttribLocation(gl.program, "a_Position");
gl.vertexAttrib3f(a_Position, 0, 0.5, 0);/** 画布绘制 **/
// 清空画布,并指定颜色
gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
// 绘制点
gl.drawArrays(gl.POINTS, 0, 1);

demo 地址:

https://codesandbox.io/s/webgl-dong-tai-hui-zhi-dian-5cdped?file=/index.js

不断修改位置信息

下面我们用一个定时器,不断地修改点的位置。

代码实现:

/*** webgl 动态绘制点 + 定时器*//** @type {HTMLCanvasElement} */
const canvas = document.querySelector("canvas");
const gl = canvas.getContext("webgl");const vertexShaderSrc = `
attribute vec4 a_Position;
void main() {gl_Position = a_Position;gl_PointSize = 20.0;
}
`;const fragmentShaderSrc = `
void main() {gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`;/**** 渲染器生成处理 ****/
// 创建顶点渲染器
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexShaderSrc);
gl.compileShader(vertexShader);
// 创建片元渲染器
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentShaderSrc);
gl.compileShader(fragmentShader);
// 程序对象
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);
gl.program = program;/** 修改着色器的 attribute */
const a_Position = gl.getAttribLocation(gl.program, "a_Position");let x = -1;
let y = -1;setInterval(() => {gl.vertexAttrib3f(a_Position, x, y, 0);x += 0.25;if (x > 1) x = -1;y += 0.25;if (y > 1) y = -1;/** 画布绘制 **/// 清空画布,并指定颜色gl.clearColor(0, 0, 0, 1);gl.clear(gl.COLOR_BUFFER_BIT);// 绘制点gl.drawArrays(gl.POINTS, 0, 1);
}, 180);

在定时器中,我们不断地修用 gl.vertexAttrib3f 修改点的位置,并重绘画布。

demo 地址:

https://codesandbox.io/s/webgl-dong-tai-hui-zhi-dian-ding-shi-qi-gnjx3t

渲染效果:

在这里插入图片描述

还修改点的大小的版本:

https://codesandbox.io/s/g4ft9m

结尾

我是前端西瓜哥,欢迎关注我,学习更多前端知识。

下一节我们将学习如何动态修改片元着色器中点的颜色。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_283446.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python五角星编程代码绘制

大家好,我是你们的好朋友,今天继续分享 Python的编程知识。 在 Python中,有一个非常强大的数据可视化工具: database. dl (),其中有一个功能就是可以绘制五角星。 什么是五角星? 在数…

jenkins配置插件发版了解

jenkins配置&插件&发版了解 jenkins https://mirrors.jenkins.io/war-stable/2.222.1/ 包下载地址 jenkins镜像源修改 sed -i s/https:\/\/www.google.com/https:\/\/www.baidu.com/g default.json sed -i s/https:\/\/updates.jenkins.io\/download/https:\/\/mi…

怎么使用思维导图?

回答这个问题前,我们先来了解下三个问题: 1.思维导图是什么? 思维导图,又名心智导图,是表达发散性思维的有效图形思维工具 ,它简单却又很有效同时又很高效,是一种实用性的思维工具&#xff08…

Ubuntu22.04中安装PyCharm

目录 1. 在ubuntu中下载linux版本的PyCharm。 2. 将下载好的pycharmxxxx.tar.gz文件解压。 3. 在解压后的pycharm文件夹下的bin文件夹下(此处为:pycharm-edu-2021.1.2/bin),在空白处右键,然后选择”在终端打开“。然…

蓝桥杯第26天(Python)考前挣扎

题型: 1.思维题/杂题:数学公式,分析题意,找规律 2.BFS/DFS:广搜(递归实现),深搜(deque实现) 3.简单数论:模,素数(只需要…

使用 LifseaOS 体验 ACK 千节点分钟级扩容

作者:阿里云 ACK 和操作系统团队 三年前的云栖大会上,LifseaOS 正式发布,这是一款专为云原生场景而垂直优化的操作系统发行版,即业界统称的 ContainerOS。初始发布时,它提供了如下几个突出的特性:轻量&…

guitar pro8.1免费的吉他学习辅助软件

从名字上看就知道这是一款针对吉他谱开发的软件,相信大多数吉他爱好者都用过或者听过这款软件。可以通过鼠标和键盘的操作对吉他谱的内容进行输入,支持四线谱,五线谱、六线谱等曲谱的制作。软件涵盖了几乎所有的吉他演奏技巧符号,…

OpenCV实战(17)——FAST特征点检测

OpenCV实战(17)——FAST特征点检测0. 前言1. FAST 特征点检测2. 自适应特征检测3. 完整代码小结系列链接0. 前言 Harris 算子根据两个垂直方向上的强度变化率给出了角点(或更一般地说,兴趣点)的数学定义。但使用这种定义需要计算图像导数&am…

Delphi 彻底搞懂 Unix/Linux 时间格式及平台间转换

目录 一、TDateTime 时间格式 二、Unix/Linux的日期和时间格式 三、Delphi中操作Unix/Linux格式的日期和时间 1. TDateTime 转 Unix/Linux格式 2. Unix/Linux格式 转 TDateTime 3. 与腾讯、阿里等平台(简称:平台)时间转换 四、Delphi…

秋招笔试知识点

1、计算出结构体大小(对齐规则) struct st { char name; int age; double money; }s; 规则(字节对齐) 1、 char 从0开始,0是任何数字的整数倍 int 是4个字节,4开始 double 是8个字节,从8开…

人人开源快速搭建后台(踩过的大坑,已解决)

目录 一、renrenfast后端代码导入idea后pom文件中的plugins报错 二、后端yaml配置出现问题 三、启动后端出现404 四、在vscode终端上运行 npm 会询问 “你要如何打开这个文件“ 五、npm install失败 一、renrenfast后端代码导入idea后pom文件中的plugins报错 亲测有效 谷…

ToBeWritten之汽车信息安全威胁建模

也许每个人出生的时候都以为这世界都是为他一个人而存在的,当他发现自己错的时候,他便开始长大 少走了弯路,也就错过了风景,无论如何,感谢经历 转移发布平台通知:将不再在CSDN博客发布新文章,敬…

itop-3568开发板驱动学习笔记(9)高级字符设备(三)信号驱动 IO

《【北京迅为】itop-3568开发板驱动开发指南.pdf》 学习笔记 文章目录应用层信号机制应用层开启异步通知驱动层异步通知接口实验代码信号驱动 IO 不需要像 poll 一样查询设备的状态,一旦设备有目标事件发生,就会触发 SIGIO 信号,然后处理信号…

Eyeshot .NET 2023.1 Crack

概述 Eyeshot 是.NET 的 CAD 控件。它本身支持Windows Forms和Windows Presentation Foundation。它随附四个不同的Visual Studio工具箱项目:用于 2D 和 3D 几何创建或编辑的设计、用于自动生成 2D 视图的 绘图、使用线性静态分析进行几何验证的模拟以及用于CNC刀具…

MySQL学习笔记(十八)—— 事务基本知识

1. 数据库事务概述 存储引擎支持请况 SHOW ENGINES; # 命令来查看当前 MySQL 支持的存储引擎都有哪些,以及这些存储引擎是否支持事务。能看出在 MySQL 中,只有InnoDB 是支持事务的。 基本概念 事务:一组逻辑操作单元,使数据从一…

4.8 Beijing Rust Meetup | Call For Presenters

如果你有兴趣参与探讨Rust作为一种强调性能、安全和并发性的编程语言的各种应用、实践和无限可能性的头脑风暴,就一定不能错过这场来自达坦科技、南京大学、CloudWeGo、华为等技术专家带来的关于Rust编程语言相关应用的线下Meetup。我们的主题是Rust 💡X…

stable diffusion成为生产力工具(一):制作购物车图标icon

S:你安装stable diffusion就是为了看小姐姐么? I :当然不是,当然是为了公司的发展谋出路~~ 预先学习: 安装webui《Windows安装Stable Diffusion WebUI及问题解决记录》。运行使用时问题《Windows使用Stable Diffusion时…

nodejs微服务:微服务集群

搭建Grpc微服务集群 某单一的微服务,比如:micro_a, 部署在一台机器上挂掉后, 不管是微服务机器挂掉还是consul_client挂掉,都会导致整个微服务不可访问,这时候我们就需要进行微服务的集群也就是 micro_a 的微服务不能部署到一台机…

基于html+css的盒子旋转

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…

Java多线程编程—wait/notify机制

文章目录1. 不使用wait/notify机制通信的缺点2. 什么是wait/notify机制3. wait/notify机制原理4. wait/notify方法的基本用法5. 线程状态的切换6. interrupt()遇到方法wait()7. notify/notifyAll方法8. wait(long)介绍9. 生产者/消费者模式10. 管道机制11. 利用wait/notify实现…