1、WebGL介绍
1.1 WebGL不足
效果较差:较于桌面开发API:Direct3D、OpenGL、UE、Unity。
开发成本:熟悉并掌握一定的数据知识,例如:线性代数。
硬件要求:开发及部署系统硬件要求较高,尤其GPU。
1.2 WebGL学习基础
物理知识、{HTML、CSS、JavaScript、计算机图形学}、数学基础
1.3 WebGL学习资料
网站:
- WebGL中文网:WebGL中文网
- GAMES计算机图形学官网:GAMES简介 – 计算机图形学与混合现实在线平台
- Three.js网站(WebGL的二次封装):Three.js教程
课程:
- GAMES101-现代计算机图形学入门-闫令琪:GAMES101-现代计算机图形学入门-闫令琪 - Bing video
书籍:
- WebGL编程指南
- WebGL高级
- GPU编程与CG语言之阳春白雪下里巴人(康玉之)
2、WebGL入门
2.1 WebGL容器(坐标系)
canvas的坐标系如下图,其中canvas坐标的单位都是“px”
WebGL坐标系如下图,WebGL使用的是正交右手坐标系,每个方向可使用的值的区间都是(-1,1),超出该矩形区间的图像不会绘制。这些值与Canvas的尺寸无关,无论Canvas的长宽比是多少,WebGL的区间值都是一致的。
2.2 WebGL渲染管线
渲染管线就像一条流水线,由一系列具有特定功能的数字电路单元组成,下一个功能单元处理上一个功能单元生成的数据,逐级处理数据。
顶点着色器和片元着色器是可编程的功能单元,拥有更大的自主性,还有光栅器、深度测试等不可编程的功能单元。
CPU会通过WebGL API和GPU通信,传递着色器程序和数据:
- GPU执行的着色器程序可以通过useProgram方法切换。
- 传递数据就是把CPU主存中的数据传递到GPU显存中。
顶点缓冲区:形状的坐标信息。待加工的数据/数组,将这组数据给到程序,就可以进行处理。
uniform数据:shader里面的数据,把“顶点缓冲区”的数据传递给“顶点着色器”。
图元装配:这些顶点缓冲区用来干什么?做“方便面”。
光栅器:矢量的图形转换成像素图形。
片元着色器:把颜色/纹理加到光栅化后的像素上。
归属测试/模板测试、深度测试(3D):绘制前的测试。
2.3 WebGL关键名词
(1)顶点着色器
GPU渲染管线上一个可以执行着色器语言的功能单元,具体执行的就是顶点着色器程序。
WebGL顶点着色器程序在JavaScript中以字符串的形式存在,通过编译处理后传递给顶点着色器执行。
总结:顶点着色器主要作用就是执行顶点着色器程序对顶点进行变换计算。例如顶点位置坐标进行旋转、平移等矩阵变换,变换后新的顶点坐标然后赋值给内置变量gl_Position,作为顶点着色器的输出,图元装配和光栅化环节的输入。
(2)图元装配
硬件上具体怎么回事不用思考,从程序的角度来看,就是绘制函数drawArrays()或drawElements()第一个参数绘制模式mode控制顶点如何装配为图元:
- gl.LINES:把两个顶点装配成一个线条图元。
- gl.TRIANGLES:把三个顶点装配为一个三角面图元。
- gl.POINTS:一个点域图元。
(3)光栅化
分解成一些小的像素。
片元着色器
片元着色器和顶点着色器一样是GPU渲染管线上一个可以执行着色器程序的功能单元。顶点着色器处理的是逐顶点处理顶点数据,片元着色器是逐片元处理片元数据。
通过给内置变量gl_fragColor赋值可以给每一个片元进行着色,值可以是一个确定的RGBA值,可以是一个和片元位置相关的值,也可以是插值后的顶点颜色。
除了给片元进行着色外,通过关键字discard还可以实现哪些片元可以被丢弃,被丢弃的片元不会出现在帧缓冲区,自然不会显示在canvas画布上。
2.4 实例:鼠标动态绘制点
2.5 动态绘制多个点
蓝色:屏幕坐标系
绿色:canvas坐标系
最里面是:WebGL坐标系,坐标范围是(-1,1)
2.6 绘制命令
(1)webgl.drawArrays()
POINTS
LINES LINE_STRIP LINE_LOOP
TRIANGLES TRIANGLE_STRIP TRIANGLES_FAN
(2)drawElements()
好处:当大量数据时,顶点缓冲区数据量很大时,内存会受到限制。使用索引缓冲区,可以节省内存,重复利用点。
用法:需要创建一个索引缓冲区
3 WebGL常用API
(1)TypeArray类型化数组和Array无类型数组
TypeArray数组最大的作用:提升数组的性能。浏览器事先知道数组中的数据类型,故而处理起来更有效率。
JS中Array的内部实现是链表,可以动态增加减少元素,但是元素多时,性能会比较差。当访问某个元素时,需要通过链表一个一个地找下去。
类型化数组管理的是连续内存区域,知道了这块内存的起始位置,可以通过起始位置+N*偏移量(一次加法一次乘法操作)访问到第N个位置的元素。
类型化数组将实现拆分为缓冲和视图两部分。
- 一个缓冲(ArrayBuffer)描述的是内存中的一段二进制数据,缓冲没有格式而言,并且不提供机制访问其内容。
- 为了访问在缓存对象中包含的内存,你需要使用视图。视图可以将二进制数据转换为实际有类型的数组。
- 一个缓冲可以提供给多个视图进行读取,不同类型的视图读取的内存长度不同,读取出来的数据格式也不同。
(2)Float32Array和Float64Array
单精度,也即float,一般在计算机中存储占用4字节,也32位,有效位数为7位;双精度(double)在计算机中存储占用8字节,64位,有效位数为16位。
单精度是这样的格式,1位符号,8位指数,23位小数。 双精度是1位符号,11位指数,52位小数。 含义:表明单精度和双精度精确的范围不一样,
(3)类型化数组的方法、属性和常量
get(index) 、set(index,value)、set(array,offset)、length、BYTES_PER_ELEMENT
(4)顶点数据配置(顶点缓冲区)
createBuffer()方法会在GPU控制的显存上创建一个缓冲区用来存储顶点或顶面索引数据。通过deleteBuffer(buffer)表示:删除某个缓冲区,参数buffer表示顶点/顶点索引缓冲区的名字,也就是执行createBuffer()方法返回的对象变量名。
bindBuffer(target,buffer):target相同,也就是同类缓冲区在同一个时刻只能绑定一个,只有处于绑定状态才能传入数据。
- target:gl.ARRAY_BUFFER表示顶点缓冲区;ELEMENT_ARRAY_BUFFER表示顶点索引缓冲区。
- buffer:顶点缓冲区变量名。
bufferData(target,data,usage):把CPU控制的内存中类型数组传入GPU控制的线程顶点或顶点索引缓冲区。
- target:
- data:CPU内存
- usage:通过不同的值控制传入缓冲区数据的方式、GPU使用缓冲区调用数据方式:gl.STATIC_DRAW静态绘制模式(只绘制一次);gl.STREAM_DRAW流绘制模式;gl.DYNAMTC_DRAW动态绘制模式
vertexAttribPointer(location,size,type,normalized,stride,offset)
规定GPU从顶点缓冲区去读取数据的方式,很多时候为了提高顶点数据的传输读取效率,往往会把顶点位置、顶点颜色、顶点法向量、纹理坐标交叉定义在一个类型数组汇总,一次性传入顶点缓冲区中,CPU和GPU不需要多次通信,只需要执行一次databuffer()方法,这时候GPU为了使用顶点缓冲区的不同用于数据,就要按照一定规律读取。
可以在同一个WebGL程序中定义多个该方法,每个方法的参数location分别指向一个不同的顶点变量,然后控制其后面其他的参数。
- location:顶点着色器程序中顶点的位置(shader中的变量-》JS中的变量)
- size:每次取几个数据(x,y,z,1.0)。如果该值为1,着色器程序中的顶点变量vec4后的第2,3分量是0,第4分量是1。
- type:顶点数据类型,所有数据没有分界线,只能靠类型按作用的位bit数来分界。
- normalized:布尔值,是否归一化到区间[0,1],[-1,1],一般为false
- stride:点个数*字节数
- offset:CPU从一组数据中第几元素开始读取数据
enableVertexAttribArray(location)
顶点缓冲区和GPU渲染管线之间存在一个硬件单元可以决定GPU是否能读取顶点缓冲区中的顶点数据。关闭方法:disableVertexAttribArray(location),location是顶点着色器程序中顶点变量的索引位置。