几何处理阶段
几何阶段主要负责大部分多边形操作和顶点操作,包括顶点着色、坐标变换、生成图元、投影、裁剪、屏幕映射等过程,其中顶点着色、坐标变换由顶点着色器完成
- 顶点着色器
- 生成图元
- 投影
- 裁切
- 屏幕映射
顶点着色器
完成顶点着色、坐标变换
生成图元
索引数组:
{1,2,3}
{3,2,4}
{4,2,7}
{7,2,5}等等…
投影
裁剪
仅保留视景体内部的图元进行渲染
屏幕映射
这个阶段是不可配置也不可编程的。主要用来实现图元的坐标转换到屏幕坐标
三维坐标转变为二维屏幕坐标的过程
- MC : 建模坐标系
- WC : 世界坐标系
- VC : 观察坐标系
- PC : 投影坐标系
- NPC : 规格化投影坐标系
- DC : 设备坐标系
坐标系详细概念
世界坐标系 : 坐标系统主要⽤用于计算机图形场景中的所有图形对象的空间定位和定义
局部坐标系 : 独立于世界坐标系来定义物体几何特性
观察坐标系 : 观察坐标系通常是以视点的位置为原点,通过用户指定的一个向上的观察向量来定义整个坐标系统,观察坐标系主要⽤于从观察者的角度对整个世界坐标系内的对象进行重新定位和描述,从而简化几何物体在投影面的成像的数学推导和计算
投影坐标系 : 物体从世界坐标描述转换到观察坐标后,可将三维物体投影到二维表⾯上,即投影到虚拟摄像机的胶片上,这个过程就是投影变换。以胶片中心为参考原点的空间坐标系称为投影坐标系,物体在投影坐标系中的坐标称为投影坐标。
设备坐标系 : 是图形设备上采用的与具体设备相关的坐标系。设备坐标系⼀般采⽤整数坐标,其坐标范围由具体设备的分辨率决定。设备坐标系上的一个点一般对应图形设备上的一个像素。由于具体设备的限制,设备坐标系的坐标范围一般是有限的
规格化投影坐标系 : 是为了避免设备相关性⽽定义的⼀种虚拟的设备坐标系。规格化坐标系的坐标范围一般从0到1,也有的是从-1到+1。采⽤规格化设备坐标系的好处是屏蔽了具体设备的分辨率,使得图形处理能够尽量避开对具体设备坐标的考虑。实际图形处理时,先将世界坐标转换成对应的规格化设备坐标,然后再将规格化设备坐标映射到具体的设备坐标上去
屏幕坐标系统 : 也称设备坐标系统,它主要用于某一特殊的计算机图形显示设备(如光栅显示器)的表面的点的定义,在多数情况下,对于每⼀个具体的显示设备,都有一个单独的坐标系统,在定义了成像窗口的情况下,可进一步在屏幕坐标系统中定义称为视图区(view port)的有界区域,视图区中的成像即为实际所观察到的。
平移变换
缩放变换
索引绘图
关键代码
1 | -(void)render |
其中关于矩阵变换的操作(旋转/平移/缩放), 需要依赖一个GLES的数学类
GLESMath.c
导入进工程; 当然也可以用苹果封装好的GLKit中的对应方法代替(下篇文章会讲解)
实现围绕X/Y/Z轴旋转三角体:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
{
float xDegree;
float yDegree;
float zDegree;
BOOL bX;
BOOL bY;
BOOL bZ;
NSTimer* myTimer;
}
- (IBAction)XClick:(id)sender {
//开启定时器
if (!myTimer) {
myTimer = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:@selector(reDegree) userInfo:nil repeats:YES];
}
//更新的是X还是Y
bX = !bX;
}
- (IBAction)YClick:(id)sender {
//开启定时器
if (!myTimer) {
myTimer = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:@selector(reDegree) userInfo:nil repeats:YES];
}
//更新的是X还是Y
bY = !bY;
}
- (IBAction)ZClick:(id)sender {
//开启定时器
if (!myTimer) {
myTimer = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:@selector(reDegree) userInfo:nil repeats:YES];
}
//更新的是X还是Y
bZ = !bZ;
}
-(void)reDegree
{
//如果停止X轴旋转,X = 0则度数就停留在暂停前的度数.
//更新度数
xDegree += bX * 5;
yDegree += bY * 5;
zDegree += bZ * 5;
//重新渲染
[self render];
}