opengl学习脚印opengl坐标变换_第1页
opengl学习脚印opengl坐标变换_第2页
opengl学习脚印opengl坐标变换_第3页
opengl学习脚印opengl坐标变换_第4页
opengl学习脚印opengl坐标变换_第5页
已阅读5页,还剩5页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、OpenGL 学习脚印 OpenGL 坐标变换OpenGL 学习脚印 : OpenGL 坐标变换写在前面 本节内容翻译和整理自 songho 的博客 OpenGL Transformation 内容 ,以供自己和初学者熟悉 OpenGL 中坐 标变换的整个过程。通过本节,你可以了解到 :OpenGL 坐标变换过程理解 OpenGL 矩阵计算概览几何数据例如顶点位置和法向量在光栅化操作之前,都要通 过 Vertex Operation 和 Primitive Assembly OpenGL 流 水线操作 (在 OpenGL pipeline 节描述 )。 OpenGL 顶点变换 Object C

2、oordinates( 对象坐标系或模型坐标系 ) 这是对象的局部坐标系统,是对象在被应用任何变 换之前的初始位置和方向所在的坐标系。要对对象实行变换, 可以使用 glRotatef(), glTranslatef(), glScalef() 等函数。 Eye Coordinates( 眼坐标系或照相机坐标系 )由 GL_MODELVIEW 矩阵和模型坐标系中坐标相 乘的结果。在 OpenGL 中使用 GL_MODELVIEW 矩阵来使 对象从模型坐标系转换到眼坐标系。GL_MODELVIEW 矩阵是模型变换和视变换矩 阵的组合 (Mview*Mmodel) 。模型变换从对象坐标系转换到世 界

3、坐标系,而视变换从世界坐标系转换到眼坐标系。注 意:OpenGL中并没有单独的视变换矩阵。 因此,要想模拟变 换照相机或者进行视变换, 那么场景 (3D 对象和光照 )必须以 视变换矩阵的逆矩阵进行变换。换言之, OpenGL 将照相机 定义在位于眼坐标系下朝向 -Z 轴,位于点 (0,0,0) 的位置,而 不能进行变换。 法向量同样从对象坐标系变换到眼坐标系来用于光照计算。 注意:法向量的转换方式和顶点不同。它用法向量乘以 GL_MODELVIEW 矩阵的逆矩阵的转置矩阵。 请参考 Normal Vector Transformation 获取更多细节。 Clip Coordinates(

4、裁 剪坐标系 )眼坐标通过乘以 GL_PROJECTION 变成了裁剪 坐标。这个 GL_PROJECTION 矩阵定义了视见体 ( viewing volume,frustum) ,顶点式如何投影到屏幕上的 ( 透视投影还 是正交投影 perspective or orthogonal) 。称作裁剪坐标系的 是因为,经过变换后的顶点(x,y,z)将与可相比较来进行裁 剪。请参考下面 ProjectionMatrix 部分获取更多细节。Normalized DeviceCoordinates (NDC) ( 归一化设备坐标系 )由裁剪坐标系下通过除以 W 分量得到。这个操作称 为透视除法。 N

5、DC 坐标很像屏幕坐标, 但是还没有经过平移 和缩放到屏幕像素。现在 3 个轴上的值范围均为 -1,1 。 Window Coordinates (Screen Coordinates)( 屏幕坐标 ) 通过对 NDC 坐标进行视口变换得到。 NDC 坐标通 过平移和缩放来适应渲染的屏幕。屏幕坐标最终传递给绘制 流水线中的光栅化处理部分来变成片元。 glViewport() 用来定义渲染区域的矩形,这是最终图像映射到的区域。另 外, glDepthRange() 用来确定屏幕坐标中的 Z 值。屏幕坐标 通过上面两个函数的给定参数来进行计算 : glViewport(x, y, w, h);gl

6、DepthRange(n, f);这个公式由 NDC 坐标和屏幕坐标之间的线性关系来获得 的 :OpenGL 变换矩阵OpenGL 使用 4x4 矩阵来进行变换。 注意, 这 16 个元 素的矩阵,实际上按列主序的方式以 1D 形式存储。如下图 所示:如果想当做通常的行主序格式使用,你需要将其转置。OpenGL 当中,有四类型的矩阵 : GL_MODELVIEW,GL_PROJECTION, GL_TEXTURE, 和 GL_COLOR可以通过 glMatrixMode() 函数来指定当前矩阵 类型,例如使用模视矩阵,则可以选择 GL_MODELVIEW 调用 glMatrixMode(GL_

7、MODELVIEW) 。 Model-View Matrix (GL_MODELVIEW)模视矩阵GL_MODELVIEW 矩阵将模型变换矩阵和视变换矩 阵组合成一个矩阵。为了转换相机,你需要对整个场景执行 相反的变换。 gluLookAt() 函数专门用来设定视变换。矩阵最 后一列元素 (m12,m13, m14) 用于执行平移变换, glTranslatef() 。 元素 m15 是齐次坐标系下坐标,特别用于投影变换。(m0, m1,m2), (m4, m5, m6) and (m8,m9,m10)这3个元素集,用于欧几里得和仿射变换,例如 glRotatef() 用于旋转, glScal

8、ef() 用于缩放。注意 : 这三个元 素集实际上代表 3 个正交坐标轴 :(m0, m1,m2): +X axis,left vector, (1, 0, 0) by default(m4, m5,m6): +Y axis, up vector, (0, 1, 0) by default(m8, m9,m10) : +Z axis, forward vector, (0, 0, 1) by default如下图所示 :我们可以从角度和 lookat 向量来直接构造 GL_MODELVIEW, 而不是用 OpenGL 来操作 4 列的 GL_MODELVIEW 矩阵。这里有一些有用的代码来构造

9、 GL_MODELVIEW 矩阵 :Angles to AxesLookat to AxesMatrix4 class 注意 :如果多个变换应用到一个顶点时 ,OpenGL 以逆序的方 式执行多个相乘操作。 举例来说, 如果顶点先由 MA 变 换,再由 MB 变换,那么 OpenGL 先执行 MB x MA 操作,再乘以顶点。因此,在代码中,后执行 的变换先出现,而先执行的变换后出现:cpp view plaincopyprint?/ Note that the object will be translated first then rotatedglRotatef(angle, 1, 0,

10、 0);/rotate object angle degree around X-axis glTranslatef(x, y, z);/ move object to (x, y, z)drawObject();<span style=font-size:14px;><code class=codeblockstyle=margin-left:30px;></code></span>Projection Matrix (GL_PROJECTION) 投影矩阵 GL_PROJECTION 用于定义视锥。视锥决定了哪些对象以 及对象的哪些部分会被裁

11、减掉。 同时, 它也决定了 3D 场景 是如何被投影到屏幕上的。OpenGL 使用两个函数来进行投影变换。 glFrustum() 用于进 行透视投影 ,glOrtho() 用于进行正交 (平行 )投影。这两个函数 都需要 6 各参数来指定裁剪平面的 :left,right, bottom, top, near and far planes 。两个函数原型如下 : void glFrustum(GLdouble left, GLdouble right,GLdoublebottom,GLdoubletop, GLdoublenearVal,GLdoublefarVal);void glOrth

12、o(GLdoubleleft,GLdouble right,GLdoublebottom,GLdoubletop, GLdoublenearVal,GLdoublefarVal);8个顶点如下图所示 :远裁剪面 (far) 的顶点可以通过相似三角形的比例计算出来 (补充 : 实际上通过函数 gluFrustum 指定时,参数都是指的 近裁面的 l,r,t,b ,远裁剪面可以计算出来 ),例如,远裁剪面 的 left 参数可以如下计算:对于正交投影, 这个比例是 1,因此远裁剪面的 left,right, bottom 和 top 和近裁剪面的一样 ,如下图所示 : gluPerspective

13、() and gluOrtho2D() 函数使用时需 要更少的参数。 gluPerspective() 只需要四个参数, FOV 视 角,宽高比,以及远近裁剪面的距离。函数原型为 : void gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar); 从 gluPerspective() 转换为同等的 glFrustum() 的代码如下 :cpp view plaincopyprint?/ This creates a symmetric frustum. / It converts to 6

14、params (l, r, b, t, n, f) for glFrustum() / from given 4 params (fovy, aspect, near, far) void makeFrustum(double fovY, double aspectRatio, double front, double back)const doubleDEG2RAD = 3.14159265 / 180;double tangent =tan(fovY/2 * DEG2RAD);/ tangent of half fovYdouble height = front * tangent;/ h

15、alf height ofnear planedouble width = height * aspectRatio;/ half width of near plane/ params: left, right,bottom, top, near, farglFrustum(-width, width,-height, height, front, back);补充 : 关于 gluPerspective 函数计算视锥 利用 gluPerspective 函数指定视锥如下图所示 注意到视锥的对称性,利用三角形的相似性,可以推算如下 图所示 : 其中 top : n = tan(fov/2)

16、,bottom= -top, left = -right =>top= height/2 =n*tan(fov/2) height 为近裁剪面高度 => right=width/2 = aspect*height/2=aspect*n*tan(fov/2) width 为近裁剪面宽度注意上述代码中 width,height 均为实 际值的一半。 注意 :这里使用 gluPerspective 函数构造的是 一个对称的视锥,如果你想要构造非对称视锥必须直接使用 glFrustum() 函数。例如,你想要把一个宽场景绘制到两个相 连的屏幕上,你可以将视锥分割为左右两个非对称的视锥, 然

17、后在每个视锥中渲染场景,如下图所示:Texture Matrix(GL_TEXTURE) 纹理矩阵纹理坐标 (s,t,r,q) 在进行任何纹理映射前乘以 GL_TEXTURE 。默认情况下,它是一个单位阵,因此纹理 会被映射到物体的位置,那个你指定纹理坐标的位置。通过 修改 GL_TEXTURE ,你可以滑动、旋转、拉伸以及收缩纹 理。 cpp view plaincopyprint?/ rotate texture around X-axis glMatrixMode(GL_TEXTURE);glRotatef(angle, 1, 0, 0)Color Matrix (GL_COLOR) 颜

18、色矩阵颜色分量 (r,g,b,a) 乘以 GL_COLOR 矩阵。可以用 于颜色空间转换和颜色分量交换。 GL_COLOR 矩阵被经常 使用,并且需要 GL_ARB_imaging 拓展。其他的矩阵操作 glPushMatrix() :push the current matrix into the current matrix stack.glPopMatrix() :pop the current matrix from the current matrix stack.glLoadIdentity() :set the current matrix to the identity matrix.glLoadMatrixfd(m) : replace the current matrix with the matrixm.glLoadTransposeMatrixfd(m) : replace the current matrix with the row-major ordered matrixm.glMultMatrixfd(m) :multiply the current matrix by the matrixm, and u

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论