上节说到了不同的图元的装配方式,本节主要通过绘制金字塔,圆环,并使用透视投影
,和矩阵变换
来控制图形的显示
基础知识
OpenGL涉及到的基础变换主要有下面4种
变换 | 说明 |
---|---|
视图变换 | 移动观察者的位置,观察者动,物体不动 |
模型变换 | 在场景中移动物体,观察者不动,物体动 |
投影变换 | 正投影,透视投影 |
视口变换 | 对窗口上最终输出进行缩放 |
其中对于同一个物体,使用视图变换
和模型变换
都能做到同样的效果,具体采用什么变换取决于实际情况
视图变换
视图变换是应用到场景中的第一种变换,通过物体/观察者在Z轴上的移动(默认是Z轴,也可以改为其他轴),确定场景中利于观察的位置。默认情况下,透视投影中的观察者位置处于原点(0,0,0),并沿着z轴负方向看向屏幕里面,一般通过moveForward
方法来调整观察者位置,moveForward默认的朝向是-z轴,所以向屏幕里面移动传正数值,向屏幕外即+z轴,需要传负数值
1 | // 定义一个参考证 |
模型变换
模型变换,主要涉及三个函数,移动、旋转、缩放。有了这三个函数的组合,我们可以进行任意变换。
1 | // 平移,沿x/y/z三个方向平移,矩阵结果放在第一个参数里面 |
翻转操作可以用旋转,也可以用缩放(缩放到-1)
投影变换
通常也在窗口改变的时候设置
1 | GLFrustum viewFrustum; |
视口变换
视口变换相关函数为,通常在窗口大小改变的时候修改
1 | // 修改glView视口 |
这里需要注意的是,矩阵变换叉乘不满足交换律,变换顺序会导致结果不一致
绘制
定义7个批次类,用于保存顶点
1 | GLBatch pointBatch; |
在setupRC
初始化顶点数据
1 | // 定义三个点 |
然后在renderSence里面,把对应的批次类draw出来就可以了
1 | // 画点 |
矩阵堆栈
本案例涉及到3个矩阵,视图矩阵
(修改观察者位置),模型矩阵
(旋转),投影矩阵
(透视投影)
这里我们定义两个矩阵堆栈,来计算
1 | // 矩阵堆栈,用于设置投影矩阵 |
为了方便计算,我们定义一个变换管道
transformPipeline,用于合并2个矩阵堆栈(投影矩阵堆栈projectionMatrix和模型视图矩阵堆栈modelViewMatrix)
1 | // 几何变换的管道 |
对于投影矩阵,直接在changeSize
的时候配置就可以
1 | // 透视投影 |
接下来我们在renderSence
配置模型视图矩阵
1 | // 加载一个单元矩阵到栈顶 |
最终通过变换管道,生成矩阵传递给着色器
1 | // 生成最终的矩阵 |
对于几何图形除了直接填充颜色,还需要绘制边框(glPolygonMode
)
1 | // 开启多边形偏移 |
关于矩阵堆栈的操作
矩阵堆栈API | 说明 |
---|---|
GLMatrixStack::LoadIdentity(void) | 在栈顶加载/覆盖一个单元矩阵 |
GLMatrixStack::LoadMatrix(const M3DMatrix44f m) | 在栈顶加载/覆盖成矩阵m |
GLMatrixStack::MultMatrix(const M3DMatrix44f m) | 矩阵m与栈顶矩阵叉乘,结果覆盖栈顶矩阵 |
GLMatrixStack::GetMatrix(void) | 获取栈顶矩阵 |
GLMatrixStack::PushMatrix(void) | 拷贝栈顶矩阵入栈 |
GLMatrixStack::PushMatrix(const M3DMatrix44f m) | 把矩阵m入栈 |
GLMatrixStack::PopMatrix(void) | 出栈,移出栈顶矩阵 |
完整代码在这里