OpenGL空间(坐标系)变换


   网友的《3D图形学的学习策略》一文使我深受启发,在图形学以及openGL学习方面给了我很有价值的指导性意见,在此对前辈们的不吝赐教表示感激,谢谢你们的无私分享。

    如文章所说,API是工具,不是本质,OpenGL/Direct3D的本质是图形学,而不是OpenGL/Direct3D的本身,API的本身只是一些Interface而已。最重要的,最根本的是,你要明白这些API背后的图形学的原理---因为那才是根本中的根本。其实很多事情,包括学习也涉及到生活,只有抓住了本质,才能体会到其中的真谛。

    带着这种希望探究本质的学习方法,结合图形学原理,通过阅读书目和网友们的文章,我对OpenGL几何空间变换进行了总结性的学习。

   OpenGL处理管线的目的是将对象的三维描述转换为可以显示的二维图像。为了完成这个从三维到二维的转换,OpenGL使用了多个空间(坐标系),每个空间完成特定的任务,从一个空间到另一个空间需要进行空间转换。理解OpenGL所使用的各种空间以及它们间的变换是非常重要的。

      

    如上图所示,openGL中使用的空间依次是:对象空间、世界空间、视点空间、裁剪空间、归一化设备空间、窗口空间、屏幕空间。结合自己的理解,就每个空间完成的基本任务和空间的变换关系,总结如下。

    对象空间。对象空间中完成的最大任务是对象建模,三维对象的属性,包括顶点位置和表面法线等是在这个空间内指定的。这个空间的坐标原点一般在对象上,有时候也在其他地方,主要是为了建模方便。每一个对象都有一个自己的对象空间。就openGL而言,我目前还没有接触到建立很复杂模型的应用,建模一般在其他地方如3DMAX中完成,然后读入openGL进行处理。

    世界空间。对象空间之后是世界空间,我理解为世界坐标系是固定不变的。世界空间主要是对三维场景进行描述,就是把已经建立的各种对象摆放在三维空间中,空间的转换是通过模型变换完成的。可以通过平移、旋转、比例缩放等把对象摆放在需要的位置,就好像买好家具以后设计房间布局一样。同时光源位置以及相机的位置、方向等也是在世界空间中指定的。这样,通过把对象、光源、相机指定到同一个空间中,就可以很方便的设置、调整它们之间的空间关系,得到自己想要的结果。

    房间的场景布置好以后,就可以在房间的不同的地方以不同的角度进行欣赏了。这就涉及到从世界空间到视点空间的转换了,这个任务由视图转换完成。视点空间是以视点(相机)为坐标原点的观察空间,并且观察的轴线方向始终指向Z轴的负方向,也就是说在视点坐标系里面,观察点的位置和方向是固定的。视点坐标系是左手坐标系,世界坐标系是右手坐标系。

    在openGL中,模型转换和视图转换是通过一个矩阵完成的,这个矩阵叫模型视图矩阵。在世界空间中变换对象、移动相机都是改变的模型视图矩阵,在任何时刻,模型视图矩阵状态值都包含了照相机坐标系和世界坐标系之间的关系。平移、旋转、比例缩放等模型变换只对在它们之后定义的对象起作用,而移动相机对世界空间中的所有对象都起作用,也就是说只要相机移动,模型视图矩阵就被修改,然后作用到世界空间中的所有对象上,进行视图转换。可以理解为模型变换是对某些对象进行的,而视点变换是对整个场景进行的。这里需要说明光源是个特例,glLight()是在世界空间中指定光源位置的,模型变换可以修改它在世界空间的位置,但是这个位置不一定经过视图变换,我在以前的总结《怎样在openGL中控制光源的位置》里思考过这个问题,现在感觉当时的理解是正确的。进入视点空间后,对象的相对空间关系没有变化,改变的只是对它们的描述。

    视点空间还有一个作用就是指定观察视域体。处在观察视域体内部或者部分在内部的对象才有可能被绘制到二维的图像中,而完全在外部的对象将会被舍弃。确定哪些对象完全在观察视域体内,哪些对象部分在观察视域体内,哪些对象完全不在观察视域体内的过程叫裁剪。这就由视点空间进入到裁剪空间,以便完成裁剪,这个变换通过投影变换完成,修改的是投影矩阵。

    裁剪之后经过透视除法就进入了归一化设备空间,这个空间在openGL里是处在(-1, -1, -1), (1, 1, 1)间的立方体空间。

    这里需要说一下,我在这个地方花费的时间最多,疑惑也最多,关于透视投影的一些问题依然不确定。在透视投影产生的裁剪空间里是如何裁剪的呢?网友Twinsen编写的《深入探索透视投影变换》一文中这样写到:

 透视投影变换由两步组成:

        1)用透视变换矩阵把顶点从视锥体中变换到裁剪空间的CVV中。

     2)CVV裁剪完成后进行透视除法。       

   CVV即(-1, -1, -1), (1, 1, 1)间的立方体空间。这个步骤好像和投影变换产生CVV的顺序有矛盾。CVV是经过投影变换矩阵和透视除法后才形成的,怎么可能在透视除法前进行CVV裁剪呢?这个CVV和归一化设备坐标空间是不是一个空间,或许我把它们混淆了?这些是我不明白的地方。我感觉也许在透视投影裁剪空间里使用的是一种叫做齐次坐标裁剪的裁剪方法,而不是CVV裁剪,不过这有待确认。殷切希望网友们的指导或推荐能够帮我解决这些问题的资料,谢谢大家。

    在归一化设备空间中的点都有可能出现在二维图像里,不过它们要经历一系列测试,只有那些能够过五关、斩六将的点才能笑到最后。这个不是这次总结的重点。 

    归一化设备空间的下一个空间是窗口空间。窗口空间也是一个三维的空间,以前我以为它是二维的。从归一化设备空间到窗口空间需要进行视口变换,主要完成平面x,y和深度z的映射。在openGL中视口变换一般把归一化设备空间中-1到1的深度变换到0到1的范围内,以便和像素灰度范围一致。窗口空间的二维平面信息对应屏幕的显示,深度信息则对应深度缓存内的信息。图形图元的栅格化是使用窗口坐标执行的。

    经过这么一系列空间变换和其他一些操作,一幅三维图像就生成了。


后记:

 总结性的学习,有利于整体把握知识,使得学习系统化,完备化。 

参考资料:

1《OpenGL着色语言》Randi J.Rost著,天宏工作室译, 人民邮电出版社

2 blog.csdn.net/xueyong1203/archive/2008/01/10/2033873.aspx 

  《深入探索透视投影变换》

3www.songho.ca/opengl/gl_transform.html

 《OpenGL Transformation》

转载于:https://www.cnblogs.com/zsw-1993/archive/2012/12/14/4880569.html

你可能感兴趣的:(OpenGL空间(坐标系)变换)