《深入了解OpenGL》第二讲:顶点线性变换_第1页
《深入了解OpenGL》第二讲:顶点线性变换_第2页
《深入了解OpenGL》第二讲:顶点线性变换_第3页
《深入了解OpenGL》第二讲:顶点线性变换_第4页
《深入了解OpenGL》第二讲:顶点线性变换_第5页
已阅读5页,还剩7页未读 继续免费阅读

下载本文档

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

文档简介

深入了解深入了解 OpenGL OpenGL 第二讲 顶点线性变换第二讲 顶点线性变换 时间 2010 05 11 12 56 点击 2157 次 上周发布了 深入了解 OpenGL 第一讲 绘制基本图元 今天 CocoaChina 会员 zenny chen 带来了 OpenGL 知识第二讲 帖子地址 这一章节可 能会比较枯燥 上周发布了 深入了解 OpenGL 第一讲 绘制基本图元 今天 CocoaChina 会员 zenny chen 带来了 OpenGL 知识第二讲 帖子地址 id 20395 html 这一章节可能会比较枯燥 当然示例代码将会非常有趣 枯燥的是将会有很多线性代数的 知识夹杂其中 在本章中我们将对 3D 图形进行绘制 我们会介绍 顶点变换的过程 以及 法线向量与绘制顺序 这里将首先介绍一下一个三维空间上的顶点被映射到二维屏幕坐标的步骤 请各位务必牢 记 物体顶点坐标 顶点 模型视图变换 视觉坐标 投影变换 裁剪坐标 透 视划分 规格化设备坐标 视口变换 窗口坐标 上图中 表示经过某种变换 表示得到某个坐标 下面我们将根据这个顺序来依次介绍各个变 换 这里将主要介绍模型视图变换和投影变换 先介绍 OpenGL 中物体顶点坐标的表示 OpenGL 中 物体的顶点坐标是由一个四维的行向量来表示的 表示为 x y z w 其 中 x y z 分别对应 x 轴 y 轴和 z 轴 而 w 用于辅助做线性变换 我们会理所当然地认 为 三维坐标系只要三个分量就够了 w 到底有何用呢 我们这里首先要说 明一下 在 OpenGL 中 线性变换矩阵的变换都是用矩阵的乘法 没有 加减法 因此所有线性变换都是通过矩阵的乘法来完成的 所以 比如说我们要把一个顶 点 1 1 1 沿 x 轴向右平移 5 个单位 那要用三维变换矩阵表示的话就要是 M 6 0 0 0 1 0 0 0 1 那么 v v M 6 1 1 但很多场合下使用三维空间做变换将会使计算变得非常复杂 甚至很难进行变换 因此引 入 四维空间使得变换更加灵活 比如 顶点 v 1 1 1 1 沿 x 轴向右平移 5 个单位 那么变换矩阵 M 1 0 0 0 0 1 0 0 0 0 1 0 5 0 0 1 我们将看到这个 4x4 的变换矩阵与 3x3 的相比就显得简单很多 因 为对于平移来说 本身 就是加法 而三维空间中就需要使用乘法 从而加大了计算负荷 在 OpenGL 中 物体的顶点坐标在进行计算时总是以行向量的 形式表示 并且计算时总是 在最左边 下面将正式介绍视图各种变换 先贴代码 1 void prepareOpenGL 2 3 glShadeModel GL SMOOTH 4 5 glClearColor 0 0 0 0 0 0 0 0 6 glViewport 0 0 320 320 7 8 glMatrixMode GL PROJECTION 9 glLoadIdentity 10 glOrtho 1 0 1 0 1 0 1 0 1 0 5 0 11 12 glMatrixMode GL MODELVIEW 13 glLoadIdentity 14 glTranslatef 0 3f 0 2f 0 0f 15 glRotatef 30 0f 0 0f 0 0f 1 0f 16 17 glFrontFace GL CCW 18 glEnable GL CULL FACE GL DEPTH TEST 19 20 21 void drawRect NSRect dirtyRect 22 23 static struct 24 25 GLubyte colours 4 26 GLfloat vertices 3 27 28 vertexInfoList 29 255 0 0 255 0 5f 0 5f 1 0f 30 0 255 0 255 0 5f 0 5f 1 0f 31 0 0 255 255 0 5f 0 5f 2 0f 32 255 0 255 255 0 5f 0 5f 2 0f 33 34 35 Drawing code here 36 glClear GL COLOR BUFFER BIT 37 38 glInterleavedArrays GL C4UB V3F 0 vertexInfoList 39 40 glCullFace GL BACK 41 glDrawArrays GL TRIANGLE STRIP 0 4 42 43 glFlush 44 下面介绍视图模型变换 视图模型变换是将三维物体的顶点做平移 旋转等操作 我们可以这么理解 我们把摄像 机镜头固定好 然后观察物体的移动行 为 在上述代码的第 12 行 glMatrixMode GL MODELVIEW 用于将当前矩阵变换的操作作用到 视图模型变换栈上 glLoadIdentity 作用是将当前的矩阵作为单位矩阵 即 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 其实际效果就是 C I 其中 C 表示 本矩阵模式的当前矩阵 I 表示单位矩阵 glTranslatef 0 3f 0 2f 0 0f 是平移变换 函数原型为 void glTranslated GLdouble x GLdouble y GLdouble z void glTranslatef GLfloat x GLfloat y GLfloat z 其中 x 表示沿 x 轴平移多少单位 y 表示沿 y 轴平移多少单 位 z 表示沿 z 轴平移多少 单位 而 其对应的平移变换矩阵就是 1 0 0 0 0 1 0 0 0 0 1 0 x y z 1 那么 glTranslatef 0 3f 0 2f 0 0f 实际效果就是 C T C T I 因为我们 刚才调用了 glLoadIdentity 因此在调用此函数时的当前矩阵就是 I 而下面的 glRotatef 30 0f 0 0f 0 0f 1 0f 则是将所要绘制的物体的每个顶点坐标 绕 z 轴 顺时针旋转 30 度 下面给出 glRotatef 的原型 void glRotated GLdouble angle GLdouble x GLdouble y GLdouble z void glRotatef GLfloat angle GLfloat x GLfloat y GLfloat z 其中 angle 表示角度制的角度 x y 和 z 表示绕着由 x y 和 z 构成的向量进行旋转 如果 angle 大于 0 则做逆时针旋转 小于 0 做顺时针旋转 等于 0 不动 由于 glRotate 所对应的变换矩阵比较 复杂 各位可以参考 OpenGL 官网上的手册 如果将旋转变换矩阵表示为 R 的话 那么这里调用 R 的效果其实就是 C R C 那么 将上面所有的串起来就是 C R T I 如果顶点单纯地只经过视图模型变换 那 么对于物体其中一个顶点 v 而言 变换后的顶点 v v R T I 我们这 里实际上是先对物体做绕 z 轴旋转 然后再平移 但是调用的时候必须先调平移函 数 再调旋转函数 下面在介绍投影变换前再介绍几个对矩阵操作的函数 首先是 glLoadMatrix 下面先给出 函数原型 void glLoadMatrixd const GLdouble m 只能用于 OpenGL void glLoadMatrixf const GLfloat m void glLoadMatrixx const GLfixed m 只能用于 OpenGL ES 该函数表示在当前变换矩阵模式下将矩阵 m 取代当前的变换矩阵 比如 glLoadIdentity 可以用一下代码替换 glLoadMatrixf const GLfloat 1 0f 0 0f 0 0f 0 0f 0 0f 1 0f 0 0f 0 0f 0 0f 0 0f 1 0f 0 0f 0 0f 0 0f 0 0f 1 0f 然后是再介绍一下 glMultMatrix 函数 请参 看函数原型 void glMultMatrixd const GLdouble m 仅用于 OpenGL void glMultMatrixf const GLfloat m void glMultMatrixx const GLfixed m 仅用于 OpenGL ES 这个函数就很直白地表示用矩阵 m 与当前矩阵相乘 然后将结果再 给回当前矩阵 即 C M C 我们可以用一下代码替换 glTranslatef glMultMatrixf const GLfloat 1 0f 0 0f 0 0f 0 0f 0 0f 1 0f 0 0f 0 0f 0 0f 0 0f 1 0f 0 0f 0 3f 0 2f 0 0f 1 0f 将上述代码替换掉 3 楼的第 14 行 效果不变 下面介绍投影变换 投影变换就好像为照相机选择镜头 我们可以认为这种变换的目的就是确定视野 或视景 体 并且确定哪些物体位于视野之内以及它 们能够被看到的程度 投影变换主要有两种 一种是透视投影 Perspective Projection 这种投影效果就像 是玩第一人称游戏或是第一人称的赛车类游戏 你向前看具有透视效果 远处的物体显得 小 近处的物体显得大 还 有一种投影是正交投影 Orthographic Projection 这种投影是将顶点以平行于视 野的角度垂直地映射到屏幕上 物体不管离你多远 其大小都是一样的 透视投影对应的函数 为 glFrustum 函数原型如下 void glFrustum GLdouble left GLdouble right GLdouble bottom GLdouble top GLdouble nearVal GLdouble farVal OpenGL void glFrustumf GLfloat left GLfloat right GLfloat bottom GLfloat top GLfloat near GLfloat far OpenGL ES void glFrustumx GLfi xed left GLfixed right GLfixed bottom GLfixed top GLfixed near G Lfixed far OpenGL ES 其中 left 表示 x 轴坐标最左端的值 right 表示 x 坐标 最右端的值 bottom 表示 y 轴坐标最下端的值 top 表示 y 轴最上端的值 near 表示与摄像机或你 的眼镜最近的距离 far 表示摄像机或离你的眼镜 最远的距离 near 和 far 都 大于 0 方有效 而正交投影的定义与透视投影的类似 下面给出函数原型 void glOrtho GLdouble left GLdouble right GLdouble bottom GLdouble top GLdouble nearVal GLdouble farVal OpenGL void glOrthof GLfloat left GLfloat right GLfloat bottom GLfloat top GLfloat near GLfloat far OpenGL ES void glOrthox GLfixed left GLfixed right GLfixed bottom GLfixed top GLfixed near GLfixed far OpenGL ES 首先 各位可以先用 glFrustum 来替换 glOrtho 看看效果 呵呵 然后我们看 3 楼代码 29 到 32 行 为什么这里 z 坐标为 1 和 2 因为我们调用了 glOrtho 1 0 1 0 1 0 1 0 1 0 5 0 也就是说你的视 野最近看到的距离为 1 最远是 5 由于你的视野是正对屏幕的 也就是朝 z 轴 的负方向 因此这里必须把物体沿 z 轴移到你的视野范围 内才能看到物体 如 果我们把物体顶点的 z 轴值改为大于 1 或小于 5 那偶们就看不见该顶点了 呵呵 好 那么我们现在结合模型视图变换 和投影变换 那么它们的调用顺序是何如 的呢 我们在 1 楼知道 视图的变换步骤是先经过视图模型变换 然后再经过投影变 换 因此对于一个顶点 v 来 说 若视图模型变换矩阵是 M 而投影变换矩阵为 P 那么变换后的顶点 v v M P 我们不妨可以做个实验 为了能证明这个步 骤 我们将投影变换改为透视投影 即 将 glOrtho 改为 glFrustum 观察图形 然后我们做以下修改 复制代码 1 void prepareOpenGL 2 3 glShadeModel GL SMOOTH 4 5 glClearColor 0 0 0 0 0 0 0 0 6 glViewport 0 0 320 320 7 8 glMatrixMode GL PROJECTION 9 glLoadIdentity 10 glFrustum 1 0 1 0 1 0 1 0 1 0 5 0 11 12 glMatrixMode GL MODELVIEW 13 glLoadIdentity 14 15 glMultMatrixf const GLfloat 16 1 0f 0 0f 0 0f 0 0f 17 0 0f 1 0f 0 0f 0 0f 18 0 0f 0 0f 1 5f 1 0f 19 0 0f 0 0f 2 5f 0 0f 20 21 22 glTranslatef 0 3f 0 2f 0 0f 23 glRotatef 30 0f 0 0f 0 0f 1 0f 24 25 glFrontFace GL CCW 26 glEnable GL CULL FACE GL DEPTH TEST 27 28 29 void drawRect NSRect dirtyRect 30 31 static struct 32 33 GLubyte colours 4 34 GLfloat vertices 3 35 36 vertexInfoList 37 255 0 0 255 0 5f 0 5f 1 0f 38 0 255 0 255 0 5f 0 5f 1 0f 39 0 0 255 255 0 5f 0 5f 2 0f 40 255 0 255 255 0 5f 0 5f 2 0f 41 42 43 Drawing code here 44 glClear GL COLOR BUFFER BIT 45 46 glInterleavedArrays GL C4UB V3F 0 vertexInfoList 47 48 glCullFace GL BACK 49 glDrawArrays GL TRIANGLE STRIP 0 4 50 51 glFlush 52 我 们会发现这个形状与调用 glFrustum 的形状完全一样 看上去像个直角梯形 而如果我们将上面 15 到 20 行的代码搬到第 24 行 那么我们将会看到一个接近 于等腰梯形的图形 显然与原来的不符 呵呵 而上述代码中 glMultMatrixf const GLfloat 1 0f 0 0f 0 0f 0 0f 0 0f 1 0f 0 0f 0 0f 0 0f 0 0f 1 5f 1 0f 0 0f 0 0f 2 5f 0 0f 其实就等价于调用 glFrustum 1 0 1 0 1 0 1 0 1 0 5 0 上面那个是与下面 glFrustum 调用相对应的变换矩阵 好 接下去我们准备开始话 3D 图形 上面忘记说了 投影矩阵与模型视图矩阵是分开来的 也就是说 glMatrixMode GL PROJECTION 所指定指定的投影变换矩阵栈与 glMatrixMode GL MODELVIEW 所指定的模型视图变换矩阵栈是相互独立的 而投影变换矩阵变换的最终结果我们设为 P 而 模型视图变换矩阵的最终得出 的变换矩阵我们设为 M 所以上述公式中的 P 和 M 是这么得到的 我们在后序章节中将会介绍对矩阵栈的操作 好 我们下面将谈谈面的朝向 这个对于裁剪背面以及光照都有用 我们知道一张纸有正反两个面 在 OpenGL 中 一个平面可以想像为一张纸 也 有 两个面 如果你没有指定要裁剪掉看不见的反面 那么反面也会被绘制 那 么我们如何确定一个面是朝向哪里呢 这取决于我们的初始设定以及绘制顶点的 顺序 在默认情况下 顶点以逆时针方向绘制出来的方向为正面 顺时针方向绘制出 来的是反面 我们也可以用右手拇指定律来确定面的朝向 函 数 glFrontFace 用于指定是顺时针方向为正面还是逆时针方向为正面 默认 情况下 逆时针方向为正面 函数原型如下 void glFrontFace GLenum mode mode 只有两个值 要么是 GL CW 指定绘制顺序为顺时针 时表示正面 要么是 GL CCW 指定绘制顺序为逆时针方向时为正面 默认为 GL CCW 下面我们将举个绘制立方体的例子 1 void prepareOpenGL 2 3 glShadeModel GL SMOOTH 4 5 glEnable GL CULL FACE 6 glEnable GL DEPTH TEST 7 glEnable GL NORMALIZE 8 9 glClearColor 0 4 0 4 0 4 1 0 10 glViewport 0 0 320 320 11 12 glMatrixMode GL PROJECTION 13 glLoadIdentity 14 glOrtho 1 0 1 0 1 0 1 0 1 0 5 0 15 16 glMatrixMode GL MODELVIEW 17 glLoadIdentity 18 19 glTranslatef 0 0f 0 0f 3 0f 20 glRotatef 10 0f 1 0f 1 0f 1 0f 21 22 glFrontFace GL CCW 23 24 25 void drawRect NSRect dirtyRect 26 27 static const struct 28 29 GLubyte colours 4 30 GLfloat vertices 3 31 32 vertexInfoList 33 255 0 0 255 0 5f 0 5f 0 5f v0 left bottom back 34 0 255 0 255 0 5f 0 5f 0 5f v1 right bottom back 35 0 0 255 255 0 5f 0 5f 0 5f v2 right top back 36 255 0 255 255 0 5f 0 5f 0 5f v3 left top back 37 255 255 0 255 0 5f 0 5f 0 5f v4 left bottom front 38 0 255 255 255 0 5f 0 5f 0 5f v5 right bottom front 39 20 20 20 255 0 5f 0 5f 0 5f v6 right top front 40 255 255 255 255 0 5f

温馨提示

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

评论

0/150

提交评论