WebGL API文档

  文档会把常用的WebGL方法和属性一一列举,并介绍相关用法,大家在阅读别人代码遇到不懂的方法或属性时,可以通过浏览器页面,“Ctrl+F”快速搜索关键字,把本文档当做学习字典即可, 可以降低大家记忆压力。互联网的知识更新非常快不可能什么都记忆,往往很多知识都是在查看手册完成开发任务,而掌握了一项新的技能。

获取WebGL上下文

  所谓API就是一个应用程序编程接口,为了实现能够在Web上控制显卡硬件创建三维场景,对显卡的硬件细节进行了封装抽象,提供了一系列可以控制GPU渲染管线的函数, 这些函数的集合就是WebGL API。通过canvas画布对象的方法getContext()可以获得一个webgl的上下文,WebGL API的所有函数都是执行getContext()方法返回对象的方法, Javascript语言可以调用这些方法创建三维场景。

  如果知识面不够宽,提到WebGL、WebGL API、OpenGL API、OpenGL ES、canvas元素、canvas标签、canvas方法和属性、GLSL语言、GLSL ES、Javascript、JavaScript API、ECMAScript等概念可能会有所混乱, 如果分不太清可以先学习具体的命令如何使用,随着时间的推移,和知识的逐步积累,自然会理解。三维模型功能的在线预览实现需要通过HTML中众多元素中的一个canvas元素,canvas元素可以实现2D和3D绘图。 通过DOM对象方法getElementById()获取canvas对象,然后通过canvas对象的方法getContext(),可以获取一个上下文, 也可以说返回一个可以在canvas画布上绘图的环境,也可以说返回一个具有各种方法和属性的对象,当getContext()方法的参数是2d时,返回的是一个2D绘图环境;当getContext()方法的参数是webgl时, 返回的是一个3D绘图环境,也就是返回一个具有系列绘图方法和属性的CanvasRenderingContext对象,该对象具有一系列方法和属性,可以和Javascript编程语言、GLSL ES着色器语言相互配合完成一个三维场景的构建。 Javascript语言可以调用CanvasRenderingContext对象的方法和属性,CanvasRenderingContext对象可以称为Javascript语言的外置对象,该对象的方法和属性就是WebGL API,自然也可以称为Javascript API。这些方法和属性的 制定参照的是OpenGL ES,不同版本的WebGL参照不同版本的OpenGL ES。

canvas元素

属性 意义
height 画布高度
width 画布宽度
background-color 画布背景颜色
opacity 画布透明度

//在body标签里面创建一个canvas元素,画布的宽度、长度均为200,效果如下

<canvas id="myCanvas" width="200" height="200" style="background: #00B7FF;opacity: 0.5">
</canvas>

//在script标签里面获取canvas元素。

var canvas= document.getElementById('myCanvas');

getContext()方法

使用canvas元素对象的getContext()方法,“webgl”作为参数获取canvas的webgl上下文

类型数组和顶点缓冲区配置

内存显存enableVertexAttribArray()允许GPU读取数据GPU渲染管线顶点着色器单元vertexAttribPointer()数据读取规则设置createBuffer()创建缓冲区类型数据创建顶点数据bindBuffer()绑定缓冲区bufferData()数据转移执行Javascript程序执行着色器程序 顶点缓冲区createBuffer()bindBuffer()bufferData()vertexAttribPointer()enableVertexAttribArray()创建顶点或顶点索引缓冲区绑定缓冲区类型数据数据导入缓冲区设置GPU读取缓冲区中数据的规则允许GPU读取数据

类型数据

  在前端页面设计时,通常使用无类型数组构造函数Array,为了处理WebGL中大量的顶点数据在Javascript语言新标准ECMAScript 2015中引入类型数组,当然引入的类型数组构造函数也可以用解决来其它编程问题。

  数据的用途不同,要求的精度和形式自然不同,比如顶点索引使用整数即可,根据顶点的数量可以选择Uint8、Uint16、Uint32中的哪一种整型数据,顶点的位置一般使用浮点数来表示,浮点数可以选择不同的精度表示。 关于Javascript语言类型数组的更多基础知识可以关注《类型化数组》,下面简单列举两个例子一个是为了创建顶点数据, 一个是为了创建顶点数据的索引。

getAttribLocation(program,attributeName)

  执行该方法返回顶点着色器中顶点变量的索引地址

参数
program 程序对象
attributeName 顶点着色器程序中的顶点变量名
//获取顶点着色器的位置变量apos
var aposLocation = gl.getAttribLocation(program,'apos');

顶点数据配置

//创建缓冲区对象
var buffer=gl.createBuffer();
//绑定缓冲区对象
gl.bindBuffer(gl.ARRAY_BUFFER,buffer);
//顶点数组data数据传入缓冲区
gl.bufferData(gl.ARRAY_BUFFER,data,gl.STATIC_DRAW);
//缓冲区中的数据按照一定的规律传递给位置变量apos
gl.vertexAttribPointer(aposLocation,3,gl.FLOAT,false,0,0);
//允许数据传递
gl.enableVertexAttribArray(aposLocation);

顶点索引配置

    //创建缓冲区对象
    var indexesBuffer=gl.createBuffer();
    //绑定缓冲区对象
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,indexesBuffer);
    //索引数组indexes数据传入缓冲区
    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,indexes,gl.STATIC_DRAW);

createBuffer()和deleteBuffer()

  createBuffer()方法会在GPU控制的显存上创建一个缓冲区用来存储顶点或顶面索引数据,通过deleteBuffer(buffer)方法的作用是删除某个缓冲区,参数buffer表示顶点或顶点索引缓冲区的名字,也就是执行createBuffer()方法返回的对象变量名。

bindBuffer(target,buffer)

  target相同,也就是同类缓冲区在同一时刻只能绑定一个,只有处于绑定状态才能传入数据。

参数
target gl.ARRAY_BUFFER:表示顶点缓冲区
gl.ELEMENT_ARRAY_BUFFER:表示顶点索引缓冲区
buffer 顶点缓冲区变量名

bufferData(target,data,usage)

  bufferData()方法的作用是把CPU控制的主存中类型数组数据传入GPU控制的显存顶点或顶点索引缓冲区中。

参数
target 同bindBuffer()方法的target参数,保持一致
data 类型数组变量名:表示要传入缓冲区中的数组数据
usage 通过不同的值控制传入缓冲区数据的方式、GPU使用缓冲区调用数据方式
gl.STATIC_DRAW:静态绘制模式
gl.STREAM_DRAW:流绘制模式
gl.DYNAMIC_DRAW:动态绘制模式

vertexAttribPointer(location,size,type,normalized,stride,offset)

  顶点索引缓冲区不需要该方法,该方法的作用是规定GPU从顶点缓冲去中读取数据的方式,很多时候为了提高顶点数据的传输读取效率,往往会把顶点位置、顶点颜色、顶点法向量、纹理坐标交叉定义在一个类型数组中, 一次性传入顶点缓冲区中,CPU和GPU不需要多次通信,只要执行一次databuffer()方法,这时候GPU为了使用顶点缓冲去区的不同用途数据,就要按照一定规律读取,所以类型数据中的数据会把同一个顶点的所有用途数据连续放在一起, 不同顶点的数据依次排列。

  可以在同一个WebGL程序中定义多个该方法,每个方法的参数location分别只想一个不同的顶点变量,然后控制后面其它的参数保证取用不用的数据,最简单的思路就是每间隔几个数据,取用几个。

参数
location 顶点变量的位置
size size是整数1~4,表示每次取用几个数据,如果size是1,着色器中的顶点变量vec4后默认2、3分量是0,第4分量是1。
type 顶点数据类型,定义该参数主要是为了控制数据的存取,所有的数据没有分界线,只能靠数据类型占用的位bit数来分界

不同值       对应的类型数组
gl.UNSIGNED_BYTE:   Uint8Array
gl.SHORT:       Int16Array
gl.UNSIGNED_SHORT:  Uint16Array
gl.INT:        Int32Array
gl.UNSIGNED_INT:   Uint32Array
gl.FLOAT:      Float32Array
normalized 布尔值true或false,表示是否归一化到区间[0,1]或[-1,1]
stride 相邻两个顶点间隔的数据字节数,具体说就是一个顶点所有的顶点位置、顶点颜色、顶点法向量等顶点数据数量减去你要选择的那种顶点数据的数量, 顶点数量再乘以该类型数据一个元素占用的字节数,比如Float32Array创建的数据每个元素是4个字节。
offset 每个顶点的位置、颜色、法向量等数据是一组,offset是字节数,规定了GPU从一组数据中第几个元素开始读取数据。

enableVertexAttribArray(location)

  顶点缓冲区和GPU渲染管线之间存在一个硬件单元可以决定GPU是否能读取顶点缓冲区中的顶点数据,开启方法是enableVertexAttribArray(),能开启自然能够关闭,关闭的方法是disableVertexAttribArray(), 两个方法的参数都是顶点着色器程序中顶点变量的索引位置

编译着色器程序

         GPU渲染管线着色器createProgram()创建程序对象字符串格式顶点着色器程序片元着色器程序执行Javascript程序执行着色器程序useProgram()调用程序对象切换GPU上下文createShader()创建着色器shaderSource()compileShader()编译linkProgram()连接测试attachShader()绑定着色器 程序对象和着色器对象createShader()shaderSource()compileShader()createProgram()attachShader()linkProgram()useProgram()创建着色器对象着色器对象关联着色器程序编译着色器程序创建程序对象绑定着色器程序对象连接测试程序对象调用程序对象
//声明着色器初始化函数
    function initShader(gl,vertexShaderSource,fragmentShaderSource){
        //创建顶点着色器对象
        var vertexShader = gl.createShader(gl.VERTEX_SHADER);
        //创建片元着色器对象
        var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
        //引入顶点、片元着色器源代码
        gl.shaderSource(vertexShader,vertexShaderSource);
        gl.shaderSource(fragmentShader,fragmentShaderSource);
        //编译顶点、片元着色器
        gl.compileShader(vertexShader);
        gl.compileShader(fragmentShader);

        //创建程序对象program
        var program = gl.createProgram();
        //附着顶点着色器和片元着色器到program
        gl.attachShader(program,vertexShader);
        gl.attachShader(program,fragmentShader);
        //链接program
        gl.linkProgram(program);
        //使用program
        gl.useProgram(program);
        //返回程序program对象
        return program;
    }

给uniform和attribute变量传入数据

  顶点着色器中和片元着色器中会声明一系列的变量,attribute关键字声明的顶点类数据,uniform关键字声明的光线颜色方向、变换矩阵等统一类数据,除了不同的关键字定义个数据用途不同, 着色器语言中的数据类型也分很多类别,不同类型、不同用途的数据之间进行排列组合会创建出许多种变量,每种变量都要规定一个用于数据传输的WebGL API,如果数据量非常大,为了提高数据的传输读取效率, 就会在GPU可以控制的显存上创建一个缓冲区,一次性把CPU主存中的数据传入进去,比如最常见的顶点数据,复杂的几何模型往往MB或GB数量级,不可能GPU每读取一个顶点数据就与CPU通信一次,对于简单的变换矩阵、光线方向的统一类变量, 不需要创建缓冲区,执行一次相关的API就可以把数据传递给GPU着色器。关于大批量顶点数据的传输读取问题可以参考《类型数组和顶点缓冲区配置》,通过下面树状图列举的API传输数据不需要在显存上创建缓冲区。

给uniform和attribute变量传入数据attributefvertexAttrib1f()vertexAttrib2f()vertexAttrib3f()vertexAttrib4f()fvvertexAttrib1fv()vertexAttrib2fv()vertexAttrib3fv()vertexAttrib4fv()uniformfuniform1f()uniform2f()uniform3f()uniform4f()iuniform1i()uniform2i()uniform3i()uniform4i()fvuniform1fv()uniform2fv()uniform3fv()uniform4fv()ivuniform1iv()uniform2iv()uniform3iv()uniform4iv()MatrixuniformMatrix2fv()uniformMatrix3fv()uniformMatrix4fv()含义字母f——浮点数i——整数iv——整数int32类型数组fv——浮点数float32类型数组数字对应着色器语言中的数据类型1f——一个浮点数2f——向量vec23i——向量ivec3Matrix3fv——矩阵mat3变量性质attribute——顶点变量uniform——统一变量