# 二维旋转

我承认我不知道怎么解释比较好,但是管它呢!先试试吧。

首先我想向你介绍一个叫做“单位圆”的东西。如果你还记得初中数学的话(别睡着了啊~喂!), 一个圆有一个半径,圆的半径是圆心到圆边缘的距离。单位圆是半径为 1.0 的圆。

这里有个单位圆。

当你拖拽蓝色圆点的时候 X 和 Y 会改变,它们是那一点在圆上的坐标, 在最上方时 Y 是 1 并且 X 是 0 ,在最右边的时候 X 是 1 并且 Y 是 0 。

我们将从单位元上任取一点,并将该点的 X 和 Y 与之前例子 中的几何体相乘





 




 
 











attribute vec2 a_position;

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

void main() {
  // 旋转位置
  vec2 rotatedPosition = vec2(
     a_position.x * u_rotation.y + a_position.y * u_rotation.x,
     a_position.y * u_rotation.y - a_position.x * u_rotation.x);
  // 加上平移
  vec2 position = rotatedPosition + u_translation;
  // convert the position from pixels to 0.0 to 1.0
  vec2 zeroToOne = position / u_resolution;
  // convert from 0->1 to 0->2
  vec2 zeroToTwo = zeroToOne * 2.0;
  // convert from 0->2 to -1->+1 (clipspace)
  vec2 clipSpace = zeroToTwo - 1.0;
  gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);
}
// ...
const rotationLocation = gl.getUniformLocation(program, "u_rotation");
// ...
// 设置旋转
const rotation = [0, 1];

const setRotation = () => {
  gl.uniform2fv(rotationLocation, rotation);
}

# 渲染结果1

为什么会这样?来看看数学公式。


sin(α+β)=sin(α)cos(β)+cos(α)sin(β)sin(\alpha + \beta) = sin(\alpha)cos(\beta) + cos(\alpha)sin(\beta)

cos(α+β)=cos(α)cos(β)sin(α)sin(β)cos(\alpha + \beta) = cos(\alpha)cos(\beta) - sin(\alpha)sin(\beta)


本来是 Y 对应 sinX 对应 cos ,由于我们数学中 x 方向和 y 方向的顺序和 WebGL 中相反, (WebGLyx 的顺时针方向)所以需要反过来, rotatedX 对应 sinrotateY 对应 cos ,于是有了下面的计算公式。

rotatedX = a_position.x * u_rotation.y + a_position.y * u_rotation.x;
rotatedY = a_position.y * u_rotation.y - a_position.x * u_rotation.x;

此外,对于任意给定角,我们只需要求出正弦和余弦,像这样

function printSineAndCosineForAnAngle(angleInDegrees) {
  const angleInRadians = angleInDegrees * Math.PI / 180;
  const sin = Math.sin(angleInRadians);
  const cos = Math.cos(angleInRadians);
}

如果你把这些组合起来,就可以对几何体旋转任意角度,使用时只需要设置旋转的角度。

# 渲染结果2