1、WebGL编程指南笔记——自己总结
1、参考书目:
OpenGL
《OpenGL 着色语言》(通常也称作“橘皮书”)
经典红宝书
《Computer Graphics: Principles and Practice》第 3 版, John F. Hughes 等著( AddisonWesley, 2013)
《3D Computer Graphics》, Andrew S. Glassner 著(The Lyons Press, 1994)
《OpenGL Reference Manual》
2、内置变量:
gl_Position
gl_PointSize
gl_FragColor
gl_FragCoord vec4 该内置变量的前两个参数表示片元在< canvas >坐标系统(窗口坐标系统)中的坐标值。
gl.vertexAttrib3f(a_Position, 0.0, 0.0, 0.0);//向变量赋值
gl.vertexAttrib4fv(a_Position,positions);将一个个数据改成了向量。
var vertexBuffer = gl.createBuffer(); 使用缓冲区 批量输入
gl.uniform4f(u_FragColor, rgba[0], rgba[1], rgba[2], rgba[3]);//单个输入
gl.uniformMatrix4fv(u_xformMatrix, false, xformMatrix);//矩阵数组输入
// Unbind the buffer object
gl.(gl.ARRAY_BUFFER, null); 记得给缓冲区解绑
3、js要做的是向顶点着色器和片源着色器中传入 处理后的 最终的顶点、颜色、矩阵、法向量等基本信息;然后在着色器代码中,也即是字符串代码中进行乘数运算,当然了,提前在着色器中命名好 attribute、 uniform、 varying 等变量,在js的初始化代码中进行变量地址获取,传入数值等操作。
4、WebGL中矩阵的存储是以列主序存储: 列主序+行主序;
着色器的代码就是简单的字符串,可以直接在javascript内部定义字符串。
5、矩阵变换的时候得到的乘数矩阵和变换顺序是相反的:仔细想想矩阵的变换的先后顺序就知道了,因为都是左乘!
6、“ 根据自定义的观察者状态,绘制观察者看到的景象 ” 与 “ 使用默认的观察状态,但是对三维对象进行平移、旋转等变换、再绘制观察者看到的景象 ”,这两种行为是等价的。
7、视图矩阵(观察者的状态信息:视点+观察点+上方向)
模型矩阵(平移、缩放、旋转的混合矩阵)
投影矩阵(正射投影矩阵+透视投影矩阵)
模型视图矩阵 = 视图矩阵 x 模型矩阵
模型视图投影矩阵 = 投影矩阵 x 视图矩阵 x 模型矩阵
8、在任何三维场景中,都应该开启隐藏面消除,并在适当的时刻清空深度缓冲区(通常是在绘制每一帧之前)。不过需要注意的是,隐藏面的消除的前提是正确设置可视空间,否则则肯产生错误,不管是盒装的正射投影空间,还是金字塔状的透视投影空间,必须使用一个。
9、gl.drawElements()会索引到存在的每个buffer,比如创建的顶点buffer和颜色buffer。都会索引到,然后提取里面的值。
10、光照使得场景更具有层次感
// Create a cube
// v6----- v5
// /| /|
// v1------v0|
// | | | |
// | |v7---|-|v4
// |/ |/
// v2------v3
' vec4 vertexPosition = u_ModelMatrix * a_Position;\n' +
// Calculate the light direction and make it 1.0 in length
' vec3 lightDirection = normalize(u_LightPosition - vec3(vertexPosition));\n' +
11、光照的逻辑处理在顶点着色器和片元着色器中存在区别:将顶点着色器中的逻辑全部移动到片元着色器中,对于varying变量仍然只需要 color这一个,其余仍然保持为与着色器无关的 uniform 变量。在顶点着色器中算好 中的三个变量: (顶点) + (基底色)+ (法向量) 在变换之后的新信息即可,然后传入到片元着色器中。
' gl_Position = u_MvpMatrix * a_Position;\n' +
// Calculate the vertex position in the world coordinate
' v_Position = vec3(u_ModelMatrix * a_Position);\n' +
' v_Normal = normalize(vec3(u_NormalMatrix * a_Normal));\n' +
' v_Color = a_Color;\n'
'uniform vec3 u_LightColor;\n' + // Light color
'uniform vec3 u_LightPosition;\n' + // Position of the light source
'uniform vec3 u_AmbientLight;\n' + // Ambient light color
后面三个变量直接命名在片元着色器中了。
具体参考笔记 顶点处理 VS 片元处理
坐标变换
无论用DirectX还是OpenGL,最终都需要将三维的情报向二维进行变换。就像刚开始说的那样,最终的图像都是由二维显示器来显示的。这时候,坐标变换就是必须的了。坐标变换大致可以分为三种,将这些正确的组合在一起,最终决定显示器上的位置。用身边的东西举例说明的话,三维向二维转换的例子就是照相机。照片和图像,通过照相机已经全部变为了二维,最终,输出成了照片和动画。
模型变换
三种坐标变换中的第一个,是模型变换。在OpenGL的处理中虽然一般叫做模型变换,但是在DirectX中被叫做世界变换。模型变换,是指为了定义参照物在三维空间的什么位置而进行的坐标变换。和现实的世界不同,程序中的三维空间里定义了世界的中心的基准点,就是原点。从这个原点出发,为了知道参照物的相对位置,就需要进行必要的坐标变换。假设,虚拟的三维空间里有一个苹果,那么为了表示这个苹果在什么位置,就需要进行相应的模型变换了。
视图变换
三种坐标变换的第二个,是视图变换。视图变换,定义了镜头的实际位置以及镜头的方向。拿刚刚举例的苹果来说,即使三维空间中有一个苹果,如果镜头的方向不对着苹果的话,同样也是看不到这个苹果的。而且,如果将镜头大幅度远离苹果,那么也有可能看不到苹果了。为了决定镜头的位置和角度所进行的坐标变换就叫做视图变换。
投影变换
三种坐标变换中的最后一个,是投影变换。这个变换,定义了三维空间的摄影区域。比如,是横向摄影,还是纵向摄影,最远拍摄多远距离等。一般的照相机,直接拍摄镜头前的所有图像,最远拍摄多远也基本上没什么意识。但是,程序是无法模拟无限大的空间的,所以,从哪里开始拍摄,拍摄到哪里,必须有一个明确的范围。投影变幻,通过远近法则,可以将近处的物体描画的比较大,远处的物体描画的比较小。
多边形在内侧还是外侧的判断(通过链接顺序确定向量的朝向可以进行遮挡剔除)
通过顶点的连接顺序为判断基准的。顺时针连接顶点的多边形是在外侧,而逆时针连接的多边形在内侧。所以,在定义顶点情报的时候,要特别注意。如果设定了遮挡剔除,本来应该在某个位置有个多边形,但是根本就不会进行绘制。
var gl = c.getContext('webgl') || c.getContext('experimental-webgl');
GLSL(OpenGL Shading Language)
WebGL是无法利用固定渲染管线的,这个在之前的文章(四,渲染准备)里已经简单的说明过了。所以,代替它的是可编辑渲染管线中的一种着色语言,叫做GLSL(OpenGL Shading Language)。
顶点着色器处理顶点信息,片源着色器处理颜色信息。
修饰符
attribute修饰符
attribute修饰符是用来接收不同顶点传来的不同信息。如果存在很多个顶点的话,这些顶点的位置是不同的吧。用来接收这些不同顶点的不同信息的机制,用attribute修饰符来定义变量。
uniform修饰符
修饰符是uniform。使用uniform修饰符的话,可以传递对于所有顶点一致的处理的信息。
varying修饰符
GLSL里面还有一个特别重要的修饰符,就是varying修饰符。这个varying修饰符,是顶点着色器和片段着色器之间的桥梁。
着色器
顶点着色器和片段着色器,都可以通过GLSL来书写,基本上它们算是一个组合。着色器的内部,必须要定义一个main函数,在这个函数里面添加自己的处理。而且,要从WebGL一侧向着色器传递数据的时候,需要用到一些特殊的修饰符所定义的变量。
顶点缓存
顶点缓存的作用,不光是保存顶点的位置,位置以外跟顶点相关的信息都可以用顶点缓存来保存。
比如,顶点的法线,颜色,文理坐标等所有跟顶点相关的信息都可以用顶点缓存来保存和管理。但是需要注意一点的是,向顶点信息中追加信息的时候,需要使用相应的VBO。
WebGL的程序中,先把顶点的信息保存到VBO中,接着,通知着色器哪个VBO和哪个attribute变量相关,然后顶点着色器就可以正确的处理这些顶点了。
根据前面的内容,顶点缓存相关的处理的具体流程如下:
・顶点的各种信息保存到数组里
・使用WebGL的方法生成VBO
・使用WebGL的方法将数组中的信息传给VBO
・顶点着色器中的attribute函数和VBO结合