You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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_modelMatrix uniform变量即可。

内容的提问来源于stack exchange,提问作者bilzaa Tariq

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 20:50:54