title: WebGL 基础概念学习摘要(上) layout: post thread: 213 date: 2019-02-01 author: Joe Jiang categories: Document tags: [2019, WebGL, GLSL, 可视化] excerpt: 翻阅 WebGL Fundamentals 时碎碎记录下 WebGL 基础概念一些细节。
WebGL 实质上是一个光栅化引擎,根据你的代码绘制出点,线和三角形。
WebGL 每次绘制需要两个着色器, 一个顶点着色器和一个片断着色器,每一个着色器都是一个方法。 一个顶点着色器和一个片断着色器链接在一起放入一个着色程序中(或者只叫程序)。一个典型的 WebGL 应用会有多个着色程序。
// vec2, vec3和 vec4分别代表两个值,三个值和四个值
vec4 a = vec4(1, 2, 3, 4);
vec4 b = a * 2.0;
// b 现在是 vec4(2, 4, 6, 8);
// mat2, mat3 和 mat4 分别代表 2x2, 3x3 和 4x4 矩阵
mat4 a = ???
mat4 b = ???
mat4 c = a * b;
vec4 v;
// v.x 和 v.s 以及 v.r , v[0] 表达的是同一个分量。
// v.y 和 v.t 以及 v.g , v[1] 表达的是同一个分量。
// v.z 和 v.p 以及 v.b , v[2] 表达的是同一个分量。
// v.w 和 v.q 以及 v.a , v[3] 表达的是同一个分量。
v.yyyy // === vec4(v.y, v.y, v.y, v.y)
v.bgra // === vec4(v.b, v.g, v.r, v.a)
vec4(1) // === vec4(1, 1, 1, 1)
// 支持矢量调制
// 如果 v1 和 v2 都是 vec4, f 是浮点型,以下两个变量等价
vec4 m = mix(v1, v2, f);
vec4 m = vec4(
mix(v1.x, v2.x, f),
mix(v1.y, v2.y, f),
mix(v1.z, v2.z, f),
mix(v1.w, v2.w, f));
对于二维变换使用 3x3 矩阵,可以快速的实现平移,旋转,缩放,单位化效果。
var m3 = {
translation: function(tx, ty) {
return [
1, 0, 0,
0, 1, 0,
tx, ty, 1,
];
},
rotation: function(angleInRadians) {
var c = Math.cos(angleInRadians);
var s = Math.sin(angleInRadians);
return [
c,-s, 0,
s, c, 0,
0, 0, 1,
];
},
scaling: function(sx, sy) {
return [
sx, 0, 0,
0, sy, 0,
0, 0, 1,
];
},
identity: function() {
return [
1, 0, 0,
0, 1, 0,
0, 0, 1,
];
},
};
关于如下一个矩阵计算,有两种解释方式:
projectionMat * translationMat * rotationMat * scaleMat * position
从右向左解释:首先将位置乘以缩放矩阵获得缩放后的位置,然后将缩放后的位置和旋转矩阵相乘得到缩放旋转位置,然后将缩放旋转位置和平移矩阵相乘得到缩放旋转平移位置,最后和投影矩阵相乘得到裁剪空间中的坐标。
从左往右解释:每一个矩阵改变的都是画布的坐标空间, 画布的起始空间是裁剪空间的范围(-1 到 +1),矩阵从左到右改变着画布所在的空间。
gl.enable(gl.CULL_FACE);
gl.enable(gl.DEPTH_TEST);
实现动画与 WebGL 并不直接相关,需要利用 JavaScript 随着时间改变一些值然后绘制。在此处请使用 requestAnimationFrame API.
gl.generateMipmap
做的事情就是根据原始图像创建所有的缩小级别。使用 generateMipmap
时需注意纹理的维度必须是2的整数次幂。由于纹理需要异步加载资源,所以在物体渲染上存在两种处理方式。
一个 WebGL 应用推荐遵循的结构
gl.useProgram
使用需要的程序gl.bindBuffer
, gl.vertexAttribPointer
, gl.enableVertexAttribArray
gl.uniformXXX
gl.activeTexture
和 gl.bindTexture
设置纹理到纹理单元gl.drawArrays
或 gl.drawElements