WebGL绘制和变换三角形

1、绘制多个点

 构建三维模型的基本单位是三角形。不管三维模型的形状多么复杂,其基本组成部分都是三角形,只不过复杂的模型由更多的三角形构成而已。

gl.vertexAttrib3f()一次只能向顶点着色器传入一个顶点,而绘制三角形、矩形和立方体等,你需要一次性将图形的顶点全部传入顶点着色器。WebGL提供了一种很方便的机制,即缓冲区对象。 

缓冲区对象:可以一次性地向着色器传入多个顶点的数据。缓冲区对象是WebGL系统中的一块内存区域,我们可以一次性地向缓冲区对象中填充大量的顶点数据,然后将这些数据保存在其中,供顶点着色器使用。

 示例:

//顶点着色器程序
var VSHADER_SOURCE = `
attribute vec4 a_Position;
void main(){gl_Position = a_Position;//将attribute变量赋值给gl_Position变量gl_PointSize = 10.0;//设置尺寸
}
`;
//片元着色器程序
var FSHADER_SOURCE = `
precision mediump float;
uniform vec4 u_FragColor;//uniform变量
void main(){gl_FragColor = u_FragColor;//设置颜色
}`function main() {//获取<canvas>元素var canvas = document.getElementById('myCanvas');if (!canvas) {console.log("failed to retrieve the canvas element");return;}//获取WebGL的绘图上下文var gl = canvas.getContext('webgl');if (!gl) {console.log("failed to get webgl context");return;}//初始化着色器if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {console.log("failed to initialize shaders");return;}//*************设置顶点位置start***************/var n = initVertexBuffers(gl);if (n < 0) {console.log("failed to set the positions of the vertices");return;}//*************设置顶点位置end***************/var u_FragColor = gl.getUniformLocation(gl.program, 'u_FragColor');gl.uniform4f(u_FragColor, 1.0, 0.0, 0.0, 1.0);//设置canvas的背景色gl.clearColor(0.0, 0.0, 0.0, 1.0);//黑色//清除canvasgl.clear(gl.COLOR_BUFFER_BIT);//绘制三个点gl.drawArrays(gl.POINTS, 0, n);
}function initVertexBuffers(gl) {var vertices = new Float32Array([0.0, 0.5, -0.5, -0.5, 0.5, -0.5]);var n = 3;//1.1 创建缓冲区对象var vertexBuffer = gl.createBuffer();if (!vertexBuffer) {console.log("failed to create the buffer object");return -1;}//1.2 将缓冲区对象绑定到目标gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);//1.3 向缓冲区对象中写入数据gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);//2.1 获取顶点着色器变量位置var a_Position = gl.getAttribLocation(gl.program, 'a_Position');//2.2 将缓冲区对象分配给a_Positiongl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);//2.3 连接a_Position变量与分配给它的缓冲区对象gl.enableVertexAttribArray(a_Position);return n;
}

initVertexBuffers()函数的功能是:

  • 创建顶点缓冲区对象
  • 将多个顶点的数据保存在缓冲区中
  • 然后将缓冲区传给顶点着色器

1.1 使用缓冲区对象

使用缓冲区对象向顶点着色器传入多个顶点的数据,需要遵循以下五个步骤:

  1. 创建缓冲区对象(gl.createBuffer())
  2. 绑定缓冲区对象(gl.bindBuffer())
  3. 将数据写入缓冲区对象(gl.bufferData())
  4. 将缓冲区对象分配给一个attribute变量(gl.vertexAttribPointer())
  5. 开启attribute变量(gl.enableVertexAttribArray())
1.1.1 创建缓冲区对象

 执行该方法的结果是:WebGL系统中多了一个新创建出来的缓冲区对象

gl.createBuffer()函数规范如下:

gl.createBuffer();//创建缓冲区对象
返回值非null新创建的缓冲区对象
null创建缓冲区对象失败
错误

相应地,gl.deleteBuffer(buffer)函数可用来删除被gl.createBuffer()创建出来的缓冲区对象。

gl.deleteBuffer(buffer);//删除参数buffer表示的缓冲区对象
参数buffer待删除的缓冲区对象
返回值
错误
1.1.2 绑定缓冲区

将缓冲区对象绑定到WebGL系统中已经存在的“目标”上。这个“目标”表示缓冲区对象的用途,这样WebGL才能够正确处理其中的内容。gl.bindBuffer(gl.ARRAY_BUFFER,vertexBuffer)函数规范如下:

gl.bindBuffer(target,buffer);//允许使用buffer表示的缓冲区对象并将其绑定到target表示的目标上
targetgl.ARRAY_BUFFER表示缓冲区对象中包含了顶点的数据
gl.ELEMENT_ARRAY_BUFFER表示缓冲区对象中包含了顶点的索引值
buffer指定之前由gl.createBuffer()返回的待绑定的缓冲区对象。如果为null,则禁用对target的绑定
返回值
错误INVALID_ENUMtarget不是上述值之一,这时将保持原有的绑定情况不变
1.1.3 向缓冲区对象中写入数据gl.bufferData()

gl.bufferData(gl.ARRAY_BUFFER,vertices,gl.STATIC_DRAW);将第2个参数vertices中的数据写入了绑定到第1个参数gl.ARRAY_BUFFER上的缓冲区对象。gl.bufferData()的规范如下:

gl.bufferData(target,data,usage);//开辟存储空间,向绑定在target上的缓冲区对象中写入数据data
targetgl.ARRAY_BUFFER或gl.ELEMENT_ARRAY_BUFFER
data写入缓冲区对象的数据(类型化数组)

usage

表示程序将如何使用存储在缓冲区对象中的数据

gl.STATIC_DRAW只会向缓冲区对象中写入一次数据,但需要绘制很多次
gl.STREAM_DRAW只会向缓冲区对象中写入一次数据,然后绘制若干次
gl.DYNAMIC_DRAW会向缓冲区对象中多次写入数据,并绘制很多次
返回值
错误INVALID_ENUMtarget不是上述值之一,这时将保持原有的绑定情况不变

类型化数组

JavaScript中常见的Array对象是一种通用的类型,既可以在里面存储数字也可以存储字符串。而类型化数组,所有元素都是同一种类型(可提高性能)。

类型化数组的方法、属性和常量:

方法、属性和常量描述
get(index)获取第index个元素值
set(index,value)设置第index个元素的值为value
set(array,offset)从第offset个元素开始将数组array中的值填充进去
length数组的长度
BYTES_PER_ELEMENT数组中每个元素所占的字节数
//创建类型化数组方法一:
var vertices = new Float32Array([0.5,-0.5,0.0,0.1,0.4,0.6]);
//创建类型化数组方法二:
var vertices = new Float32Array(4);
1.1.4 将缓冲区对象分配给attribute变量(gl.vertexAttribPointer())

gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);//可以将整个缓冲区对象分配给attribute变量。其规范如下:

gl.vertexAttribPointer(location,size,type,normailzed,stride,offset);//将绑定到gl.ARRAY_BUFFER的缓冲区对象分配给由location指定的attribute变量
location指定待分配attribute变量的存储位置
size指定缓冲区中每个顶点的分量个数(1到4)。若size比attribute变量需要的分量数小,缺失分量将按照与gl.vertexAttrib[1234]f()相同的规则补全。例如,如果size为1,那么第2,3分量自动设为0,第4分量为1。
typegl.UNSIGNED_BYTE无符号字节,Uint8Array
gl.SHORT短整型,Int16Array
gl.UNSIGNED_SHORT无符号短整型,Uint16Array
gl.INT整型,Int32Array
gl.UNSIGNED_INT无符号整型,Uint32Array
gl.FLOAT浮点型,Float32Array
normalizetrue/false是否将非浮点型的数据归一化到[0,1]或[-1,1]区间 
stride默认0指定相邻两个顶点间的字节数
offset指定缓冲区对象中的偏移量,即attribute变量从缓冲区中的何处开始存储。如果从起始位置开始的,则offset为0
返回值
错误INVALID_OPERATION不存在当前程序对象
INVALID_VALUElocation大于等于attribute变量的最大数目。
1.1.5 开启attribute变量

为了使顶点着色器能够访问缓冲区内的数据,需要使用gl.enableVertexAttribArray()方法来开启attribute变量。

gl.enableVertexArray(location);//开启location指定的attribute变量
参数location指定attribute变量的存储位置
返回值
错误INVALID_VALUElocation大于等于attribute变量的最大数目。

执行完该命令后,缓冲区对象和attribute变量之间的连接就真正建立起来了。

同样,也可以使用gl.disableVertexAttribArray()来关闭分配。

1.2 gl.drawArrays()的第2个和第3个参数

gl.drawArrays(mode,first,count);//执行顶点着色器,按照mode参数指定的方式绘制图形
mode绘制方式:gl.POINTS、gl.LINES、gl.LINE_STRIP、gl.LINE_LOOP、gl.TRIANGLES、gl.TRIANGLE_STRIP、gl.TRIANGLE_FAN
first指定从哪个顶点开始绘制(整型数)
count指定绘制需要用到多少个顶点(整型数)

gl.drawArrays(gl.POINTS,0,3);//执行该命令后,顶点着色器被执行了3次,存储在缓冲区中的顶点坐标数据被依次传给attribute变量。

2、绘制三角形

//顶点着色器程序
var VSHADER_SOURCE = `
attribute vec4 a_Position;
void main(){gl_Position = a_Position;//将attribute变量赋值给gl_Position变量
}
`;
//片元着色器程序
var FSHADER_SOURCE = `
precision mediump float;
uniform vec4 u_FragColor;//uniform变量
void main(){gl_FragColor = u_FragColor;//设置颜色
}`function main() {//获取<canvas>元素var canvas = document.getElementById('myCanvas');if (!canvas) {console.log("failed to retrieve the canvas element");return;}//获取WebGL的绘图上下文var gl = canvas.getContext('webgl');if (!gl) {console.log("failed to get webgl context");return;}//初始化着色器if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {console.log("failed to initialize shaders");return;}//*************设置顶点位置start***************/var n = initVertexBuffers(gl);if (n < 0) {console.log("failed to set the positions of the vertices");return;}//*************设置顶点位置end***************/var u_FragColor = gl.getUniformLocation(gl.program, 'u_FragColor');gl.uniform4f(u_FragColor, 1.0, 0.0, 0.0, 1.0);//设置canvas的背景色gl.clearColor(0.0, 0.0, 0.0, 1.0);//黑色//清除canvasgl.clear(gl.COLOR_BUFFER_BIT);//绘制三个点gl.drawArrays(gl.TRIANGLES, 0, n);
}function initVertexBuffers(gl) {var vertices = new Float32Array([0.0, 0.5, -0.5, -0.5, 0.5, -0.5]);var n = 3;//1.1 创建缓冲区对象var vertexBuffer = gl.createBuffer();if (!vertexBuffer) {console.log("failed to create the buffer object");return -1;}//1.2 将缓冲区对象绑定到目标gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);//1.3 向缓冲区对象中写入数据gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);//2.1 获取顶点着色器变量位置var a_Position = gl.getAttribLocation(gl.program, 'a_Position');//2.2 将缓冲区对象分配给a_Positiongl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);//2.3 连接a_Position变量与分配给它的缓冲区对象gl.enableVertexAttribArray(a_Position);return n;
}

画面效果:

与第1章节绘制三个点,本段代码只改动了两个地方:

  • gl_PointSize = 10.0;被删除,因为该语句只有在绘制单个点的时候才会起作用。如果不删除,该语句也无效。
  • gl.drawArrays()方法的第1个参数从gl.POINTS被改成了gl.TRIANGLES。

2.1 基本图形

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

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

相关文章

【网络安全】HTTP协议 — 特点

专栏文章索引&#xff1a;网络安全 有问题可私聊&#xff1a;QQ&#xff1a;3375119339 目录 学习目标​ 一、请求与响应 1.服务器和客户端 二、不保存状态 1.不保存状态的协议 三、资源定位 1.URI&#xff08;统一资源标识符&#xff09; 四、请求方法 1.请求方法 五…

如何在window系统中安装Mysql

先简单来说说MySQL是什么&#xff1f; MySQL 是最流行的关系型数据库管理系统&#xff0c;在 WEB 应用方面 MySQL 是最好的 RDBMS(Relational Database Management System&#xff1a;关系数据库管理系统)应用软件之一。 MySQL 由瑞典 MySQL AB 公司开发&#xff0c;目前属于…

多模态模型训练QA

Q&#xff1a;InternLM-XComposer的最新版本把vit的参数量降低了但是效果好了&#xff0c;所以好奇scale up vision encoder的收益大么&#xff1f;还是说重点是一个好的llm&#xff1f; A&#xff1a;结论是二者同步扩大才会起作用。我们试下来结论是llm 7b情况下&#xff0c…

利用AI知识库,优化医保系统售后信息管理流程

在医疗行业中&#xff0c;传统知识库管理虽能整合医疗行业知识&#xff0c;但搜索和管理效率有限&#xff0c;导致医护人员难以高效利用。特别是面对医保系统等复杂系统时&#xff0c;他们常需依赖人工客服或繁琐的电子产品手册解决问题。而HelpLook AI知识库利用AI技术&#x…

中国人民解放军信息支援部队成立

中国人民解放军信息支援部队成立 ----------强化信息化战争能力&#xff0c;维护国家安全 阅读须知&#xff1a; 探索者安全团队技术文章仅供参考,未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作,由于传播、利用本公众号所提供的技术和信息而造成的任何直接或…

基于 Win32 编程,使用 C语言开发一个记事本。

现在 Win32 非常少见&#xff0c;因为太原始了&#xff0c;同时也因为高级语言做应用开发速度更快。但是用 C 语言开发一个 win32 记事本对于理解应用程序运行的内部原理还是很有帮助的&#xff0c;“最基础的就是最有用的”&#xff0c;Windows 编程圣经 《Windows 程序设计》…

HCIP学习笔记

个人学习hcip笔记 供参考 笔记有些乱 之后还会修改完善并添加其他篇幅 OSPF篇 OSPF采用组播方式发送hello包&#xff0c;组播地址为224.0.0.5 相关&#xff1a; 所有节点&#xff1a;224.0.0.1&#xff1b; 所有路由器&#xff1a;224.0.0.2&#xff1b; OSPF DRO发给DR&…

tcp inflight 守恒算法背后的哲学

tcp inflight 守恒拥塞控制的正确性 很久以前我开始纠结 tcp 锯齿&#xff0c;很多年后我知道这叫 capacity-seeking&#xff0c;甚至说 tcp 属于 capacity-seeking protocol 的原因就是它早已深入人心的 aimd 行为&#xff0c;而该行为生成了 tcp 锯齿。 在消除锯齿&#xf…

裸金属服务器和物理机有什么区别

今天&#xff0c;在我们生活的世界中&#xff0c;技术已经彻底改变了我们的生活。在开展在线业务时&#xff0c;服务器在快速高效地执行多项任务方面发挥了极其重要的作用。然而&#xff0c;很多人仍然对裡金属服务器和物理机感到很困惑。今天就给大家分析一下裡金属服务器和物…

算法训练营day15

一、层序遍历 参考链接7.2 二叉树遍历 - Hello 算法 (hello-algo.com) 层序遍历本质上属于广度优先遍历&#xff0c;也称广度优先搜索&#xff0c; BFS通常借助队列的先入先出的特性实现 参考链接102. 二叉树的层序遍历 - 力扣&#xff08;LeetCode&#xff09; 像这种较为…

利用技术优化医保购药体验:开发医保购药APP

为了解决线下医保买药繁琐的流程&#xff0c;利用技术优化医保购药体验成为了当务之急。因此&#xff0c;今天小编将为大家详解如何开发一款医保购药APP。 一、背景与意义 购药流程繁琐、耗时、信息不透明等问题日益凸显&#xff0c;亟需一种新的解决方案。开发医保购药APP可以…

【C++】类和对象④(类的默认成员函数:取地址及const取地址重载 | 再谈构造函数:初始化列表,隐式类型转换,缺省值)

&#x1f525;个人主页&#xff1a;Forcible Bug Maker &#x1f525;专栏&#xff1a;C 目录 前言 取地址及const取地址操作符重载 再谈构造函数 初始化列表 隐式类型转换 explicit关键字 成员变量缺省值 结语 前言 本篇主要内容&#xff1a;类的六个默认成员函数中…

全网人气排行第一的免费开源ERP:Odoo电商功能应用亮点介绍

Odoo E-Commerce是一款创新型电子商务管理系统&#xff0c;旨在帮助企业建立以客户为中心的B2B与B2C电子商务平台&#xff0c;提高电商业务敏捷性&#xff0c;保障利润&#xff0c;并确保客户体验战略与时俱进。 —— 开源智造Odoo老杨 什么是Odoo免费开源电商管理系统&#xf…

C++:new与delete

hello&#xff0c;各位小伙伴&#xff0c;本篇文章跟大家一起学习《C&#xff1a;new与delete》&#xff0c;感谢大家对我上一篇的支持&#xff0c;如有什么问题&#xff0c;还请多多指教 &#xff01; 文章目录 :rocket: C内存管理:airplane: 初识new和delete:airplane: new和…

海康智能相机FTP本地存图流程

背景&#xff1a;近期一个新项目需要使用到智能相机&#xff0c;借助智能相机算法直接输出检测结果并将相机图像进行本地化保存和展示。由于申购目标智能相机未到&#xff0c;暂时使用测试智能相机。 目标智能相机型号&#xff1a;海康智能相机MV-SC3050XC 当前测试相机型号…

autodesk系列软件安装错误1603,手动安装Autodesk Desktop Licensing Service之后,启动服务提示错误1067

一般Autodesk Desktop Licensing Service这个服务没安装或者不正常会导致autodesk系列软件安装错误1603或者其他报错。 手动安装Autodesk Desktop Licensing Service之后&#xff0c;启动服务提示错误1067&#xff0c; 解决方法如下 打开autoremove点击扩展功能&#xff0c;输…

基于CAPL的S19文件解析

&#x1f345; 我是蚂蚁小兵&#xff0c;专注于车载诊断领域&#xff0c;尤其擅长于对CANoe工具的使用&#x1f345; 寻找组织 &#xff0c;答疑解惑&#xff0c;摸鱼聊天&#xff0c;博客源码&#xff0c;点击加入&#x1f449;【相亲相爱一家人】&#x1f345; 玩转CANoe&…

UDS报文传输的四种帧

ISO14229-1规定了26个诊断服务细节&#xff0c;也就是UDS诊断报文的细节。它只规定了各个服务每个字节的含义&#xff0c;它不关心底层到底是怎么传输的。 ISO15765-2规定了基于CAN总线进行UDS报文传输的细节&#xff08;包括四种帧&#xff09;。是在CAN总线传输的情况下&…

掉落回弹问题(C语言)

一、N-S流程图&#xff1b; 二、运行结果&#xff1b; 三、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h>int main() {//初始化变量值&#xff1b;float b 100;float sum 0;int i 0;//运算&#xff1b;for (i 1; i < 10; i){//运算&…

力扣HOT100 - 101. 对称二叉树

解题思路&#xff1a; class Solution {public boolean isSymmetric(TreeNode root) {if(root null) return true;return recur(root.left, root.right);}boolean recur(TreeNode L, TreeNode R) {if (L null && R null) return true;if (L null || R null || L.…