webgl绘制图形API——drawArrays、drawElements

news2024/12/28 5:21:20

文章目录

  • 前言
  • gl.drawArrays()——按顶点绘制
    • 可绘制基本类型
    • 绘制矩形和圆形
  • gl.drawElements()——按索引绘制
    • 使用规范
    • 绘制矩形
  • 总结


前言

gl.drawArrays()作为webgl中常用的函数图形绘制方法,可以在浏览器按照指定的模式绘制图形,与之相对的gl.drawElements()函数也是常用的绘制函数,本文将介绍二者的区别与使用。


gl.drawArrays()——按顶点绘制

可绘制基本类型

gl.drawArrays(mode, first, count)的使用在webgl图形绘制基础中有过详细的介绍,它的mode参数其实十分强大,可以按照不同的规则绘制不同的图形,可直接绘制的图形有七种,这七种图形是绘制其它各种复杂图形的基础。

参数名图形描述
gl.POINTS一系列点,依次绘制
gl.LINES线段每两个一组绘制线段,若点的数目为奇数,最后一个点会被舍弃
gl.LINES_STRIP线条所有的点依次相连
gl.LINE_LOOP回路再线条的基础上,将首尾点相连
gl.TRIANGLES三角形每三个一组绘制三角形,若点的数目无法被三整除,剩余的点会被舍弃
gl.TRIANGLES_STRIP三角带一系列条带状的三角形,每个三角形都存在一条边共享
gl.TRIANGLES_FAN三角扇类似于扇形的图形

在这里插入图片描述

绘制矩形和圆形

绘制矩形可以通过两个三角形完成,要注意顶点数据必须按照三角形逆时针方向给出。

const vertices = new Float32Array([
      // 第一个三角形
			-0.3, 0.3, 
			-0.3, -0.3,
			0.3, -0.3,
      // 第二个三角形
			0.3, -0.3, 
			0.3, 0.3,
			-0.3, 0.3,
		])

在这里插入图片描述

绘制圆形的原理相似,当相同大小的三角形具备同一个顶点并组成一个闭环时,就可以近似视为圆。三角形数越多,圆形越近似。

当用十个点绘制时:

	const _circle = [];
    for (let i = 0; i <= 10; i++) {
      const angle = i * Math.PI * 2 / 10; // 把2Π分成10份
      _circle.push(0 + 0.3 * Math.sin(angle), 0 + 0.3 * Math.cos(angle));
    }
    const circle = new Float32Array(_circle);

在这里插入图片描述

当用一百个点绘制时:

	const _circle = [];
    for (let i = 0; i <= 100; i++) {
      const angle = i * Math.PI * 2 / 100; // 把2Π分成100份
      _circle.push(0 + 0.3 * Math.sin(angle), 0 + 0.3 * Math.cos(angle));
    }
    const circle = new Float32Array(_circle);

在这里插入图片描述
完整代码

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>webgl</title>
  <script src="./lib.js"></script>
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <style>
    body {
      margin: 0;
      padding: 0;
    }

    canvas {
      margin: 50px 30px;
      width: 500px;
      height: 500px;
    }
  </style>
</head>

<body>
  <canvas id="canvas"></canvas>
  <script>
    /** @type {HTMLCanvasElement} */
    //------------------------------------------------------创建画布

    // 获取webgl绘图上下文
    const gl = canvas.getContext('webgl');
    if (!gl) {
      throw new Error('WebGL not supported');
    }

    gl.clear(gl.COLOR_BUFFER_BIT)
    const vertex = `
			attribute vec4 aPosition;
			void main() {
				gl_Position = aPosition;
				gl_PointSize = 10.0;
			}
		`
    const fragment = `
			precision highp float;
			void main(){
				gl_FragColor =vec4(1.0,0.0,1.0,1.0);
			}
		`
    // 创建program
    const program = initShader(gl, vertex, fragment)
    // 获取attribute变量的数据存储位置
    const aPosition = gl.getAttribLocation(program, 'aPosition');
    // 创建缓冲区对象
    const buffer = gl.createBuffer();
    // 绑定缓冲区对象
    gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
    // 传入的数据
    const vertices = new Float32Array([
      // 第一个三角形
      -0.3, 0.3,
      -0.3, -0.3,
      0.3, -0.3,
      // 第二个三角形
      0.3, -0.3,
      0.3, 0.3,
      -0.3, 0.3,
    ])

    const _circle = [];
    for (let i = 0; i <= 100; i++) {
      const angle = i * Math.PI * 2 / 100; // 把2Π分成100份
      _circle.push(0 + 0.3 * Math.sin(angle), 0 + 0.3 * Math.cos(angle));
    }
    const circle = new Float32Array(_circle);
    // 开辟空间并写入数据
    gl.bufferData(gl.ARRAY_BUFFER, circle, gl.STATIC_DRAW)
    // 缓冲区对象分配给attribute变量
    gl.vertexAttribPointer(aPosition, 2, gl.FLOAT, false, 0, 0)
    // 开启attribue变量
    gl.enableVertexAttribArray(aPosition)
    // 开始绘制
    gl.drawArrays(gl.TRIANGLE_FAN, 0, 1000)
  </script>
</body>

</html>

gl.drawElements()——按索引绘制

使用规范

在绘制矩形时,实际上只需要四个顶点,可是使用gl.drawArrays却存储了六个顶点,每个顶点大小为 4 * 6 = 24 个字节,绘制矩形就浪费了 48 字节的空间,为了避免这种浪费,WebGL 提供了按照顶点索引进行绘制的方法gl.drawElements节省存储空间。

drawElements(mode, count, type, offset):将指定的缓冲区设置为预设的值

  • mode:绘制模式,与gl.drawArrays() 相同
  • count: 绑定元素数组缓冲区的元素数
  • type:元素数组缓冲区中值的类型,枚举如下:
    — gl.UNSIGNED_BYTE
    — gl.UNSIGNED_SHORT
  • offset:元素数组缓冲区中的字节偏移量

绘制矩形

效果
在这里插入图片描述

完整代码

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>webgl</title>
  <script src="./lib.js"></script>
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <style>
    body {
      margin: 0;
      padding: 0;
    }

    canvas {
      margin: 50px 30px;
      width: 500px;
      height: 500px;
    }
  </style>
</head>

<body>
  <canvas id="canvas"></canvas>
  <script>
    /** @type {HTMLCanvasElement} */
    //------------------------------------------------------创建画布

    // 获取webgl绘图上下文
    const gl = canvas.getContext('webgl');
    if (!gl) {
      throw new Error('WebGL not supported');
    }

    gl.clear(gl.COLOR_BUFFER_BIT)
    const vertex = `
			attribute vec4 aPosition;
			void main() {
				gl_Position = aPosition;
				gl_PointSize = 10.0;
			}
		`
    const fragment = `
			precision highp float;
			void main(){
				gl_FragColor =vec4(1.0,0.0,1.0,1.0);
			}
		`
    // 创建program
    const program = initShader(gl, vertex, fragment)
    // 获取attribute变量的数据存储位置
    const aPosition = gl.getAttribLocation(program, 'aPosition');
    // 创建缓冲区对象
    const buffer = gl.createBuffer();
    // 绑定缓冲区对象
    gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
    // 传入的数据
    const vertices = new Float32Array([
      // 第一个三角形
      -0.3, 0.3,
      -0.3, -0.3,
      // 0.3, -0.3,
      // 第二个三角形
      0.3, -0.3,
      0.3, 0.3,
      // -0.3, 0.3,
    ])
    // 索引缓冲区
    const index = new Uint16Array([0, 1, 2, 0, 2, 3])

    // 开辟空间并写入数据
    gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW)
    // 缓冲区对象分配给attribute变量
    gl.vertexAttribPointer(aPosition, 2, gl.FLOAT, false, 0, 0)
    // 开启attribue变量
    gl.enableVertexAttribArray(aPosition)

    const indexBuffer = gl.createBuffer();
    //绑定索引缓冲区
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
    //向索引缓冲区传递索引数据
    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, index, gl.STATIC_DRAW);

    // 开始绘制
    gl.drawElements(gl.TRIANGLES, index.length, gl.UNSIGNED_SHORT, 0);

  </script>
</body>

</html>

总结

gl.drawArrays()

  • 可绘制基本类型
  • gl.drawArrays()绘制矩形和圆形

gl.drawElements()按照索引绘制

  • 使用规范
  • 绘制矩形

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

字节跳动测试岗面试挂在2面,复盘后,我总结了失败原因,决定再战一次...

先说下我基本情况&#xff0c;本科不是计算机专业&#xff0c;现在是学通信&#xff0c;然后做图像处理&#xff0c;可能面试官看我不是科班出身没有问太多计算机相关的问题&#xff0c;因为第一次找工作&#xff0c;字节的游戏专场又是最早开始的&#xff0c;就投递了&#xf…

Java图形化界面---JSplitPane和JTabbedPane

目录 一、JSplitPane &#xff08;1&#xff09;JSplitPane的介绍 &#xff08;2&#xff09;JSplitPane的使用步骤 &#xff08;3&#xff09;案例 二、JTabbedPane &#xff08;1&#xff09;JTabbedPane的介绍 &#xff08;2&#xff09;JTabbedPane的使用步骤 &…

CSS样式基础内容6

目录 定位 为什么需要定位&#xff1f; 定位的四种方式 静态定位 相对定位 绝对定位&#xff08;脱标&#xff09; 子绝父相 固定定位&#xff08;脱标&#xff09; 固定定位---固定到版心右侧 粘性定位 定位的叠放顺序z-index 绝对定位盒子水平垂直居中 定位特殊特…

C#/WPF入门到多项目实战开发教程2——

登录界面 布局 右上角退出按钮 编辑图标和名称 用户名设置 布局 用户名框设置 密码框设置&#xff0c;使用模板进行设置 验证码框设置&#xff0c;使用模板进行设置 登录按钮 创建登录模板按钮 绑定模板 失败提醒 第三方登录设置 使用字体图标去替代一般图标&#xff0c;字体…

QThread的应用——在线程里面更新QProgressBar进度条

在线程里面更新QProgressBar进度条 编写QT软件的时候&#xff0c;经常会遇到点击某个按钮&#xff0c;进行一个比较耗时的计算。为了在计算过程中&#xff0c;软件界面就继续响应用户的点击&#xff0c;不会有卡死的感觉&#xff0c;一般会将这个耗时的计算放在另外一个线程里…

“打家劫舍”系列总结,偷不偷这个房间呢?(Java实现)

目录 前言 一、打家劫舍 ——>房子是线性的 1.1、dp定义 1.2、递推公式 1.3、初始化 1.4、遍历顺序 1.5、解题代码 二、打家劫舍II ——>房子是环型 2.1、分析 2.2、解题代码 三、打家劫舍III ——>房子是树形 3.1、dp含义 3.2、递推公式 3.3、解题代码…

【Trusted Firmware-A 移植】

Trusted Firmware-A 移植Trusted Firmware-A 简介步骤一、解压标准 tf-a 源码包,进入 tf-a 源码目录下&#xff1a;二、将 ST 官方补丁文件打到 tf-a 源码中&#xff1a;三、配置交叉编译工具链四、添加设备树文件五、编译源码六、固件烧写结果Trusted Firmware-A 简介 嵌入式…

Magisk工具使用指南

对于一般玩机用户,Magisk官方提供的发布版本即可满足要求,但对于高级开发者来说这远远不够,我们不仅仅是满足于使用,更要学会定制面具,最好的能完全理解面具的核心架构以便于自己也能写出来一套和面具差不多的工具,这才是我们研究面具最根本的原因所在。因为做移动安全,…

edp 基本信号-参数及命令

基本信号及概念通信双方及通道下图为edp规范中的总体框图。通过此框图我们可以了解到&#xff1a;交互的双方&#xff1a;1&#xff09;source device 即 显卡的显示控制部分2) sink device 即 显示屏 双方间的通道&#xff1a;1&#xff09; HPD 即热插拔&#xff0c;通过sink…

mysql之6中索引失效情况

对索引使用左或者左右模糊匹配 mysql> explain select * from user where name王五; -------------------------------------------------------------------------------------------- | id | select_type | table | type | possible_keys | key | key_len | ref …

2023.1.30---TF-A相关

完成TF-A源码的移植过程在tf-a源码目录下将补丁文件打到tf-a源码中2.在上级目录中的Makefile.sdk文件中&#xff0c;配置交叉编译工具链&#xff0c;找到CROSS_COMPILE将红色部分改为arm-linux-gnueabihf-3.在fds目录下添加设备树文件4.在上级目录中的Makefile.sdk文件中&#…

全世界游客访问最多的城市,重庆以5.9亿游客量排名第一

经过全面开放和“阳康”&#xff0c;旅游市场已经开始复苏。现在恰逢寒冬&#xff0c;海南等国内许多旅游胜地成为热门旅游目的地&#xff0c;泰国等国际旅游频频上热搜。旅游市场目前现状如何跟随《旅游市场数据报告》一起来了解吧。全国5A景区数量全国共有318个景区被评为AAA…

重温数据结构与算法之约瑟夫问题

文章目录前言一、暴力法二、动态规划三、实战3.1 力扣 1823. 找出游戏的获胜者3.2 洛谷 P1996 约瑟夫问题参考前言 约瑟夫问题&#xff0c;是一个计算机科学和数学中的问题&#xff0c;在计算机编程的算法中&#xff0c;类似问题又称为约瑟夫环&#xff0c;又称“丢手绢问题”…

K8s关键性概念图解

Kubernetes可以看做云原生时代的操作系统&#xff0c;统一管理下层的基础设施&#xff0c;如计算资源、网络资源、存储资源等等。将集群中存在的各种复杂关系抽象成各种API资源&#xff0c;以统一的方式暴露出各种接口&#xff0c;也便于未来的扩展以及开发团队根据自己的需要定…

JS创建ZIP文件,JSZip的使用

Hi I’m Shendi 最近编写压缩工具&#xff0c;需要使用js创建zip文件&#xff0c;使用 JSZip 插件 官网&#xff1a; https://stuk.github.io/jszip/ Github&#xff1a; https://github.com/Stuk/jszip https://sdpro.top/blog/html/article/1012.html 下载 NPM : npm inst…

论文笔记:NeRF: Representing Scenes as Neural Radiance Fields for View Synthesis

目录 文章摘要 1 Neural Radiance Field Scene Representation (基于神经辐射场的场景表示) 2 Volume Rendering with Radiance Fields (基于辐射场的体素渲染) 2.1 经典渲染方程 2.2 经典的体素渲染方法 2.3 基于分段采样近似的体素渲染方法 3 Optimizing a Neural Rad…

高通开发系列 - linux kernel启动阶段串口无打印采用LED点灯

By: fulinux E-mail: fulinux@sina.com Blog: https://blog.csdn.net/fulinus 喜欢的盆友欢迎点赞和订阅! 你的喜欢就是我写作的动力! 目录 问题背景kernel启动汇编探测kernel启动C函数阶段探测这篇文章之前请参考下:高通开发系列 - MSM8909指示灯操作 问题背景 最近在基于…

38. 外观数列

打卡!!!每日一题 今天给大家带来一道比较有意思的题目&#xff0c;先看看题目描述 题目描述&#xff1a; 题目示例&#xff1a; 大家题目读完可能还没太理解什么意思&#xff0c;我简单给大家翻译翻译&#xff1a; n&#xff1a;表示我们要计算多少次 每一次都是对前面一个…

详细介绍Sentence-BERT:使用连体BERT网络的句子嵌入

Sentence-BERT:Sentence Embeddings using Siamese BERT-Networks 使用连体BERT网络的句子嵌入 BERT和RoBERTa在诸如语义文本相似性&#xff08;STS&#xff09;的句子对回归任务上创造了新的最优的性能。然而&#xff0c;它要求将两个句子都输入网络&#xff0c;这导致了巨大的…

代码随想录--二叉树章节总结Part IV 完结篇

代码随想录–二叉树章节总结Part IV 完结篇&#x1f389; 1.Leetcode501 二叉树中的众数 给你一个含重复值的二叉搜索树&#xff08;BST&#xff09;的根节点 root &#xff0c;找出并返回 BST 中的所有 众数&#xff08;即&#xff0c;出现频率最高的元素&#xff09;。 如…