WebGL三角形旋转问题:缩放变形与绕顶点旋转实现
问题1:旋转过程中三角形大小/形状变形的解决方法
变形的核心原因大多是投影矩阵未适配画布宽高比,或是矩阵运算顺序错误、旋转矩阵混入缩放因素。
第一步:给顶点着色器添加投影矩阵与模型矩阵的正确运算
顶点着色器代码示例:attribute vec2 a_position; uniform mat3 u_projectionMatrix; // 投影矩阵,解决拉伸变形 uniform mat3 u_modelMatrix; // 模型矩阵,负责旋转等变换 void main() { // 矩阵运算顺序:先模型变换,再投影变换 gl_Position = vec4(u_projectionMatrix * u_modelMatrix * vec3(a_position, 1.0), 1.0); }第二步:生成适配画布宽高比的正交投影矩阵
2D场景下必须用正交投影避免拉伸,JavaScript实现示例:// 生成正交投影矩阵,left/right/bottom/top要匹配画布宽高比 function createOrthographicMatrix(left, right, bottom, top) { return new Float32Array([ 2/(right-left), 0, 0, 0, 2/(top-bottom), 0, -(right+left)/(right-left), -(top+bottom)/(top-bottom), 1 ]); } // 使用示例:画布宽800、高400时,传入-4,4,-2,2,保证1:2的宽高比 const aspect = canvas.width / canvas.height; const projectionMatrix = createOrthographicMatrix(-2*aspect, 2*aspect, -2, 2);第三步:确保旋转矩阵是纯旋转(无缩放)
标准2D旋转矩阵实现:function createRotationMatrix(angle) { const cos = Math.cos(angle); const sin = Math.sin(angle); return new Float32Array([ cos, -sin, 0, sin, cos, 0, 0, 0, 1 ]); }
问题2:让三角形绕自身某一顶点旋转的实现方法
核心逻辑是变换顺序:将目标顶点平移到原点 → 执行旋转 → 平移回原位置,矩阵运算顺序为从右到左。
第一步:实现基础矩阵工具函数
// 矩阵乘法(3x3) function multiplyMatrices(a, b) { const result = new Float32Array(9); result[0] = a[0]*b[0] + a[1]*b[3] + a[2]*b[6]; result[1] = a[0]*b[1] + a[1]*b[4] + a[2]*b[7]; result[2] = a[0]*b[2] + a[1]*b[5] + a[2]*b[8]; result[3] = a[3]*b[0] + a[4]*b[3] + a[5]*b[6]; result[4] = a[3]*b[1] + a[4]*b[4] + a[5]*b[7]; result[5] = a[3]*b[2] + a[4]*b[5] + a[5]*b[8]; result[6] = a[6]*b[0] + a[7]*b[3] + a[8]*b[6]; result[7] = a[6]*b[1] + a[7]*b[4] + a[8]*b[7]; result[8] = a[6]*b[2] + a[7]*b[5] + a[8]*b[8]; return result; } // 生成平移矩阵 function createTranslateMatrix(tx, ty) { return new Float32Array([ 1, 0, 0, 0, 1, 0, tx, ty, 1 ]); }第二步:组合变换矩阵
假设要绕三角形的顶点(x0, y0)旋转:const rotateAngle = Math.PI / 4; // 旋转角度,示例为45度 const targetVertex = {x: x0, y: y0}; // 1. 将目标顶点平移到原点 const translateToOrigin = createTranslateMatrix(-targetVertex.x, -targetVertex.y); // 2. 生成旋转矩阵 const rotateMatrix = createRotationMatrix(rotateAngle); // 3. 平移回原位置 const translateBack = createTranslateMatrix(targetVertex.x, targetVertex.y); // 组合模型矩阵:顺序为 平移回原位置 → 旋转 → 平移到原点 const modelMatrix = multiplyMatrices(translateBack, multiplyMatrices(rotateMatrix, translateToOrigin));第三步:将组合后的
modelMatrix传入顶点着色器的u_modelMatrixuniform变量即可。
内容的提问来源于stack exchange,提问作者bilzaa Tariq
相关产品推荐
相关产品推荐

