# WebGLFundamentals.org

Fix, Fork, Contribute

# WebGL 二维矩阵

 1 2 3 4 5 6 7 8 9

 newX = x * 1 + newY = x * 2 + extra = x * 3 + y * 4 + y * 5 + y * 6 + 1 * 7 1 * 8 1 * 9

 1.0 0.0 0 0.0 1.0 0 tx ty 1

 newX = x * 1.0 + newY = x * 0.0 + extra = x * 0 + y * 0.0 + y * 1.0 + y * 0 + 1 * tx 1 * ty 1 * 1

 newX = x * 1.0 + newY = x * 0.0 + extra = x * 0 + y * 0.0 + y * 1.0 + y * 0 + 1 * tx 1 * ty 1 * 1

newX = x + tx;
newY = y + ty;

 c -s 0 s c 0 0.0 0.0 1

 newX = x * c + newY = x * -s + extra = x * 0 + y * s + y * c + y * 0 + 1 * 0.0 1 * 0.0 1 * 1

 newX = x * c + newY = x * -s + extra = x * 0 + y * s + y * c + y * 0 + 1 * 0.0 1 * 0.0 1 * 1

newX = x *  c + y * s;
newY = x * -s + y * c;

 sx 0.0 0 0.0 sy 0 0.0 0.0 1

 newX = x * sx + newY = x * 0.0 + extra = x * 0 + y * 0.0 + y * sy + y * 0 + 1 * 0.0 1 * 0.0 1 * 1

 newX = x * sx + newY = x * 0.0 + extra = x * 0 + y * 0.0 + y * sy + y * 0 + 1 * 0.0 1 * 0.0 1 * 1

newX = x * sx;
newY = y * sy;

var m3 = {
translation: function(tx, ty) {
return [
1, 0, 0,
0, 1, 0,
tx, ty, 1,
];
},

return [
c,-s, 0,
s, c, 0,
0, 0, 1,
];
},

scaling: function(sx, sy) {
return [
sx, 0, 0,
0, sy, 0,
0, 0, 1,
];
},
};

attribute vec2 a_position;

uniform vec2 u_resolution;
uniform vec2 u_translation;
uniform vec2 u_rotation;
uniform vec2 u_scale;

void main() {
// 缩放
vec2 scaledPosition = a_position * u_scale;

// 旋转
vec2 rotatedPosition = vec2(
scaledPosition.x * u_rotation.y + scaledPosition.y * u_rotation.x,
scaledPosition.y * u_rotation.y - scaledPosition.x * u_rotation.x);

// 平移
vec2 position = rotatedPosition + u_translation;
...

attribute vec2 a_position;

uniform vec2 u_resolution;
uniform mat3 u_matrix;

void main() {
// 将位置乘以矩阵
vec2 position = (u_matrix * vec3(a_position, 1)).xy;
...

// 绘制场景
function drawScene() {

,,,

// 计算矩阵
var translationMatrix = m3.translation(translation[0], translation[1]);
var scaleMatrix = m3.scaling(scale[0], scale[1]);

// 矩阵相乘
var matrix = m3.multiply(translationMatrix, rotationMatrix);
matrix = m3.multiply(matrix, scaleMatrix);

// 设置矩阵
gl.uniformMatrix3fv(matrixLocation, false, matrix);

// 绘制图形
gl.drawArrays(gl.TRIANGLES, 0, 18);
}

...
// 矩阵相乘
var matrix = m3.multiply(scaleMatrix, rotationMatrix);
matrix = m3.multiply(matrix, translationMatrix);
...

// 绘制场景
function drawScene() {
// 清空画布
gl.clear(gl.COLOR_BUFFER_BIT);

// 计算矩阵
var translationMatrix = m3.translation(translation[0], translation[1]);
var scaleMatrix = m3.scaling(scale[0], scale[1]);

// 初始矩阵
var matrix = m3.identity();

for (var i = 0; i < 5; ++i) {
// 矩阵相乘
matrix = m3.multiply(matrix, translationMatrix);
matrix = m3.multiply(matrix, rotationMatrix);
matrix = m3.multiply(matrix, scaleMatrix);

// 设置矩阵
gl.uniformMatrix3fv(matrixLocation, false, matrix);

// 绘制图形
gl.drawArrays(gl.TRIANGLES, 0, 18);
}
}

X * 1 = X

matrixX * identity = matrixX

var m3 = {
identity: function() {
return [
1, 0, 0,
0, 1, 0,
0, 0, 1,
];
},

...

// 创建一个矩阵，可以将原点移动到 'F' 的中心
var moveOriginMatrix = m3.translation(-50, -75);
...

// 矩阵相乘
var matrix = m3.multiply(translationMatrix, rotationMatrix);
matrix = m3.multiply(matrix, scaleMatrix);
matrix = m3.multiply(matrix, moveOriginMatrix);

...
// 从像素坐标转换到 0.0 到 1.0
vec2 zeroToOne = position / u_resolution;

// 再把 0->1 转换 0->2
vec2 zeroToTwo = zeroToOne * 2.0;

// 把 0->2 转换到 -1->+1 (裁剪空间)
vec2 clipSpace = zeroToTwo - 1.0;

gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);

var m3 = {
projection: function(width, height) {
// 注意：这个矩阵翻转了 Y 轴，所以 0 在上方
return [
2 / width, 0, 0,
0, -2 / height, 0,
-1, 1, 1
];
},

...

attribute vec2 a_position;

uniform mat3 u_matrix;

void main() {
// 使位置和矩阵相乘
gl_Position = vec4((u_matrix * vec3(a_position, 1)).xy, 0, 1);
}
</script>

// 绘制场景
function drawScene() {
...

// 计算矩阵
var projectionMatrix = m3.projection(
gl.canvas.clientWidth, gl.canvas.clientHeight);

...

// 矩阵相乘
var matrix = m3.multiply(projectionMatrix, translationMatrix);
matrix = m3.multiply(matrix, rotationMatrix);
matrix = m3.multiply(matrix, scaleMatrix);

...
}

var m3 = {

...

translate: function(m, tx, ty) {
return m3.multiply(m, m3.translation(tx, ty));
},

},

scale: function(m, sx, sy) {
return m3.multiply(m, m3.scaling(sx, sy));
},

...

};

// 计算矩阵
var matrix = m3.projection(gl.canvas.clientWidth, gl.canvas.clientHeight);
matrix = m3.translate(matrix, translation[0], translation[1]);
matrix = m3.scale(matrix, scale[0], scale[1]);

translation * rotation * scale // 平移 * 旋转 * 缩放

scale * rotation * translation // 缩放 * 旋转 * 平移

projectionMat * translationMat * rotationMat * scaleMat * position

scaledPosition = scaleMat * position

rotatedScaledPosition = rotationMat * scaledPosition

translatedRotatedScaledPosition = translationMat * rotatedScaledPosition

clipspacePosition = projectioMatrix * translatedRotatedScaledPosition

from clip space to pixel space

move origin to tx, ty

rotate 33 degrees

### clientWidth 和 clientHeight是什么？

<canvas width="400" height="300"></canvas>

var canvas = document.createElement("canvas");
canvas.width = 400;
canvas.height = 300;

<style>
canvas {
width: 100vw;
height: 100vh;
}
</style>
...
<canvas width="400" height="300"></canvas>

• 基础概念
• 图像处理
• 二维平移，旋转，缩放和矩阵运算
• 三维
• 光照
• 组织和重构
• 几何
• 纹理
• 渲染到纹理
• 阴影
• 技术
• 建议
• 优化
• 杂项
• 参考

Issue/Bug? 在GitHub上提issue.