- 其实OpenGL的流水线,对我学习来说只能算是一个概念性的东西。毕竟OpenGL也在发展,流水线也不会是一成不变的。
- 不过理解流水线的过程,重点在于理解每一步的作用,进而可以如何衔接起来,完成整个绘制图像的工作。顺序不一定相同,但仍能完成工作,但效率上肯定会有差。
状态机
- 在OpenGL中,我们输入的总是
- “顶点”
- 但同时我们也会改变许多
- “状态”
- 比如
- 当前顶点颜色glColor
- 当前顶点的法向量glNormal
- 当前相机的位置、朝向、正向gluLookAt
- 作用于当前 顶点 的旋转、平移、缩放效果
- ……
- 所以我们叫OpenGL是一个状态机,因为你输入的每一个顶点数据,在那一行代码的时刻就有各种各样的状态对应着这个顶点,而这个顶点也必须经过这些状态的变化后,才是最终你所希望绘制的顶点
流水线的工作过程
- 所以我们有了什么?
- 世界坐标系下的一堆顶点数据
- 每个顶点所对应的各种状态变量
- 其他内容如视景体、视口……
- 想象一下如何生成最后的图像
- 对于顶点,我们需要把各种状态作用在上面,比如你设置的颜色、光照模型下这个顶点应该是什么颜色、进行的旋转等变换、顶点相对于相机的坐标、如果有透视效果会让顶点的坐标发生偏转,,,,,,之后才算一个真正的顶点
- 对于这些点,我们还需要确定这些顶点构成了怎样的图形,OpenGL里成为图元,如这三个顶点的含义是一个三角形,那四个是一个四边形,,,,,,这些信息就需要装配起来,否则顶点只是一个点,组成图形后才有更深的意义
- 对于图元,我们进一步根据你设置的视景体(三维的区域,只有区域内部才会被用来生成图像)来进行裁剪,剩下的图元就是要用来生成图像的,只是这个时候数据都是连续的数学抽象表达,而图像却是离散的像素点
- 所以,我们进一步进行光栅化(也叫扫描转换),确实每一个图元对应了哪些像素。比如一条线段只有两个顶点的数据,两个顶点会至少各占一个像素的位置,但是这条线段要连续,就要让这条线段进一步占用两个顶点之间的像素的位置。于是我们得到了一个个像素的数据,OpenGL里称之为片段或片元
- 但这些像素尚不能作为最终的图像的像素,进一步的片段处理会根据是否有纹理贴图进一步修改像素的颜色、对于三维空间中的物体的遮挡关系根据某种方法只显示在前面的物体、是否需要对锯齿效果进行反走样等等……
- 大概就是这样
细说流水线
其实我也只是学了很少的内容而已,不过作为一个简单的理解入门还是勉强够格的
- 顶点处理
- 坐标
- 齐次坐标表示
- 坐标系
- 世界坐标系
- 相机坐标系
- 裁剪坐标系
- 模型视图矩阵
- 模型变换矩阵
- 旋转矩阵
- 平移矩阵
- 缩放矩阵
- 视图矩阵
- 相机的位置、朝向、正向
- 视图矩阵
- 模型变换矩阵
- 投影矩阵
- 视景体
- 透视投影矩阵
- 正交投影矩阵
- 光照模型
- 光照分析
- 光源类型
- 材质类型
- Phong光照模型
- Blinn-Phong光照模型
- 光照分析
- 坐标
- 裁剪
- 线段裁剪算法
- Cohen-Sutherlend算法
- Sutherland-Hodgeman算法
- 多边形裁剪算法
- Sutherland-Hodgeman算法
- 线段裁剪算法
- 光栅化(扫描转换)
- 线段扫描转换
- DDA 数字微分分析器
- Bresenham算法
- 多边形扫描转换
- 内外点检测算法
- 凸多边形
- 奇偶检测
- 环绕数
- 填充算法
- 种子算法
- 扫描线算法
- 新边表
- 活动边表
- 内外点检测算法
- 线段扫描转换
- 片段处理
- 隐藏面消除
- 对象空间算法
- 画家算法
- 深度排序
- 简单
- 复杂
- 背向面剔除(多边形拣选)
- 图像空间算法
- 深度缓存ZBuffer
- 隐藏面消除