本文笔记摘自于 :https://learnopengl-cn.github.io/01%20Getting%20started/08%20Coordinate%20Systems/
绘制正方形和圆形
1. 为什么需要将坐标复制进缓冲区(Buffer)里面
因为 Java 代码是运行在虚拟机中的,会有垃圾回收功能,所以,需要将坐标参照缓冲区里面。
2. 投影,相机位置, 变换矩阵
(1).变换矩阵
因为 OpenGL 中的坐标是[-1, 1],所以需要将坐标变换成 OpengGL 的坐标。
The projection matrix recalculates the coordinates of your graphics so that they map correctly to Android device screens.
The camera view matrix creates a transformation that renders objects from a specific eye position.
在 OpenGL 中,要将坐标变换为标准化设备坐标,既每个坐标顶点的 x, y, z 坐标都在[-1, 1] 之间,这个过程需要几个坐标系统。
. 局部空间(Local Space) 或者成为物体空间(Object Space)
. 世界空间(World Space)
. 观察空间 (View Space) 或者成为视觉空间 (Eye Space)
. 裁剪空间 (Clip Space)
. 屏幕空间 (Screen Space)
- 局部坐标是对象相对于局部原点的坐标,也是物体起始的坐标;
- 下一步是将局部坐标变换为世界空间坐标,这些坐标相对于世界的全局原点,它们会和其他物体一起相对于世界原点进行摆放;
- 接下来是将世界坐标变换为观察空间坐标,使得每个坐标都是从摄像机或者说观察者的角度进行观察的;
- 在观察空间之后,将其投影到裁剪坐标。裁剪坐标会被处理至[-1, 1] 的范围内,并判断哪些顶点将会出现在屏幕上;
- 通过视口变换(Viewport Transform)的过程,将裁剪坐标变换为屏幕坐标。视口变换将位于 [-1, 1] 范围的坐标变换到由 glViewport 函数所定义的坐标范围内。将最终的坐标传入光栅器,使其转变为片段。
局部空间 (Local Space)
局部空间是指物体所在坐标空间,即对象最开始所在的地方,模型的所有点都是在局部空间中。
世界空间 (World Space)
当把物体放入到游戏世界空间中,那么物体的坐标将会从局部坐标变换为世界坐标,这个变换是由 Model Matrix 实现的。
观察空间 (View Space)
观察空间也被称为 Opengl 的 Camera, 它是从摄像机的视角所得到的空间,将世界空间坐标转化为用户视野前方的坐标而产生的结果。这个过程是将特定的对象,进过一系列的位移,旋转完成才。这个过程由 View Matrix 实现。
裁剪空间 (Clip Space)
OpenGL 期待所有的坐标都落在一个特定的范围之内,范围之外的点都被裁剪掉。将指定范围内的坐标转化为标准化设备坐标的范围[-1, 1], 这个过程由投影矩阵 Projection Matrix 实现。
(2). 投影
投影分为正投影和透视投影
. 正投影
正投影是一个类似立方体的平头截体,是一个裁剪空间,在这个空间之外的顶点都会被裁剪掉。
创建正投影矩阵
1 | glm::orthon(0.0f, 800.0f, 0.0f, 600.0f, 0.1f, 100.0f) |
第一,第二个参数是平头截体的左右坐标;
第三,第四个参数是平头截体的顶部和顶部;
第五,第六个参数是近平面和远平面的距离;
. 透视投影
在透视投影中,顶点坐标的每个分量都会除以它的 w 分量,距离观察者越远顶点坐标就会越小。
创建透视投影坐标:
1 | glm:mat4 proj = glm::perspective(glm::radians(45.0f), (float)width/(float)height, 0.1f, 100.0f) |
fov 值表示视野(Field of View),并设置了观察空间的大小。通常设为 45.0f;
第二个参数是宽高比;
第三、第四个参数是平头截体的近和远平面,通常设置近距离为 0.1f, 远距离设为 100.0f;
坐标组合在一起
模型矩阵,观察矩阵和投影矩阵组合在一起,转变成裁剪坐标:
Vclip = Mprojection Mview Vlocal