1. canvas和webgl
WebGL是利用canvas来实现的
canvas和img等标签一样,是一个可以自由制定大小的矩形区域。
通过javascript可以对矩形区域进行操作,可以自由的绘制图形,文字等。而且,可以添加影子,进行涂色,另外还可以对绘制的图形进行旋转等操作。
一般使用canvas都是使用它的2d的context功能,但是也仅限于此,像它的名字一样,只能用于2d空间的绘图。
和这个相对的,WebGL是三维,可以描画3D图形,区别于之前的2dcontext,它叫做webglcontext。
2. 3D绘图基础
利用WebGL可以模拟三维空间,但是最终必须输出显示在一个二维的显示器上。由深度决定的前后关系,根据远近进行放大和缩小,这些都必须提前进行运算得出结果。
这时候,坐标变换就是必须的了。坐标变换大致可以分为三种,将这些正确的组合在一起,最终决定显示器上的位置。
模型变换:第一种变换 定义参照物在三维空间的什么位置。假设,虚拟的三维空间里有一个苹果,那么为了表示这个苹果在什么位置,就需要进行相应的模型变换了。
视图变换:第二种变换 为了决定镜头的位置和角度所进行的坐标变换就叫做视图变换。即使三维空间中有一个苹果,如果镜头的方向不对着苹果的话,同样也是看不到这个苹果的。而且,如果将镜头大幅度远离苹果,那么也有可能看不到苹果了。
投影变换:这个变换,定义了三维空间的摄影区域。比如,是横向摄影,还是纵向摄影,最远拍摄多远距离等。
3. 矩阵
矩阵虽然有很多种,其中的一种叫做方阵。就是行数和列数相同的矩阵。
一般的3D渲染的世界中使用的是4x4的矩阵。
实际3D渲染的时候,准备好模型坐标变换,视图坐标变换,投影坐标变换的各个矩阵。再具体一点,就是准备好各种坐标变换的矩阵,然后相乘。将最终得到的矩阵传给WebGL的顶点着色器。
矩阵可以将上面提到的变换保存起来,比如,如果是模型变换的矩阵,想要绘制的3D模型的位置,扩大缩小,以及旋转等信息,都可以定义在一个矩阵中。视图变换矩阵,镜头的位置,镜头的方向,以及镜头对准了哪个点(注视点)等可以定义在一个矩阵中。投影变换矩阵的话,显示的横竖比例和视角等信息可以定义在一个矩阵中。
需要注意一点,如果是普通的数学计算,相乘的时候,不需要注意相乘的顺序,比如2x3等于6,3x2也等于6。但是矩阵的话,根据相乘的顺序得出的结果是不同的。因为矩阵的这种性质,所以进行模型,视图,投影的矩阵相乘的时候,要特别注意相乘的顺序。
顶点着色器从传过来的矩阵中,获取到模型的坐标,加工到画面上显示出来。也就是说,操作坐标变换的矩阵,就可以决定模型在画面上如何绘制。
4. webgl可描述的东西
要说在WebGL的世界里能够描画什么,其实任何东西都可以描画。而描画的最基本的东西就是下面几种。
- 点
- 线段
- 三角形
WebGL就是使用三角形在画面上绘制一些东西。这个三角形就是一个多边形,一个多边形至少是将三个顶点连接画出来的三角形,所以一个绘制一个多边形,最少需要三个顶点。
顶点,就是三维空间上存在的一个点。当然,这个点需要有坐标位置。顶点的横坐标是x,纵坐标是y,深度是z。将包含这些信息的点连接起来就形成了一个多边形。
非常逼真的3D游戏用了你想像不到的大量的三角形,制作出了无比精美的人物和场景。
想要绘制复杂构造的模型的话,需要准备大量的非常小的多边形。用的多边形越少,绘制的模型的棱角就越明显。
想要绘制精美的模型,就需要更多的多边形,当然,这些多边形的数量增加的话,定点数量也会成倍成倍的增加,坐标计算的负荷就越大。
顶点链接顺序和遮挡剔除
3D渲染的世界里,看不到的东西不绘制的是减轻负担的最普通的方法。这就叫做遮挡剔除,如果设定了遮挡剔除,就只会绘制外侧看得见的多边形,内侧的所有多边形就都不再进行绘制了。
顺时针连接顶点的多边形是在外侧,而逆时针连接的多边形在内侧。所以,在定义顶点情报的时候,要特别注意。如果设定了遮挡剔除,本来应该在某个位置有个多边形,但是根本就不会进行绘制。
5.context初始化
代码语言:javascript复制window.onload = function () { var c = document.getElementById('canvas');
c.width = 500;
c.height = 300; var gl = c.getContext('webgl') || c.getContext('experimental-webgl');
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
}
代码语言:javascript复制gl.clear(gl.COLOR_BUFFER_BIT);
这个函数将画面清空,回到一个全新的状态。参数是要清空的对象,或者是WebGL中定义的常量。这一次,只是清空一下画面上的颜色,所以使用COLOR_BUFFER_BIT这个常量,这个常量是为了使用canvas里面指定的颜色来清空画面而定义的。
代码语言:javascript复制gl.clearColor(0.0, 0.0, 0.0, 1.0);
如果要清空画面所使用的颜色的话,就必须得另外定义了。这个函数是clearColor。clearColor函数的参数有四个,就是单纯的RGBA,很直观吧,使用方法如下。
6.着色器
WebGL中,所谓的固定渲染管线是不存在的。
固定渲染管线,简单来说,就是3d渲染所进行的一连串的计算流程,就像流水线一样。如果有了固定渲染管线,编写程序就比较容易了,因为所有的变换都是由固定渲染管线来完成的,但是缺点就是自由度低。固定渲染管线只能完成一些最基本的操作,如果想要做一些特殊的处理,就比较麻烦了。
WebGL中不存在固定渲染管线。也就是说,坐标变换必须全部由自己来做。而且,这个记述了坐标变换的机制就叫做着色器(Shader)。
这样可以由程序员控制的机制叫做可编辑渲染管线。而着色器又有 处理几何图形顶点的顶点着色器和处理像素的片段着色器两种类型。 由于WebGL中没有固定管线,所以必须准备好顶点着色器和片段着色器。
着色器的添加可以有多种做法。着色器是由程序员自己编写的,而且着色器的代码就是简单的字符串而已。所以,不管用什么方法,只要把这个着色器字符串传给程序就可以了。
最简单的方法,就是把着色器记录在HTML中。使用这种方法的话,是利用HTML的script标签来做的。下面是一个简单的例子。
代码语言:javascript复制<script id="vshader" type="x-shader/x-vertex">
※顶点着色器 </script>
<script id="fshader" type="x-shader/x-fragment">
※片段着色器 </script>
指定type属性的理由: type属性指定了[x-shader/x-vertex]和[x-shader/x-fragment],这并不是HTML中定义的正式的写法。但是一般的浏览器如果遇到不识别的标签的话会无视掉的,浏览器不会认为这是javascript代码的。浏览器只会把它当成无意义的字符串,而程序中则可以使用标签里面的内容。