# WebGLFundamentals.org

Fix, Fork, Contribute

# WebGL 实现二维矩阵栈

``````function MatrixStack() {
this.stack = [];

// 因为栈是空的，需要放入一个初始化矩阵
this.restore();
}

// 抛出顶部的矩阵，重置为前一个矩阵
MatrixStack.prototype.restore = function() {
this.stack.pop();
// 永远不要让栈为空
if (this.stack.length < 1) {
this.stack[0] = m4.identity();
}
};

// 讲当前矩阵备份到栈中
MatrixStack.prototype.save = function() {
this.stack.push(this.getCurrentMatrix());
};
``````

``````// 获取当前矩阵（栈顶的矩阵）
MatrixStack.prototype.getCurrentMatrix = function() {
return this.stack[this.stack.length - 1].slice();
};

// 设置当前矩阵
MatrixStack.prototype.setCurrentMatrix = function(m) {
return this.stack[this.stack.length - 1] = m;
};
``````

``````// 平移当前矩阵
MatrixStack.prototype.translate = function(x, y, z) {
var m = this.getCurrentMatrix();
this.setCurrentMatrix(m4.translate(m, x, y, z));
};

// 旋转当前矩阵
var m = this.getCurrentMatrix();
};

// 缩放当前矩阵
MatrixStack.prototype.scale = function(x, y, z) {
var m = this.getCurrentMatrix();
this.setCurrentMatrix(m4.scale(m, x, y, z));
};
``````

``````// 平移当前矩阵
MatrixStack.prototype.translate = function(x, y, z) {
+  if (z === undefined) {
+    z = 0;
+  }
var m = this.getCurrentMatrix();
this.setCurrentMatrix(m4.translate(m, x, y, z));
};

...

// 缩放当前矩阵
MatrixStack.prototype.scale = function(x, y, z) {
+  if (z === undefined) {
+    z = 1;
+  }
var m = this.getCurrentMatrix();
this.setCurrentMatrix(m4.scale(m, x, y, z));
};
``````
``````// 将坐标从像素空间转换到裁剪空间
var matrix = m4.orthographic(0, gl.canvas.width, gl.canvas.height, 0, -1, 1);

// 将矩形平移到 dstX, dstY
matrix = m4.translate(matrix, dstX, dstY, 0);

// 将单位矩形的宽高缩放到 texWidth, texHeight 个单位
// from 1 unit to texWidth, texHeight units
matrix = m4.scale(matrix, dstWidth, dstHeight, 1);
``````

``````var matrixStack = new MatrixStack();
``````

``````// 将坐标从像素空间转换到裁剪空间
var matrix = m4.orthographic(0, gl.canvas.width, gl.canvas.height, 0, -1, 1);

+// 将原点移动到栈顶矩阵代表的转换
+matrix = m4.multiply(matrix, matrixStack.getCurrentMatrix());

// 将矩形平移到 dstX, dstY
matrix = m4.translate(matrix, dstX, dstY, 0);

// 将单位矩形的宽高缩放到 texWidth, texHeight 个单位
matrix = m4.scale(matrix, dstWidth, dstHeight, 1);
``````

``````var textureInfo = loadImageAndCreateTextureInfo('resources/star.jpg');

function draw(time) {
gl.clear(gl.COLOR_BUFFER_BIT);

matrixStack.save();
matrixStack.translate(gl.canvas.width / 2, gl.canvas.height / 2);
matrixStack.rotateZ(time);

drawImage(
textureInfo.texture,
textureInfo.width,
textureInfo.height,
0, 0);

matrixStack.restore();
}
``````

``````matrixStack.translate(gl.canvas.width / 2, gl.canvas.height / 2);
matrixStack.rotateZ(time);
+matrixStack.translate(textureInfo.width / -2, textureInfo.height / -2);
``````

``````matrixStack.translate(gl.canvas.width / 2, gl.canvas.height / 2);
matrixStack.rotateZ(time);

+matrixStack.save();
+{
+  matrixStack.translate(textureInfo.width / -2, textureInfo.height / -2);
+
+  drawImage(
+    textureInfo.texture,
+    textureInfo.width,
+    textureInfo.height,
+    0, 0);
+
+}
+matrixStack.restore();
+
+matrixStack.save();
+{
+  // 我们在中间图像的中心，所以去左上角
+  matrixStack.translate(textureInfo.width / -2, textureInfo.height / -2);
+  matrixStack.rotateZ(Math.sin(time * 2.2));
+  matrixStack.scale(0.2, 0.2);
+  // 我想让图像的右下角绘制在这里
+  matrixStack.translate(-textureInfo.width, -textureInfo.height);
+
+  drawImage(
+    textureInfo.texture,
+    textureInfo.width,
+    textureInfo.height,
+    0, 0);
+
+}
+matrixStack.restore();
+
+matrixStack.save();
+{
+  // 我们在中间图像的中心，所以去右上角
+  matrixStack.translate(textureInfo.width / 2, textureInfo.height / -2);
+  matrixStack.rotateZ(Math.sin(time * 2.3));
+  matrixStack.scale(0.2, 0.2);
+  // 我想让图像的左下角绘制在这里
+  matrixStack.translate(0, -textureInfo.height);
+
+  drawImage(
+    textureInfo.texture,
+    textureInfo.width,
+    textureInfo.height,
+    0, 0);
+
+}
+matrixStack.restore();
+
+matrixStack.save();
+{
+  // 我们在中间图像的中心，所以去左下角
+  matrixStack.translate(textureInfo.width / -2, textureInfo.height / 2);
+  matrixStack.rotateZ(Math.sin(time * 2.4));
+  matrixStack.scale(0.2, 0.2);
+  // 我想让图像的右上角绘制在这里
+  matrixStack.translate(-textureInfo.width, 0);
+
+  drawImage(
+    textureInfo.texture,
+    textureInfo.width,
+    textureInfo.height,
+    0, 0);
+
+}
+matrixStack.restore();
+
+matrixStack.save();
+{
+  // 我们在中间图像的中心，所以去右下角
+  matrixStack.translate(textureInfo.width / 2, textureInfo.height / 2);
+  matrixStack.rotateZ(Math.sin(time * 2.5));
+  matrixStack.scale(0.2, 0.2);
+  // 我想让图像的左上角绘制在这里
+  matrixStack.translate(0, 0);  // 0,0 表示这行代码其实什么也没做
+
+  drawImage(
+    textureInfo.texture,
+    textureInfo.width,
+    textureInfo.height,
+    0, 0);
+
+}
+matrixStack.restore();
``````

• 基础概念
• 图像处理
• 二维平移，旋转，缩放和矩阵运算
• 三维
• 光照
• 组织和重构
• 几何
• 纹理
• 渲染到纹理