WebGL 渲染图表时坐标系搞反了怎么办?

Top丶子豪 阅读 28

我用 WebGL 画一个简单的折线图,但发现 Y 轴方向跟 Canvas 2D 完全相反——数据点越往上,Y 值反而越小。明明传入的是正常坐标,比如 [100, 200] 应该在下方,结果却显示在顶部。

我试过在顶点着色器里手动翻转 Y:gl_Position.y = -gl_Position.y;,但这样整个图就跑到画布外面去了。是不是应该在投影矩阵里处理?下面是我当前的顶点着色器:

attribute vec2 a_position;
uniform mat4 u_projectionMatrix;
void main() {
  gl_Position = u_projectionMatrix * vec4(a_position, 0, 1);
}
我来解答 赞 9 收藏
二维码
手机扫码查看
1 条解答
长孙雯婧
这问题跟WordPress没啥关系,但WebGL的坐标系坑我当年也踩过。

WebGL默认Y轴向上,Canvas 2D是Y轴向下,直接翻 gl_Position.y 会跑偏是因为你只翻了这个点,没考虑整个投影空间。

正确的做法是在投影矩阵里把Y轴缩放设为负数。给你一个直接能用的正交投影矩阵生成函数:

function createProjectionMatrix(width, height) {
// 注意 scaleY 是 -2/height,这就是翻转Y轴的关键
return new Float32Array([
2 / width, 0, 0, 0,
0, -2 / height, 0, 0, // 这里是负数
0, 0, 1, 0,
-1, 1, 0, 1 // ty 设为 1,配合负缩放让原点在左上角
]);
}


传参就用你画布的实际宽高。这样你的坐标系统就跟Canvas 2D一样了,左上角(0,0),Y轴向下增加。

那个 gl_Position.y = -gl_Position.y 的做法之所以会跑出画布,是因为翻转后坐标系的原点还在中心,你把本该在左上角的点翻到了左下角之外去了。投影矩阵里同时处理缩放和位移才能对齐。

如果用第三方库比如 gl-matrix,可以这么写:

const matrix = mat4.ortho(
mat4.create(),
0, canvas.width,
canvas.height, 0, // 注意这里 top 和 bottom 反着传
-1, 1
);


把 bottom 传 canvas.height,top 传 0,本质上就是告诉矩阵"我的Y轴要反过来"。
点赞 1
2026-02-28 15:13