WebGL坐标系

源码下载

  使用空间中的三个点构成的三角平面来测试,本节课的源码并不会呈现出这个效果,只是借此给大家引入一些问题

  完成第一和第二个案例后,想必你已经迫切希望呈现出三维的效果,本节课预先进行三维坐标系的讲解。

1    <!DOCTYPE html>
2    <html lang="en">
3    <head>
4        <meta charset="UTF-8">
5    </head>
6    <body>
7    <canvas id="webgl" width="500" height="500" style="background-color: #0d72da"></canvas>
8    <script>
9        var canvasElement=document.getElementById('webgl');
10       var gl=canvasElement.getContext('webgl');
11       //顶点着色器源码
12       var vertexShaderSource = '' +
13           //attribute声明vec4类型变量apos
14           'attribute vec4 apos;'+
15           'void main(){' +
16           //顶点坐标apos赋值给内置变量gl_Position
17           '   gl_Position =apos;' +
18           '}';
19       //片元着色器源码
20       var fragShaderSource = '' +
21           'void main(){' +
22           '   gl_FragColor = vec4(1.0,0.0,0.0,1.0);' +
23           '}';
24       //初始化着色器
25       var program = initShader(gl,vertexShaderSource,fragShaderSource);
26       //获取顶点着色器的位置变量apos
27       var aposLocation = gl.getAttribLocation(program,'apos');
28   
29       //9个元素构建三个顶点的xyz坐标值
30       var data=new Float32Array([
31           0, 0, 1,
32           0, 1, 0,
33           1, 0, 0
34       ]);
35   
36       //创建缓冲区对象
37       var buffer=gl.createBuffer();
38       //绑定缓冲区对象
39       gl.bindBuffer(gl.ARRAY_BUFFER,buffer);
40       //顶点数组data数据传入缓冲区
41       gl.bufferData(gl.ARRAY_BUFFER,data,gl.STATIC_DRAW);
42       //第二个代码案例vertexAttribPointer方法的第二个参数是2,这里是3
43       gl.vertexAttribPointer(aposLocation,3,gl.FLOAT,false,0,0);
44       //允许数据传递
45       gl.enableVertexAttribArray(aposLocation);
46       //开始绘制图形,使用TRIANGLES模式,三点构成一个平面
47       gl.drawArrays(gl.TRIANGLES,0,3);
48   
49       //声明初始化着色器函数
50       function initShader(gl,vertexShaderSource,fragmentShaderSource){
51           var vertexShader = gl.createShader(gl.VERTEX_SHADER);
52           var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
53           gl.shaderSource(vertexShader,vertexShaderSource);
54           gl.shaderSource(fragmentShader,fragmentShaderSource);
55           gl.compileShader(vertexShader);
56           gl.compileShader(fragmentShader);
57           var program = gl.createProgram();
58           gl.attachShader(program,vertexShader);
59           gl.attachShader(program,fragmentShader);
60           gl.linkProgram(program);
61           gl.useProgram(program);
62           return program;
63       }
64   </script>
65   </body>
66   </html>

体验测试

  1.   下载上面的源码用你的浏览器打开测试,你可以看一个直角三角形,准确地说你所看到是图像一个空间三角平面的投影,三角平面的三个顶点分别xyz轴上,说明投影的方向是其中的一个坐标轴所在的方向,才能呈现出这种效果
  2. WebGL正投影效果图

    节选自:《画法几何学》(大连理工教研室编)

  3.   尝试把31行代码中的数值1更改为0.5,查看屏幕的三角形是否有变化,若无变化,说明投影方向默认的是z轴,也就是说z轴WebGL系统默认的观察三维模型的视线方向,30行定义的数组里9个元素,每间隔3个为一组,分别代表xyz轴上的坐标值,刚刚更改的数值就是z
  4.   尝试把32~33行代码中的数值1更改为0.5,观察变化,回到数值初始状态,再把其中的一个1更改为2,观察变化。可以看到超出1的顶点,不会在图形区域显示出来,这就为以后显示大场景提供了基础,通过控制点坐标值的大小就可以控制是否在场景中显示出来
  5.   你可尝试把32行坐标的y值1更改为-1,把33行坐标的x值1更改为-1,可以看到三角形显示在左下角,可以看出WebGL坐标系-1~1区间对应的是canvas画布的四个边界线。
  6.   你可尝试把31~33行坐标的第三个数,也就是点坐标z值都设定为-1~1之外的数值,比如都更改为2,刷新浏览器你会发现没有任何图像,如果你更改其中一组,你会发现显示部分,顶点光栅化后,Z轴方向处在-1~1区域之外片元的会被剪裁掉

总结

WebGL坐标系
  1. canvas画布宽高采用的是像素值定义,以显示器为准,WebGL中顶点坐标的表示方法采用的是相对坐标,相对于canvas而言
  2. WebGL坐标系统,X轴水平向右,也就是canvas画布的width表示的宽度方向,x等于-1表示canvas画布的左边界,x等于1表示canvas画布的右边界,x等于0对应的是画布宽度方向的中间
  3. WebGL坐标系统,Y轴竖直向上,也就是canvas画布的height表示的高度方向,y等于-1表示canvas画布的下边界,y等于1表示canvas画布的上边界,y等于0对应的是画布高度方向的中间
  4. WebGL坐标系统,Z轴垂直canvas画布朝外,Z值-1和1是Z方向的极限值,GPU成像默认的沿着Z轴投影,你也可以抽象出一个概念,人眼睛位于z轴上,沿着z轴方向去观察物体,如果你在其他的书上看到视图坐标系等其它各类坐标系都是抽象出的概念 都是建立在本节课所说的WebGL 坐标系统之上,例如无人机导航中的所说的机体坐标系、地球坐标系都是直接对现实中事物的描述,三维场景中的各类坐标系与无人机中坐标系没什么区别,但是要显示在屏幕上,就要经过一些处理,这里不再详述,后面的教程后为大家引入各类坐标系概念, 正射投影和透射投影概念。

代码执行流程简述

  代码的执行流程与第二个代码示例基本一样,区别就是顶点数组不一样,vertexAttribPointer第二参数不一样,上一个例子是四个顶点,定义了每个顶点的x、y值,z值默认缺省设置为1, 本案例中定义的是三个点,每个点都定义了xyz坐标值,数组就像一个仓库,存储了大量数据,如何按照一定的规律从库中取出数据,WebGL定义了一个API就是vertexAttribPointer方法,该方法的第2、5、6参数描述的就是如何取出,比如从哪个数据开始取出 每几个数据为一组,间隔几个数据,暂时不用关心,后面用到自然明白,根据这两节课的学习,你至少知道第二参数定义的是几个数为一组。