4. UI渲染数学基础

在 OpenGL ES 的 UI 渲染中,我们最终看到的每一个按钮、文字、图标,本质上都是二维平面上的几何图元。但 GPU 并不直接理解“左上角坐标”或“像素位置”,它处理的是一套统一的数学管线:顶点先经过模型变换、视图变换、投影变换,再经过透视除法与视口变换,最终落到屏幕像素空间。理解这条数学链路,是写出稳定、可复用 UI 渲染器的前提。

一、向量与矩阵:UI 几何的两种基本语言

向量描述“位置”和“方向”。在 UI 中,一个矩形顶点可以表示为 (x, y, z, w),其中 w 是齐次分量。矩阵则描述“变换”,例如平移、缩放、旋转。OpenGL ES 使用列主序矩阵,顶点通常写成列向量,变换写作 M * v。这意味着多个变换叠加时,矩阵乘法顺序与直觉相反:先缩放、再旋转、最后平移,应写成 T * R * S * v。

UI 渲染中最常用的矩阵是 4×4 矩阵。虽然 UI 大多是二维的,但保留 4×4 形式可以统一处理平移、旋转、透视和深度。下面是一个典型的正交投影矩阵构造片段:

// 列主序,正交投影:left, right, bottom, top, near, far
float ortho[16] = {
    2.0f/(right-left), 0, 0, 0,
    0, 2.0f/(top-bottom), 0, 0,
    0, 0, -2.0f/(far-near), 0,
    -(right+left)/(right-left),
    -(top+bottom)/(top-bottom),
    -(far+near)/(far-near), 1.0f
};

二、齐次坐标:让平移也能用矩阵表达

三维矩阵无法直接表示平移,因为平移不是线性变换。齐次坐标通过增加一个维度 w 解决这个问题:把三维点 (x, y, z) 写成 (x, y, z, 1),把方向向量写成 (x, y, z, 0)。这样平移矩阵的最后一列就可以携带位移量,而方向向量不会被平移影响。

在 UI 渲染中,齐次坐标还有一个关键作用:透视除法。顶点经过投影矩阵后得到裁剪空间坐标 (x, y, z, w),GPU 会自动执行 (x/w, y/w, z/w),把坐标映射到 NDC(标准化设备坐标)。对于正交投影,w 通常保持为 1,因此不会产生近大远小的效果,这正是 2D UI 所需要的。

核心结论:UI 渲染通常使用正交投影,因为 UI 元素不应随距离缩放。正交投影矩阵把视口范围映射到 NDC 的 [-1, 1] 区间,再由视口变换映射到实际像素。

三、模型视图变换与屏幕空间映射

一个 UI 顶点的完整旅程可以概括为:局部坐标 → 模型矩阵 → 世界坐标 → 视图矩阵 → 相机坐标 → 投影矩阵 → 裁剪坐标 → 透视除法 → NDC → 视口变换 → 屏幕像素。对于 2D UI,视图矩阵通常设为单位矩阵,模型矩阵负责元素自身的位置、旋转和缩放,投影矩阵负责把设计稿坐标映射到屏幕。

假设设计稿宽度为 750,屏幕宽度为 1080,我们希望 UI 等比缩放并居中。可以构造正交投影:left=0, right=750, bottom=0, top=1334,再通过视口变换把 NDC 映射到实际屏幕。这样所有 UI 元素都可以用设计稿坐标书写,渲染器自动完成适配。

UI 顶点从局部坐标到屏幕像素的数学管线 局部坐标 (x, y, 0, 1) 模型矩阵 M 平移 / 旋转 / 缩放 视图矩阵 V 2D UI 常设单位阵 投影矩阵 P 正交投影 裁剪空间 (x, y, z, w) 透视除法 (x/w, y/w, z/w) NDC [-1, 1] 视口变换 屏幕像素 UI 渲染关键:正交投影使 w 保持为 1,避免近大远小;模型矩阵负责元素布局,视口变换负责适配不同分辨率。 设计稿坐标 → 正交投影 → NDC → 屏幕像素

四、案例:设计稿坐标到屏幕像素的完整映射

假设设计稿为 750×1334,目标屏幕为 1080×1920。我们希望在屏幕中保持等比缩放并居中。步骤如下:

  1. 设置正交投影:left=0, right=750, bottom=1334, top=0,注意 Y 轴翻转,使原点在左上角。
  2. 设置视口:glViewport(offsetX, offsetY, viewW, viewH),其中 viewW = 1080,viewH = 1080 * 1334 / 750 ≈ 1921,略大于屏幕高度,可微调。
  3. 每个 UI 元素使用设计稿坐标构建顶点,模型矩阵只做元素自身的旋转和缩放。
  4. 顶点着色器执行 gl_Position = P * M * vec4(aPos, 1.0)。

这样,无论屏幕分辨率如何变化,UI 都能保持设计稿比例。若需要适配刘海屏或安全区,只需调整视口偏移和投影范围。

五、常见误区与复盘

误区 现象 修正方法
矩阵乘法顺序写反 元素位置偏移、旋转中心错误 牢记列主序:先缩放,再旋转,最后平移,写作 T * R * S
Y 轴方向未翻转 UI 上下颠倒 正交投影中设置 bottom 大于 top,或模型矩阵中做 Y 翻转
误用透视投影 UI 元素近大远小,边缘变形 2D UI 统一使用正交投影,w 保持为 1
忽略视口偏移 画面被拉伸或黑边 根据屏幕宽高比计算视口,保持等比缩放
齐次坐标 w 未归一化 顶点位置异常 确保投影后由 GPU 自动执行透视除法,或手动检查 w 分量

实践建议:在 UI 渲染器中,把投影矩阵和视口计算封装成独立的 OrthoCamera 类,对外只暴露设计稿宽高和屏幕宽高。这样业务层只关心“元素放在设计稿的哪个位置”,数学细节全部由渲染器内部处理,能显著降低出错概率。

掌握向量、矩阵、齐次坐标、正交投影与屏幕空间映射之后,你就拥有了 UI 渲染的“坐标系思维”。后续无论是实现滚动列表、旋转动画,还是处理多分辨率适配,都可以在这条数学管线上找到对应的变换环节。