WebGL学习笔记(四):绘图
图元
WebGL可以绘制非常复杂的3D模型,这些模型都是由下面3种基本几何图元构成的,下面我们来详细的看看。
三角形
WebGL中任何复杂的模型,都是由三角形组合而成的,可以说三角形是任意形状的最小构成单位。
WebGL可以绘制下面几种三角形:
独立的三角形(gl.TRIANGLES)
指定3*n个任意点,可以任意绘制的三角形,优点是没有限制,缺点是数据量大;
三角形带(gl.TRIANGLE_STRIP)
经过指定的规则,绘制连在一起的三角形,比如4个点就可以绘制2个三角形了,优点是数据量小,缺点是顶点顺序要按照指定的顺序来;
三角扇(gl.TRIANGLE_FAN)
类型三角形带,是另外一套绘制规则;
直线
虽然,3D中的大部分图形都是由三角形组成的,但是当我们需要绘制如线框之类的纯线段时,就需要使用到直线这种图元了。
同样,直线的绘制也有几种方式:
独立线(gl.LINES)
指定2*n个任意点,可以任意的绘制线段;
线带(gl.LINE_STRIP)
传入的点,是连续的,比如传入3个点就会绘制2条线段;
线环(gl.LINE_LOOP)
类似线带,最后一个点和第一个点会绘制直线;
点(gl.POINTS)
需要提前设定点的大小,在WebGL中,点经常用来实现粒子效果,比如模拟火焰烟雾等。
三角形顶点顺序和背面剔除
我们需要确定一个三角形三个点的顺序,顺序有两种顺时针(gl.CW)和逆时针(gl.CCW);
当我们确定这个顺序之后,就可以知道一个三角形面,是正对着我们还是背对着我们了,比如当我们确定顺时针的顶点的三角形是正面时,当有三角形在绘制时其顶点时逆时针的时候,这些三角形就是背向我们的了,背向我们的三角形,一般来说都是看不见的,为了提高运行效率可以不进行绘制,这就是背面剔除技术。
// 设定逆时针顶点顺序为正面
gl.frontFace(gl.CCW);
// 开启背面剔除
gl.enable(gl.CULL_FACE);
// 剔除背面
gl.cullFace(gl.BACK);
绘图方法
gl.clear
该方法会清除整个颜色缓冲,并填充颜色为 gl.clearColor 设定的颜色;
gl.drawArrays
通过前面设定好的顶点来绘制图像(可以指定要绘制那种图元);
gl.drawElements
和 drawArrays 基本一至,不同的地方是,这个方法支持传入索引缓冲,通过索引缓冲,可以用更少的顶点来绘制图像;
类型化数组
由于js中并没有指定位数的数字,所有的数字使用的类型都是64位(整形和浮点型都包括),而在WebGL中,需要操作二进制数据,js天生是不支持二进制数据的操作的(以前有人通过字符串的操作来实现,但是效率极低),所以特别引入了类型化数组来操作二进制数据,解决这个问题:
- ArrayBuffer:作为内存区域,可以存放多种类型的数据。不同数据有不同的存储方式,这就叫做“视图”。
目前,JavaScript提供以下类型的视图:
- Int8Array:8位有符号整数,长度1个字节。
- Uint8Array:8位无符号整数,长度1个字节。
- Uint8ClampedArray:8位无符号整数,长度1个字节。(和Uint8Array的区别在于处理不在[0-255]范围内的数字不一样,详情查看:https://blog.csdn.net/cuixiping/article/details/42270561)
- Int16Array:16位有符号整数,长度2个字节。
- Uint16Array:16位无符号整数,长度2个字节。
- Int32Array:32位有符号整数,长度4个字节。
- Uint32Array:32位无符号整数,长度4个字节。
- Float32Array:32位浮点数,长度4个字节。
- Float64Array:64位浮点数,长度8个字节。
可以将ArrayBuffer看做二进制数据源,他本身是不能直接操作二进制数据的,而多个类型的Array则是可以操作该二进制数据源的视图,具体使用方法如下:
// 创建 4 个字节大小的数组缓冲
var arrayBuffer = new ArrayBuffer(4);
// 创建 Int32 位的操作视图
var int32View = new Int32Array(arrayBuffer);
// 给第一个数组元素赋值, 可以理解为在 0 号字节位置写入一个 int32 类型的数字
int32View[0] = 10000000;
// 创建 Uint8 位的操作视图
var unit8View = new Uint8Array(arrayBuffer);
// 打印后即可看到 Int32 位的 10000000 在 Uint8 的字节中看起来的样子了
console.log(unit8View); // Uint8Array(4) [128, 150, 152, 0]
退化三角形
如果一个三角形的面积是0的话,这种三角形就被称为退化三角形,WebGL遇到退化三角形时,会进行跳过不绘制。
通过这个特性,我们在绘制三角带(正常情况绘制出来是必须连着的)时,可以在一个三角带中插入一个或多个退化三角形来绘制多个相互之间不相连的图像。
顶点变换缓存
为了减少传递到显卡的顶点数量,我们会采取使用共享顶点的方式,比如一个矩形由两个三角形组成,我们会传递4个顶点而不是6个,那么我们知道,我们的顶点会经过顶点着色器进行变换,这就意味着在渲染管线中,共享的顶点可能会经过多次的转换,而除了第一次的转换,后面的转换都是多余的,平均缓存缺失率表示一个顶点被转换的次数,下面是来自网络的记录:
ACMR(平均缓存缺失率):每个三角形所处理的平均顶点数量,该数据用来测量渲染性能。在典型的封闭网络中,三角形数量约等于两倍的顶点数量,理想的ACMR值为0.5,理想的取值范围为0.5~1,最坏的情况是3;
欧拉多面体公式:V-E+F=2 V表示顶点,e表示边,f表示面,优化ACMR的方法是对三角形中的顶点进行排序;
交叉存放顶点数据
顶点缓冲,除了存放顶点的坐标数据外,还可以同时存放颜色、法线、纹理坐标等数据;
使用常量顶点数组
我们之前提交的顶点缓冲,在顶点着色器中,会按照我们指定的顺序处理每一个顶点,代码如下:
// 将提交的顶点数据绑定到着色器的 aVertexPosition 属性, 并设置每份数据的尺寸和数据类型
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, vertexBuffer.itemSize, gl.FLOAT, false, 0, 0);
// 开启属性 aVertexPosition 作为数组的使用, 开启之后,顶点着色器会按照每个顶点的尺寸来遍历处理这些数据,即顶点着色器每次处理该属性的值都会改变
gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
那么如果我希望是传递一个数据,该数据对于每一个顶点来说,都是不变的时候,可以用下面的方法来实现:
// 将一个 vec4 的数据直接绑定到 vertexColorAttribute 属性
gl.vertexAttrib4f(shaderProgram.vertexColorAttribute, 0, 0, 0, 1);
// 关闭该属性作为数组的使用,关闭之后,顶点着色器每次处理 vertexColorAttribute 属性的值都不会改变
gl.disableVertexAttribArray(shaderProgram.vertexColorAttribute);
通过调用enableVertexAttribArray和disableVertexAttribArray就可以确定指定的属性是否是常量数据;
示例
点击查看示例1:交叉存放顶点数据;
https://hammerc.github.io/dou3d-ts/learning/learningNotes/lesson_2/index_1.html
点击查看示例2:多种类型图元绘制;
https://hammerc.github.io/dou3d-ts/learning/learningNotes/lesson_2/index_2.html
WebGL学习笔记(四):绘图的更多相关文章
- webgl学习笔记四-动画
写在前面 建议先阅读下前面我的三篇文章. webgl学习笔记一-绘图单点 webgl学习笔记二-绘图多点 webgl学习笔记三-平移旋转缩放 下面我们将讲解下如何让一个正方形动起来~不断擦除和重绘 ...
- webgl学习笔记二-绘图多点
写在前面 建议先看下第一篇webgl学习笔记一-绘图单点 第一篇文章,介绍了如何用webgl绘图一个点.接下来本文介绍的是如何绘制多个点.形成一个面. webgl提供了一种很方便的机制,即缓冲区对象, ...
- webgl学习笔记一-绘图单点
写在前面 WebGl(全称:Web Graphics Library : web图形库) 是基于OpenGL ES 2.0的3D绘图协议. WebGL完美地解决了现有的Web交互式三维动画的两 ...
- webgl学习笔记五-纹理
写在前面 建议先阅读下前面我的三篇文章. webgl学习笔记一-绘图单点 webgl学习笔记二-绘图多点 webgl学习笔记三-平移旋转缩放 术语 : 纹理 :图像 图形装配区域 :顶点着色器顶点坐标 ...
- webgl学习笔记三-平移旋转缩放
写在前面 建议先阅读下前面我的两篇文章. webgl学习笔记一-绘图单点 webgl学习笔记二-绘图多点 平移 1.关键点说明 顶点着色器需要加上 uniform vec4 u_Translation ...
- WebGL学习笔记二——绘制基本图元
webGL的基本图元点.线.三角形 gl.drawArrays(mode, first,count) first,代表从第几个点开始绘制即顶点的起始位置 count,代表绘制的点的数量. mode,代 ...
- C#可扩展编程之MEF学习笔记(四):见证奇迹的时刻
前面三篇讲了MEF的基础和基本到导入导出方法,下面就是见证MEF真正魅力所在的时刻.如果没有看过前面的文章,请到我的博客首页查看. 前面我们都是在一个项目中写了一个类来测试的,但实际开发中,我们往往要 ...
- IOS学习笔记(四)之UITextField和UITextView控件学习
IOS学习笔记(四)之UITextField和UITextView控件学习(博客地址:http://blog.csdn.net/developer_jiangqq) Author:hmjiangqq ...
- java之jvm学习笔记四(安全管理器)
java之jvm学习笔记四(安全管理器) 前面已经简述了java的安全模型的两个组成部分(类装载器,class文件校验器),接下来学习的是java安全模型的另外一个重要组成部分安全管理器. 安全管理器 ...
- Learning ROS for Robotics Programming Second Edition学习笔记(四) indigo devices
中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS for Robotics Pr ...
随机推荐
- CI框架扩展系统类库
CI框架不支持像yii2框架那样,可以直接在controllers下创建CommonController并继承父类,那么我们想要做登录控制或权限控制时,直接在父类控制器操作是不合理的. 这时比较方便的 ...
- 动态渲染左侧菜单栏 :menu tree 动态渲染
其中后端代码不包含权限控制,同时支持二级(无子菜单) 和 三级菜单(无子菜单). 1.layui前端代码:(其他前端框架实现方法通用,不过需要修改js中append对应标签元素即可) <div ...
- 动手搭建codecombat服务
# 因为后面需要使用浏览器访问 127.0.0.1:3000去获取管理员控制权,所以需要一个图形化的界面. yum install net-tools -y yum groupinstall &q ...
- 如何自动加载scratch3.0的页面上实现自动加载原有的作品
首先,我们在安装scratch3.0后,浏览器默认打开的是编程的页面.如下图: 那么我们希望开发一个功能,就是打开的时候默认加入某一个SB3的开发文件 1.首先,我们需要有一个.SB3的开发文件,建议 ...
- 《TensorFlow2深度学习》学习笔记(四)对笔记二中的模型增加正确率展示
全部代码如下:(红色部分为与笔记二不同之处) #1.Import the neccessary libraries needed import numpy as np import tensorflo ...
- 前端知识--控制input按钮的可用和不可用
最近在项目的开发的时候,自己虽然是写后端的,但是,在开发核心的时候,前端的知识自己还是会用到的,多以前端这块自己由于好长时间都没有去看,所以几乎已经忘记的差不多了,现在也只能是想起一点记录一点,以便能 ...
- Dubbo源码分析:ProxyFactory
roxyFactory将对外开放的服务进行封装.这里使用到代理的方式.ProxyFactory接口有两个不同的实现类:JavassistProxyFactory和JdkProxyFactory.Jdk ...
- MySQL 详细解读undo log :insert undo,update undo
转自aobao.org/monthly/2015/04/01/ 本文是对整个Undo生命周期过程的阐述,代码分析基于当前最新的MySQL5.7版本.本文也可以作为了解整个Undo模块的代码导读.由于涉 ...
- 持续集成学习7 jenkins自动化代码构建
一.整体功能 1.触发上下游构建 2.我们在触发一个job的时候顺便丢一些参数过去,这些参数有可能是我这次编译过程中产生的一些地址,版本号或动态的一些东西丢到下游作为下游的构建参数 3.不同种类的视图
- js解决大文件断点续传
最近遇见一个需要上传百兆大文件的需求,调研了七牛和腾讯云的切片分段上传功能,因此在此整理前端大文件上传相关功能的实现. 在某些业务中,大文件上传是一个比较重要的交互场景,如上传入库比较大的Excel表 ...