[翻译]坐标变换——OpenGL ES Common/Common-Lite 规范(版本 1.1.12)

原文网址:点击打开链接http://www.moandroid.com/?p=992

2.10 坐标变换

顶点,规格化和纹理坐标 在应用到帧缓存中构建图片前都需要变换。我们开始介绍顶点坐标如何变换和如何控制这些变换。

1

图示2.5. 顶点变换序列

图示2.5演示了应用到顶点上的一系列变换。在GL中顶点坐标 称作 物体坐标。模型-视图矩阵将这些坐标变换成视觉坐标。其他被称为物体矩阵的矩阵,将视觉坐标变换成裁剪坐标。透视除法将裁剪坐标变换成规格化设备坐标。视口变换最终将这些坐标变换成窗口坐标。

    物体坐标,视觉坐标和裁剪坐标都为4维值,分别为x,y,z和w坐标。因此,模型-视图矩阵和物体矩阵为4*4矩阵。

如果一个物体坐标中的顶点为 1,模型-视图矩阵为M,则顶点的视觉坐标值为

2

同样,如果P为物体矩阵,则裁剪坐标值为

3

顶点的规格化设备坐标值为

1

2.10.1 控制视口

视口的宽度 px、高度py和中心坐标(ox,oy)决定视口变换值。顶点的窗口坐标值为:

2

 zd通过n和f通过以下命令生成

void DepthRangef(clampf n, clampf f);

void DepthRangex(clampx n, clampx f);

每个n和f都在[0,1]之间,类型为clampf或者clampx。zw使用一个顶点数表示,比特位数至少和帧缓存中的深度缓存一致。我们假设定点数可以表达的值为k/(2m-1),k∈{0,1,…,2m-1}。

    视口变换的参数通过以下的命令定义

void Viewport(int x, int y, sizei w, sizei h);

这里的x和y定义了视口左下角的窗口坐标,w和h定义了视口的宽度和高度。其他参数可以通过以上值计算获得,ox=x+w/2;oy=y+h/2;px=w,py=h。

    视口的宽度和高度在0和最大值之间,其中最大值依赖具体实现。这个最大值可以通过一个Get命令获得。视口的最大值必须大于等于显示器的可见区域。如果w或者h为负值,将会产生INVALID_VALUE错误。

    执行视口变换的状态值需要四个整数和2个浮点数。初始化时,使用窗口的宽度和高度设置w和h,ox和oy被设置成w/2和h/2,n和f被设置为0.0和1.0。

 

2.10.2 矩阵

物体矩阵和模型-视图矩阵可以通过一些命令来设置和修改。当前的矩阵模式决定了矩阵的类型。设置当前矩阵模式的命令为

void MatrixMode(enum mode);

mode 为预设定的常量TEXTURE,MODELVIEW,或者PROJECTION。TEXTURE将在以后介绍。如果当前矩阵模式为MODELVIEW,则对矩阵操作将应用到模型-视图矩阵中;如果为PROJECTION,则操作将应用到物体矩阵中。影响当前矩阵的2个基本命令为

void LoadMatrix{xf}(T m[16]);

void MultMatrix{xf}(T m[16]);

LoadMatrix的参数T为一个指向4*4矩阵的数组指针,该数组中按照列优先(这点不同于标准C中行优先的顺序,如果使用标准的顺序,所有子变换都将改变,列向量将变成行向量)保存了16个定点或者浮点数。例如:

3

指针指向的矩阵将代替当前矩阵。MultMatrix的参数和LoadMatrix类型一样,但是MultMatrix使用当前矩阵乘以参数指针指向的矩阵的结果代替当前矩阵。如果C是当前矩阵,M为参数指针指向的举证,计算后的结果矩阵为C’,则

C’=C·M

命令

void LoadIdentity(void);

等同于调用以单位矩阵做参数的LoadMatrix:

4

还有一些其他的操作矩阵的命令。Rotate,Translate,Scale,Frustum和Ortho都可以操作当前矩阵。每次计算一个矩阵后,在调用MultMatrix使用这个矩阵。

void Rotate{xf}(T θ, T x, T y, T z);

θ定义一个旋转的角度,以度为单位。一个向量v的坐标值表示为29。计算后的矩阵围绕通过原点的特定坐标轴做逆时针旋转,该坐标轴已经被清楚表明的(可以使用右手规则在确定旋转的角度)。因此矩阵为

6

假设7 。如果

8

9

命令

void Translate{xf}(T x, T y, T z);

的参数使用一个变换向量 10。命令实际使用下列向量进行矩阵变换:

11

命令

void Scale{xf}(T x, T y, T z);

沿着x,y,z坐标轴进行缩放,对应的矩阵为

12

命令

void Frustum{xf}(T l, T r, T t, T n, T f);

坐标 1314定义了最近裁剪平面的点。假设观察点在15 ,f定义了距离观察点最远裁剪平面的点。如果n或者f小于等于0,l等于r,b等于t,或者n等于f,都会产生INVALID_VALUE的报错。对应的矩阵为

16

命令

void Ortho{xf}(T l, T r, T b, T t, T n, T f);

描述了一个构建平行物体的矩阵。坐标1314定义了最近裁剪平面的点。假设观察点在15 ,f定义了距离观察点最远裁剪平面的点。如果l等于r,b等于t,或者n等于f,都会产生INVALID_VALUE的报错。对应的矩阵为

17

对于每个纹理单元,一个4*4矩阵应用到对应的纹理坐标值。这个矩阵应用如下

18

左边的矩阵是当前的纹理矩阵。这个矩阵应用到当前纹理坐标值。变换后的坐标值与一个向量进行联合。设置矩阵模式为TEXTURE将把矩阵操作应用到纹理矩阵中。

每个纹理单元都有一个相对应的纹理矩阵堆栈。矩阵操作可以改变这个堆栈,可以调用以下命令设置活动的纹理单元选择器。

void AciveTexture(enum texture);

这个选择器会影响到一些调用:修改纹理的环境状态,纹理的坐标生成状态,纹理的绑定状态和所有当前纹理坐标的可查询状态值。

定义一个无效的纹理会导致INVALID_ENUM报错,纹理的有效值与MultiTexCoord命令中描述的一样。

    每个矩阵模式MODELVIEW和PROJECTION下,以及每个纹理单元都有一个对应的堆栈。在MODELVIEW模式下,堆栈的深度至少为16(也就是说,至少可以存放16个模型-视图矩阵)。对于其他模式,堆栈的深度至少为2。所有的纹理单元有同样深度的纹理矩阵堆栈。当前矩阵都为在栈顶矩阵。

命令

void PushMatrix(void);

推入一个对象到栈中,复制当前矩阵到栈顶和栈顶的下一个对象。

命令

void PopMatrix(void);

推出顶层的对象,并使用第二个对象代替当前矩阵。堆出和推入操作影响当前矩阵模式对应的堆栈。如果从只有一个对象的堆栈中推出一个矩阵,将会产生STACK_UNDEFLOW报错。推入一个矩阵进入一个满栈,将会产生一个STACK_OVERFLOW报错。

    当前矩阵模式为TEXTURE时,推入和推出会作用于当前活动纹理的矩阵堆栈。

    实现一个纹理变换,需要一个整型值为当前活动纹理单元的选择器,一个四值整型值(枚举值)指明当前的矩阵模式,一个至少可以存放2个4*4物体矩阵或者纹理单元矩阵的堆栈,MODELVIEW模式下,一个至少可以存放16个4*4矩阵的堆栈。每个矩阵堆栈有一个对应的栈指针。初始化时,在每个堆栈中只有一个矩阵,所有的矩阵都为单元矩阵。初始化纹理单元选择器为TEXTURE0,初始化的矩阵模式为MODELVIEW。

 

2.10.3 规格化变换

最后,我们考虑下模型-视图矩阵和变换状态如何影响规格化。在使用光照前,需要在模型-视图模式下,通过一个矩阵,规格化坐标值到视觉坐标中。在光照前,优先执行重新缩放和规格化操作,以保证他们的单元长度。重新缩放和规格化通过以下命令控制

void Enable(enum target);

void Disable(enum target);

target为RESCALE_NORMAL或者NORMALIZE。这里需要2个比特位的状态值。初始化的状态值为不重缩放或者不规格化。

    如果模型-视图矩阵为M,则规格化到视觉坐标值按照以下方法计算:

19

如果20 为矢量坐标,则

21

具体实现可能选择转换22到视觉坐标中。

23

此处Mu为M中左上的3*3子矩阵。

重缩放需要一个缩放因子乘以规格化的值。

24

如果重缩放不可用,则f=1。如果重缩放可用,f按照以下方式计算

25

mij为M-1中,i行j列的元素,此处第一行行号为1,第一列列号为1。

注意如果规格化到GL中为单元长度,并且模型-视图矩阵唯一的缩放空间,则重缩放也为单元长度。

       可选择的,在规格化时,具体实现可能按照以下方式重新计算f

26

这个将使用所有非零长度的规格化单元长度,不管他们的输入长度和模型-视图矩阵的自然长度。

    重缩放后,光照中的最终规格化转换nf,计算如下

27

如果规格化不可用,则m=1。反之

28

因为我们没有定义浮点格式,也没有定义矩阵的转置,所以我们不能定义模型-视图的矩阵M不是一个非凡矩阵。如果存在一个非凡矩阵,规格化变换是未定义的。如果GL的实现决定模型-视图矩阵是不可转置的,则转置后的矩阵是随意的。无论怎样,规格化变换或者使用规格化变换的都不可能导致GL的中断或者终止。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值