OpenGL红宝书正序解读二

首先感谢大家对我博客的支持,这篇博客我们重点的解读一下第三章视图的相关概念,本人想在写完这篇博客以后写个代码,囊括第二章第三章的内容
本章视图的目标就是让读者学会,不再使用默认的坐标系和观察点,我们要会自己指定观察的方向和空间中我们要放的物体的位置,同时,我们在把一个三维空间中物体的位置对应到屏幕这种二维面上时,应该怎么做,在这里,给出了一个基本的顺序:
1.包括模型视图投影操作,这三个操作都是由矩阵乘法表示的。
2.裁剪掉裁剪平面之外的物体
3.视口变换,就是让变换的坐标和我们的屏幕像素之间,建立好对应关系

用照相机打比方

之前我们提到了观察方向,这里我们用照相机来做一个比喻,比如我们想拍一张照片,那么我们就要选好角度,这个过程就是视图变换,然后有了好的角度,场景中的物体要怎么摆放呢,这个就是模型变换,然后我们选择了照相机的镜头,调整放大倍数,这个是投影变换,最后我们洗照片,洗多大尺寸的,这个就是视口变换,我们在对顶点操作过程中,视图变换一定要在模型变换之前,在后续你们会看到,这两个其实融为一体了,对于投影和视口变换,可以在绘图之前的任何时候开始。而且绘图我们一般是在上面这四个步骤完成之后才开始的,不要把模型变换当作是绘制图形,只是指定了一个矩阵而已,用于后续我们绘制物体顶点时,进行变换。
对于视图模型投影这三个变换,我们一般会用一个4X4的矩阵来表示,在后面,这些矩阵会和所有绘制的顶点相乘。这个矩阵是放到乘法式子的左边的,大家看好,矩阵的乘法是有顺序的。
在这里选用4*4的矩阵是因为,我们在指定顶点的时候,所有的顶点都是四维的,虽然最后一个大部分情况为0或1(二维和三维),同时,视图和模型变换还会对顶点上的法线产生作用,法线是相对于视觉坐标而言的,这就保证了法线和坐标之间有正确的对应关系。
在这里涉及到了坐标的概念,我会逐步地向大家介绍。
视图和模型变换一起组成了视图模型矩阵,作用于物体坐标,那么最开始,每个物体的初始坐标为物体坐标,与前述矩阵相乘之后,形成的是视觉坐标,视觉坐标是相对于视觉的,所以得在指定视图变换之后才产生视觉坐标。如果此时,有裁剪平面的话,裁剪平面生效。
OpenGL使用投影矩阵对顶点进行变换以后,就产生了裁剪坐标,投影变换定义了一个视景体,视景体之外的空间会被裁剪,紧接着利用透视除法把坐标值除以w,产生规范化的设备坐标,最后经过视口变换,成为窗口坐标。
由于我们绘制的是二维的电脑屏幕,很多人觉得,我们只需要场景中物体的xy坐标即可,但是我们在进行各种变换时,我们的变换也会对物体的z坐标起作用,原因是,我们的z坐标可以表示不同的物体相对于我们照相机的位置,也是深度值,如果遇到了两个物体的遮挡,那么我们可以不绘制被遮挡的物体。

通用的变换函数

首先我们在进行各种变换之前,我们要先明确我们想要修改的是什么矩阵,是模型视图矩阵还是投影矩阵,
我们利用函数glMatrixMode(),来决定我们接下里要修改的矩阵,只有一个参数,是模式值,可以是GL_MODELVIEW,GL_PROJECTION,GL_TEXTURE,一次只能修改一个矩阵,默认情况下,修改的是模型视图矩阵,默认情况三个矩阵都是单位矩阵,在我们利用函数嵌套的调用时,一定记得对矩阵模式进行重置。
函数glLoadIdentity()函数用于将我们现在正在指定的矩阵变成单位矩阵,没有参数。
在这里我们还介绍了两个函数,glLoadMatrix()和glMultMatrix(),函数都是一个指针,指向一个具有十六个值的矩阵,load函数用于把这是十六个值加载到当前矩阵中,mult函数用于把当前矩阵和这十六个值组成的矩阵进行矩阵乘法,这里红宝书明确提出,当前矩阵总是在左边!!!!!!!
认真看书的读者应该有所发现,这里指定的矩阵是列主序的,这与我们c语言的风格截然相反,这里我们使用书中给出的两种方法,是矩阵转置加载和乘法:glLoadTransposeMatrix(),和glMultTransposeMatrix(),这样的话,与我们c语言的思想是完全吻合的。

模型和视图变换

这里的内容比较抽象,就算我用我的话跟大家说明白了,我的话同样抽象,所以我这里不多解释,重点以下几点,这里把模型和视图变换放到一起,原因是因为你不管是移动视角还是移动物体,其实两种方法选其一都是可以做到的,因为位置都是相对的,所以我们一般情况下把模型和视图放到一起讨论,还有一点,我们对于顶点的操作,对于在世界坐标系里,是反序的,对于局部移动坐标系,才是正序的。如果我们不使用默认的视图方式的话,也就是你要用函数来指定,这些函数应该出现在程序里模型变换的前面,这样,我们代码的意思是,我们现在场景里分布好了模型的,之后我们选择在什么位置进行观测。

模型变换

模型变换的函数本书介绍了三个。这三个函数的本质都是,产生一个变化矩阵,然后用这个矩阵为参数调用glMultMatrix*(),而且这样做比直接使用glMultMatrix*()函数速度要快。
glTranslate{fd}()函数参数三个。表示移动。
glRotate{fd}()参数有四个,第一个是旋转的角度,后三个参数表示了一个点,该点和坐标原点形成的线为旋转轴。
glScale{fd}(),参数有三个,分别代表了,拉伸各个轴的倍数,对于局部坐标系,是拉伸的坐标轴,然后里面的物体随之改变。
拉伸函数只有在必要时才使用,因为会改变表面的法线向量,对于光照计算来说,增加了计算成本。

视图变换

最先提到的方法就是利用了运动的相对性,函数就是利用到我们上面讲到的移动和旋转函数。
之后书中提到了一个函数glLookAT()这个函数有九个参数,每三个一组,分别指定了观察点的位置,定义了照相机瞄准的参考点,并提示哪个方向是向上的。
在这里提到了全景扫描的概念,利用glLookAt()实现全景扫描,这里我也不是很懂,希望大家读到这里可以和我讨论。
大家注意:在任何时候,只能有一个视图变换处于活跃状态,我们不能组合两个视图变换的效果,所以我们想使用试图变换的时候,一定要用函数glLoadIdentity()函数,消除之前所做的视图变换。
我们看书过程中应该读到,glLookAt()函数,是一个工具库里的函数,他是一个工具,是以为他封装了glTranslate和glRotate这两个函数,那么如果我们想自定义视图变换函数的话,其实只要在函数体里包含这两个移动和旋转函数即可。具体的书上也没多说,我也不多说哈哈。

投影变换

投影变换区别于模型试图变换,不需要组合其他变换,所以每次我们都要指定投影模式,然后把投影矩阵变成单位矩阵。投影变换的目的是定义一个视景体,有两个作用,第一是说明三维空间的物体是如何映射到屏幕上的,第二是进行裁剪。

透视投影

透视投影是接近我们生活的,就是我们俗称的近大远小,那么我们使用透视投影所用的视景体就是平截头体,距离视点近的,矩形平面小,反之,矩形平面大。我们可以使用glFrustum()函数来指定一个视景体,并且把它与当前矩阵相乘。这个函数有六个参数,大家自己看一下书,每个参数的意义,六个参数就是指定了靠近视点的左下和右上点的坐标,以及前后两个面的距离。这个视景体可以不是对称的,轴也没有要求,而且这个函数可以高分辨率的绘制一幅图像。
除了这个函数,我们还可以使用,gluPerspective()函数,这个函数有四个参数,大家看一下书,四个参数的作用是指定y方向的视野的角度,以及纵横比,还有远近平面的位置,但是这个函数比上面的glFrustum函数要求高一点,我们绘制的函数只能是沿着视线方向的,而且必须是对称xy轴的。而且我刚才查阅资料,视景体和我们的相机可以说是一体的,相机动,视景体也会动。

正投影

正投影是那种用于工业设计领域的,就是物体的大小不会因为距离我们照相机远就变小。所以这个正投影的视景体是一个长方体。我们使用glOrtho()函数来创建一个视景体,参数和glFrustum的参数一样。
这个参数还有一个二维的形式,意义是把一个二维图像投影到二位屏幕。
glOrtho2D()函数有四个参数。指定了一个矩形的左下角坐标和右下角坐标。这个函数假定所有的z值都是-1到1之间。

视口变换

这是我们最后一个步骤,冲洗照片,那么照片要多大的呢,就要用到这个小节的知识。

定义视口

在屏幕上打开窗口的任务不是OpenGL完成的,而是由窗口系统完成的,默认情况下,视口被设置为占据打开窗口的整个像素矩形,我们可以使用glViewPort()函数选择一个更小的绘图区域,还可以对窗口进行划分,显示多个视图。
我们使用函数glViewPort()函数,函数有四个参数,前两个指定视口左下角的坐标,后面两个参数指定视口的宽和高。
这里涉及到了视口和视景体的关系,视口和视景体的纵横比最好相等,这样我们把投影平面的照片洗出来的时候才不会变形,同时,我们改变窗口大小的时候,视口的大小并不会发生改变,所以我们应该在reshape函数里修改视口的大小。

变换深度坐标

深度坐标是在视口变换期间进行编码的,以后存储在深度缓冲区中,我们使用函数glDepthRange()对深度缓冲区的最大值和最小值进行了设定,默认为0-1.这里应用到了深度的知识,我也有点不明白。

操纵矩阵堆栈

模型视图还有投影矩阵,其实都存在于矩阵堆栈里,每次我们进行矩阵的操作,其实都是对堆栈最顶端的矩阵进行的。
书中提到的当前矩阵,都是堆栈最顶端的矩阵,我们可以使用glPushMatrix和glPopMatrix函数来操纵堆栈顶端的矩阵,书中对这两个函数的描述有点晦涩,不过那个里面形容这两个函数的话还是非常形象的,push就是记住自己的位置,pop就是回到原来的位置。
而且我们会在矩阵堆栈的底部压入一个单位矩阵,为了避免重复调用glLoadIdentity()
模型视图矩阵堆栈最多可以有三十二个,投影矩阵堆栈最多有两个,其中一个是用来透视投影,另一个是为了某些特殊的应用程序需要单独打开一个窗口来实现文本提示,由于文本最好选用正投影,所以可以来回切换。

其他裁剪平面

除了我们视景体的六个裁剪平面以外,我们还可以再指定最多六个裁剪平面,我们使用函数glClipPlane,该函数有两个参数,第一个数裁剪平面名,第二个是一个指针。每次使用这个函数时,我们还要使用glEnable(GL_CLIP_PLANEi);i的值可以是0和最大裁剪平面数减一。

逆变换和模拟变换

一般情况下我们是把三维空间里的一个点绘制到二维屏幕上,但是有时我们要这个相反的过程,就是我们点击屏幕上的一个点,可以返回这个点对应的三维空间的位置。我们使用函数glUnProject();(如果深度是默认的0-1),否则我们要用glUnProect4();
glProject与glUnproject相对应,给出一个三维坐标,可以指定二维坐标,这三个函数里的矩阵都是列主序的,我们可以使用glGetDoublev()和glGetIntegerv()来帮助我们,具体的例子见书p111-示例程序3-8.

OpenGL红宝书正序解读(二)相关推荐

  1. OpenGL红宝书正序解读(一)

    OpenGL红宝书正序解读(一) 第一章:OpenGL简介 第二章:状态管理和绘制几何物体 绘图工具箱 清除窗口 指定颜色 强制完成绘图操作 坐标系统工具箱 描述点.直线.多边形 什么是点.直线.多边 ...

  2. OpenGL红宝书的部分学习记录

    我看的OpenGL红宝书为: <OpenGL编程指南>-- 原书第9版 OpenGL Programming Guide – The Official Guide to Learning ...

  3. OpenGL红宝书:第一个渲染程序Triangles常见问题归总

    OpenGL红宝书第八版从shader开始讲起,其实渲染对大多数人来说都是充满吸引力的,但是程序写起来确实比较麻烦,书上面第一示例程序零零散散也弄了好几天.这里写个博客汇总一下,我觉得对所有初学者都有 ...

  4. 游戏开发计算机图形学杂项知识系列:OpenGL红宝书中第一个渲染程序Triangles常见问题归总

    游戏开发计算机图形学杂项知识系列:OpenGL红宝书中第一个渲染程序Triangles常见问题归总 声明:未经作者允许,严禁商用,转载请标明出处和来源,谢谢 转载自:https://www.cnblo ...

  5. VS2012通过makefile编译OpenGL红宝书的示例代码

    通过创建新VC项目,然后设置一堆属性,对于懒人来说还是太复杂了.既然它自带了makefile,可以尝试下使用nmake. 需要注意的是VS2012的安装目录里面已经没有GL的头文件和库文件.这个改动应 ...

  6. OpenGL红宝书第九版环境配置

    OpenGL红宝书第九版环境配置(VS2017) 对于很多想要学OpenGL的人来说,环境配置一直是一个大问题,笔者就是其中之一.虽然网络上有许多教程,但是由于不同的教程使用的库并不同,利用这些教程配 ...

  7. 关于在vs2013中配置opengl红宝书第八版环境

    转自 http://blog.csdn.net/qq821869798/article/details/45247241 本人刚开始学习opengl,买了一本opengl红宝书第八版, 第一个例子研究 ...

  8. Mac上OpenGL红宝书例程环境适配

    参考:OpenGL编程指南第8版(红宝书) 参考:https://github.com/badousuan/openGLredBook9th (Owed by: 春夜喜雨 http://blog.cs ...

  9. OpenGL红宝书学习(1、概述)

    OpenGL简介 OpenGL 全称Open Graphics Library,一种用于渲染2D.3D矢量图形的跨语言.跨平台的应用程序编程接口(API).由1992年成立的OpenGL架构评审委员会 ...

  10. OpenGL红宝书8th第一个例子triangles

    年初用Qt涉及过OpenGL,当时只根据Qt自给的库使用,按照Qt给的例子没有出现啥问题,但是最近接触计算机图形学,尝试编译红宝书8th(<OpenGL编程指南>(原书第8版)中文版)第一 ...

最新文章

  1. Linux中screen的用法
  2. 【Python CheckiO 题解】Speech Module
  3. python是后端语言还是前端语言_从前端到后台-语言选择
  4. Python基础----元组
  5. python调用excel的宏_Python – 运行Excel宏
  6. 特殊用途的IP地址介绍
  7. 《R语言数据挖掘:实用项目解析》——1.9 循环原理——repeat循环
  8. ELK logstash gork匹配在线测试
  9. 中科方德桌面操作系统_国产操作系统——中科方德桌面操作系统,USB无线网卡配置...
  10. 学习笔记之30个常用的maven命令
  11. Java爬携程_Java数据爬取——爬取携程酒店数据(二)
  12. 寻找反素数python
  13. Java基础——【双色球案例】判断中奖情况
  14. 阿里巴巴校招内推一面总结
  15. combo 技术简单介绍
  16. linux电脑开机慢,Ubuntu 启动速度慢的解决方法
  17. 博弈论大作战之 PART1
  18. MySql ocp认证之备份与恢复(四)
  19. 回顾过去,才能展望未来
  20. 2021 CSC加拿大出国签证、贴签、机票申请材料汇总

热门文章

  1. word中尾注分隔符删除后还有一个回车符怎么删
  2. C++对象模型探索视频课程
  3. w7计算机不显示移动硬盘,Win7移动硬盘在电脑上不显示盘符的解决办法
  4. c语言中四种简单的数组排序
  5. 【02.06-02.13】长赢计划主理人“ETF拯救世界”微博精选
  6. mysql数据库商户与买家_基于mysql实现离我最近的商家列表
  7. linux查找文件重复项,Linux中如何使用命令查找重复文件
  8. c语言内存不能为written,该内存不能为written的解决方法 has written 和wrote的区别
  9. 【转载】网站域名备案相关流程介绍
  10. 网站备案需要买服务器吗,域名备案需要购买服务器吗