返回

OpenGL 中投影变换矩阵的反向推导

Android

OpenGL 中投影变换矩阵的反向推导

正交投影和透视投影的作用都是把用户坐标映射到 OpenGL 的可视区域。如果我们能根据二者的变换矩阵来推出最终经过映射的坐标范围恰好是 OpenGL 的可视区域,也就是反向推导出了这两个投影矩阵。OpenGL 的可视区域的坐标范围是一个边长为 2 的立方体。每个维度上的大小是 2,范围是 [-1, 1]。

正交投影矩阵

正交投影矩阵如下:

| 2/w  0   0   0 |
| 0   2/h  0   0 |
| 0   0   2/n  0 |
| 0   0   0   1 |

其中,w、h 和 n 分别是可视区域在 x、y 和 z 轴上的尺寸。

为了反向推导出正交投影矩阵,我们需要将最终映射的坐标范围 [-1, 1] 映射回用户坐标。

对于 x 坐标,映射关系为:

x_user = (x_clip - 0) * w / 2

其中,x_user 是用户坐标,x_clip 是裁剪空间坐标。

同理,对于 y 和 z 坐标,映射关系分别为:

y_user = (y_clip - 0) * h / 2
z_user = (z_clip - 0) * n / 2

将这三个映射关系合并,得到:

| x_user |   | 2/w  0   0   0 | | x_clip |
| y_user | = | 0   2/h  0   0 | | y_clip |
| z_user |   | 0   0   2/n  0 | | z_clip |
| 1     |   | 0   0   0   1 | | 1     |

整理得到正交投影矩阵:

| 2/w  0   0   0 |
| 0   2/h  0   0 |
| 0   0   2/n  0 |
| 0   0   0   1 |

透视投影矩阵

透视投影矩阵如下:

| 2n/w  0   0   0 |
| 0   2n/h  0   0 |
| 0   0   (n+f)/(n-f)   -2nf/(n-f) |
| 0   0   1   0 |

其中,w、h、n 和 f 分别是可视区域在 x、y 和 z 轴上的尺寸,以及近平面和远平面的距离。

为了反向推导出透视投影矩阵,我们需要将最终映射的坐标范围 [-1, 1] 映射回用户坐标。

对于 x 坐标,映射关系为:

x_user = (x_clip - 0) * w / (2n)

其中,x_user 是用户坐标,x_clip 是裁剪空间坐标。

同理,对于 y 和 z 坐标,映射关系分别为:

y_user = (y_clip - 0) * h / (2n)
z_user = (z_clip - -nf/(n-f)) * (n-f) / (2nf)

将这三个映射关系合并,得到:

| x_user |   | 2n/w  0   0   0 | | x_clip |
| y_user | = | 0   2n/h  0   0 | | y_clip |
| z_user |   | 0   0   (n+f)/(n-f)   -2nf/(n-f) | | z_clip |
| 1     |   | 0   0   1   0 | | 1     |

整理得到透视投影矩阵:

| 2n/w  0   0   0 |
| 0   2n/h  0   0 |
| 0   0   (n+f)/(n-f)   -2nf/(n-f) |
| 0   0   1   0 |

结论

通过反向推导,我们得到了正交投影矩阵和透视投影矩阵。这些矩阵可以用来将用户坐标映射到 OpenGL 的可视区域,从而实现 3D 场景的渲染。