本文是WebGL电子书的1.2节内容
学习本节课,建议先结合注释看看案例源码,对于不熟悉的WebGL API可以在MDN搜索文档,不过刚开始学习,没必要去掌握每一个WebGL API,把主要精力放在理解WebGL的整个渲染流程上面,如果你能建立渲染管线的概念,自然对WebGL系统会有一个基本的认知。
//类型数组构造函数Float32Array创建顶点数组
// 矩形四个顶点坐标的数据
var data=new Float32Array([0.5,0.5,-0.5,0.5,-0.5,-0.5,0.5,-0.5]);
new Float32Array([0.5,0.5,...
顶点数组数据的数值随意更改大小,范围控制在0.0~1.0之间,观察绘制出的图形轮廓变化,你会发现数组的8个子元素表示的是四边形的四个点顶位置。//开始绘制图形
gl.drawArrays(gl.LINE_LOOP,0,4);
第65行代码,drawArrays()
方法的第3个参数4,更改为3或2,观察图形轮廓变化。可以看出第三个参数表示是的绘制前几个点,两点确定一条直线,四个顶点绘制并且闭合后是矩形,如果前三个点组成矩形,两个点只能构成直线。
第65行代码,drawArrays
方法的第2个参数0,更改为1,会发现报错,canvas画布也不显示。其实是因为第二个参数表示从第几个点开始绘制,1表示从第二个开始,第三个据说不能再填写4,最大只能有3个点,因为第一个点没有参与绘制
第65行代码,drawArrays
方法的第1个参数LINE_LOOP
,分别更改为LINES
、LINE_STRIP
、TRIANGLES
,可以看到不同的效果,第一个参数成为绘制模式mode,不同的模式有不同的意思,可以查询WebGL中文文档gl.drawArrays()获取详细解释。
attribute
关键字这节课首先给大家引入一个新的着色器语法,声明顶点相关数据的时候需要用到attribute
关键字。
attribute vec4 apos;
声明的变量apos
表示矩形所有顶点的位置坐标。WebGL着色器语言之所以规定attribute
这样一个关键字,目的是为了javascript可以调用相关的WebGL API把顶点数据从javascript传递顶点着色器attribute
声明的变量。
//attribute声明vec4类型变量apos
attribute vec4 apos;
你可以看到案例代码中类型数组var data=new Float32Array([0.5,0.5,-0.5...
包含了矩形四个顶点的xy坐标。
//类型数组构造函数Float32Array创建顶点数组
var data=new Float32Array([0.5,0.5,-0.5,0.5,-0.5,-0.5,0.5,-0.5]);
javascript会调用相关的WebGL API通过下面的代码把类型数组data
中包含的顶点位置坐标数据传递给顶点着色器中attribute
关键字声明的变量apos
。
//获取顶点着色器的位置变量apos,即aposLocation指向apos变量。
var aposLocation = gl.getAttribLocation(program,'apos');
...
...
//创建缓冲区对象
var buffer=gl.createBuffer();
//绑定缓冲区对象,激活buffer
gl.bindBuffer(gl.ARRAY_BUFFER,buffer);
//顶点数组data数据传入缓冲区
gl.bufferData(gl.ARRAY_BUFFER,data,gl.STATIC_DRAW);
//缓冲区中的数据按照一定的规律传递给位置变量apos
gl.vertexAttribPointer(aposLocation,2,gl.FLOAT,false,0,0);
//允许数据传递
gl.enableVertexAttribArray(aposLocation);
var program=initShader(...)
,会调用第68行的初始化着色器函数initShader()
,该函数第一个案例代码中用到过,以后也会经常使用,暂时可以把它当成黑箱,知道总体作用就行。 执行该函数后,会返回一个程序program对象,同时顶点着色器的位置变量apos会 与program建立联系,你可以把apos理解为对象program的属性。//初始化着色器
var program = initShader(gl,vertexShaderSource,fragShaderSource);
getAttribLocation()
方法使当前定义的变量aposLocation指向apos变量,方法的第一个参数是对象program,第二个参数是顶点着色器位置变量apos,并使用引号标识。//获取顶点着色器的位置变量apos,即aposLocation指向apos变量。
var aposLocation = gl.getAttribLocation(program,'apos');
new Float32Array([0.5,...
定义的是矩形四个顶点的顶点坐标,仅定义了x和y轴坐标,8个元素存入数组,z轴坐标未定义,z轴方向垂直屏幕,如果图形没有旋转平面显示不受z影响,关于WebGL的坐标系问题可以先不关心。 当浏览器运行这句代码时,会在内存上开辟一个区域,初始化语句重定义的矩形顶点数据。//类型数组构造函数Float32Array创建顶点数组
var data=new Float32Array([0.5,0.5,-0.5,0.5,-0.5,-0.5,0.5,-0.5]);
gl.vertexAttribPointer(aposLocation,2,gl.FLOAT,false,0,0);
设定的是当执行第65行代码绘制函数gl.drawArrays()
时候,如何提取数据,该语句的第二个参数2表达的意思是两个数组为一组, 8个元素也就是总共四组,逐组传递给apos变量,查看第15行代码attribute vec4 apos;
可以知道apos是vec4类型数据,也就是有四个参数的向量,这样的话缺少两个数值元素, 这种情况下,一般第三个代表z轴的坐标值默认为0.0,第四个参数默认为1.0,数据逐组传递的过程就蕴含着GPU渲染管线逐顶点处理数据的概念。//创建缓冲区对象
var buffer=gl.createBuffer();
//绑定缓冲区对象,激活buffer
gl.bindBuffer(gl.ARRAY_BUFFER,buffer);
//顶点数组data数据传入缓冲区
gl.bufferData(gl.ARRAY_BUFFER,data,gl.STATIC_DRAW);
//缓冲区中的数据按照一定的规律传递给位置变量apos
gl.vertexAttribPointer(aposLocation,2,gl.FLOAT,false,0,0);
//允许数据传递
gl.enableVertexAttribArray(aposLocation);
gl.drawArrays(gl.LINE_LOOP,0,4);
相当于最后的发令枪,命令GPU开始逐顶点处理数据,并安装一定的方式处理顶点,生成最终像素数据,第一个参数控制的是如何根据点生成像素。//开始绘制图形
gl.drawArrays(gl.LINE_LOOP,0,4);
shader program
),在GPU顶点着色器单元上执行的是顶点着色器程序, 在GPU片元着色器单元上执行的是片元着色器程序。顶点着色器
//attribute声明vec4类型变量apos
attribute vec4 apos;
void main() {
//顶点坐标apos赋值给内置变量gl_Position
//逐顶点处理数据
gl_Position = apos;
}
片元着色器
void main() {
// 逐片元处理数据,所有片元(像素)设置为红色
gl_FragColor = vec4(1.0,0.0,0.0,1.0);
}
可编程顶点处理器(Programmable Vertex Processor
)又称为顶点着色器,用来执行顶点着色器程序
可编程片元处理器(Programmable Fragment Processor
)又称为片元着色器,用来执行片元着色器程序
GPU中有各种专门的寄存器,比如用来接收顶点坐标数据的寄存器是输入寄存器,从数据类型的角度看属于浮点寄存器,用来临时存储浮点数; 存储输出到显示器像素的帧缓存是输出寄存器,从处理速度的角度看是数据缓冲寄存器,GPU处理数据的速度要比显示器扫描帧缓存中像素数据的速度要快得多
显示器像素是显示器可以通过RGB值控制的最小单位,一幅图像是由大量像素点累积显示。着色器中的颜色定义会反映在显示器中
显示器的分辨率就是显示器长度方向像素点的个数X显示器宽度方向像素点的个数
屏幕相邻的两个像素单元的距离就是点距,点距越小显示效果越好,一般现在显示器0.2mm~0.4mm之间