OpenGL模型视图变换、投影变换、视口变换的理解
OpenGL中不设置模型,投影,视口,所绘制的几何图形的坐标只能是-1到1(X轴向右,Y轴向上,Z轴垂直屏幕向外)。
产生目标场景的过程类似于用照相机进行拍照:
(1)把照相机固定在三角架上,并让他对准场景
从不同位置观察场景(视图变换)
(2)对场景进行安排,使各个物体在照片中的位置是我们所希望的
移动,旋转或者放大缩小场景中的物体(模型变换)
(3)选择照相机镜头,并调整放大倍数(调焦)
显示物体时,可以选择物体是如何投影到屏幕上(投影变换)
(4)确定照片的大小,放大照片还是缩小照片
把图形画下来,是要占据整个屏幕还是屏幕的一部分(视口变换)
OpenGL中的各种转换是通过矩阵运算实现的,具体的说,就是当发出一个转换命令时,该命令会生成一个4X4阶的转换矩阵(OpenGL中的物体坐标一律采用齐次坐标,即(x, y, z, w),故所有变换矩阵都采用4X4矩阵),当前矩阵与这个转换矩阵相乘,从而生成新的当前矩阵。例如,对于顶点坐标v ,转换命令通常在顶点坐标命令之前发出,若当前矩阵为C,转换命令构成的矩阵为M,则发出转换命令后,生成的新的当前矩阵为CM,这个矩阵再乘以顶点坐标v,从而构成新的顶点坐标CMv。上述过程说明,程序中绘制顶点前的最后一个变换命令最先作用于顶点之上。这同时也说明,OpenGL编程中,实际的变换顺序与指定的顺序是相反的。
一、视点变换
void gluLookAt(GLdouble eyex,GLdouble eyey,GLdouble eyez,GLdouble centerx,GLdouble centery,GLdouble upx,GLdouble upy,GLdouble upz);
glTranslate{fd}(TYPE x,TYPE y,TYPE z);
glRotate{fd}(TYPE angle,TYPE x,TYPE,y,TYPE z);
glScale{fd}(TYPE x,TYPE y,TYPE z);
(1)OpenGL透视投影函数有两个
1. 其中函数glFrustum()的原型为:
void glFrustum(;GLdouble left,GLdouble Right,GLdouble bottom,GLdouble top,GLdouble near,GLdouble far);
它创建一个透视视景体。其操作是创建一个透视投影矩阵,并且用这个矩阵乘以当前矩阵。这个函数的参数只定义近裁剪平面的左下角点和右上角点的三维空间坐标,即(left,bottom,-near)和(right,top,-near);最后一个参数far是远裁剪平面的Z负值,其左下角点和右上角点空间坐标由函数根据透视投影原理自动生成。near和far表示离视点的远近,它们总为正值。
2、glPerspective( GLdouble fovy, GLdouble aspect, GLdouble near, GLdouble far)
创建一个表示对称透视视图平截头体的矩阵,并把它与当前矩阵相乘。fovy是YZ平面上视野的角度,范围【0,180】。aspect是这个平截头体的纵横比,也就是宽度除于高度。near和far值分别是观察点与近侧裁剪平面以及远侧裁剪平面的距离(沿Z轴负方向)这两个值都是正的。
正投影的主要函数
1、glOrtho( GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far)
创建一个平行视景体(就是一个长方体空间区域)。实际上这个函数的操作是创建一个正射投影矩阵,并且用这个矩阵乘以当前矩阵。其中近裁剪平面是一个矩形,矩形左下角点三维空间坐标是(left,bottom,-near),右上角点是(right,top,-near);远裁剪平面也是一个矩形,左下角点空间坐标是(left,bottom,-far),右上角点是(right,top,-far)。注意,near和far都是正值。只有在视景体里的物体才能显示出来,我感觉你最后两个参数取得有点问题,而且你改成0,0后,视景体深度没有了,整个视景体都被压成个平面了,当然就显示不正确了。
3、glOrtho2D( GLdouble left, GLdouble right, GLdouble bottom, GLdouble top)
创建一个表示把二维坐标投影到屏幕上的矩阵,并把当前矩阵与它相乘,裁剪区域为矩形。
把像素绘制到屏幕上glViewport()定义视口,前两个参数最左下方,后两个参数宽度和高度。
4、视口变换
在窗口中定义一个像素矩形,最终的图像将映射到这个矩形中。
glViewport( Glint x, Glint y, GLsizei width, GLsizei height );XY指定了视口的左下角,WH指定了视口的高度和宽度。在默认情况下,视口的初始值是(0,0,winwidth,winheight)。
视口的纵横比一般和视景体的纵横比相同。当窗口的大小发生变化时,并不会自动影响视口,应用程序应该检测窗口大小改变事件。
六、矩阵栈的操作
1.模型转换与视点转换:
void glLoadMatrix{fd}(const TYPE *m)
设置当前矩阵中的元素值。函数参数*m是一个指向16个元素(m0, m1, ..., m15)的指针,这16个元素就是当前矩阵M中的元素,其排列方式如下
M = | m0 m4 m8 m12 |
| m1 m5 m9 m13 |
| m2 m6 m10 m14 |
| m3 m7 m11 M15 |
矩阵以列作为主要的排列方式。
2. void glMultMatrix{fd}(const TYPE *m)
用当前矩阵去乘*m所指定的矩阵,并将结果存放于*m中。当前矩阵可以是用glLoadMatrix() 指定的矩阵,也可以是其它矩阵变换函数的综合结果。
该方法用任意矩阵去乘以当前矩阵,该方法不返回任何值。
说明:
The glMultMatrix function multiplies the current matrix by the one specified in m. That is, if M is the current matrix and T is the matrix passed to glMultMatrix, then M is replaced with M • T.
如果M是当前矩阵, T是该方法中的参数指定的矩阵。则该方法调用之后,当前矩阵变为 M = M * T.
The current matrix is the projection matrix, modelview matrix, or texture matrix, determined by the current matrix mode (see glMatrixMode).
The m parameter points to a 4x4 matrix of single-precision or double-precision floating-point values stored in column-major order. That is, the matrix is stored as shown in the following image.
3. glMatrixMode
指定当前矩阵类型:可以设置以下矩阵类型。
| Value | Meaning |
|---|---|
|
Applies subsequent matrix operations to the modelview matrix stack.【模型视图矩阵】 |
|
Applies subsequent matrix operations to the projection matrix stack.【投影矩阵】 |
|
Applies subsequent matrix operations to the texture matrix stack.【纹理矩阵】 |
4.矩阵堆栈操作:glPushMatrix(),glPopMatrix()
说明,OpenGL中有两个最基本的矩阵,模型视景矩阵和投影矩阵,它们都有相应的矩阵堆栈,这些矩阵的当前值就是在矩阵堆栈中的最顶层元素。对于转换操作,发出转换命令后生成的新的当前矩阵就存储在矩阵堆栈中,因此,我们可以利用矩阵堆栈存储当前值,并在需要的时候将当前值弹出堆栈。
举例来说,我们现在需要绘制一个自行车,设置自行车的两个轮子相对于坐标原点是对称的。我们可以这样绘制:将坐标系原点移动到前车轮中心,然后进行绘制,完成后,计算前车轮中心到后车轮中心的距离,并将坐标系原点移动到后车轮中心,再绘制后车轮。显然,这种绘制顺序是不科学的,如果需要绘制更多的对称物体,那么这种计算量会非常大,而且容易产生错误。
这种问题,我们使用矩阵堆栈可以很容易得到解决。在绘制前车轮之前,将当前矩阵保存在矩阵堆栈中,然后将坐标原点移动到前车轮中心,绘制前车轮,绘制结束后,将保存的当前矩阵弹出矩阵堆栈,这时堆栈顶部的矩阵仍为原坐标系,下一步只需相对于原坐标系移动相应距离到后车轮进行绘制,这样,所有物体的位置都是相对于原坐标系进行设置,程序计算量得到缩减,而且不容易出错误。
OpenGL模型视图变换、投影变换、视口变换的理解的更多相关文章
- 简单理解OpenGL模型视图变换
前几天学习了OpenGL的绘图原理(其实就是坐标的不停变换变换),看到网上有个比较好的例程,于是学习了下,并在自己感兴趣的部分做了注释. 首先通过glMatrixMode(GL_MODELVIEW)设 ...
- [计算机图形学]视图变换:MVP变换、视口变换
目录 一.MVP变换 1. 模型变换 1.1 缩放矩阵 1.2 旋转矩阵 1.3 平移矩阵 2. 视角变换 3. 投影变换 二.Viewport变换 一.MVP变换 MVP变换是模型变换(M).视角变 ...
- OpenGL 模型视图投影矩阵 仿射矩阵
矩阵基础知识 要对矩阵进行运算,必须先要了解矩阵的计算公式,这个知识的内容涉及到了线性代数. 我们知道在Cocos2dx中,有关于平移,旋转,缩放等等操作,都必须要进行矩阵的乘法. 只需要一张图就能理 ...
- OpenGL的视图变换、模型变换、投影变换、视口变换
产生目标场景的过程类似于用照相机进行拍照: (1) 把照相机固定在三角架上,并让他对准场景从不同位置观察场景(视图变换) gluLookAt (2) 对场景进行安排,使各个物体在照片中的位置是我们所希 ...
- OpenGl学习笔记3之模型变换、视图变换、投影变换、视口变换介绍
模型变换.视图变换.投影变换.视口变换介绍 opengl中存在四种变换,分别是模型变换,视图变换,投影变换,视口变换.这四种变换是图形渲染的基本操作,实质上这四种变换都是由矩阵乘法表示(这些操作都是由 ...
- WebGL简易教程(五):图形变换(模型、视图、投影变换)
[toc] 1. 概述 通过之前的教程,对WebGL中可编程渲染管线的流程有了一定的认识.但是只有前面的知识还不足以绘制真正的三维场景,可以发现之前我们绘制的点.三角形的坐标都是[-1,1]之间,Z值 ...
- OpenGL学习笔记4——模型视图变换
以日月地为例的一个模型视图变换.绕了比较多的弯路,下面是几个注意点总结. 注意点: 1.GL函数对模型的操作是基于当前局部坐标系,即模型坐标系而非世界坐标系,二者只在第一次初始化完毕之后才重合: 2. ...
- OpenGL(五) 三维变换之模型视图矩阵
计算机三维图形学中,一个基本的任务是如何描述三维空间中一个物体位置的变化,也就是如何 描述物体的运动.通常情况下,物体位置的变化包含三个基本的变化:平移.旋转和缩放,物体的运动也可以用这三个基本的运动 ...
- WebGL或OpenGL关于模型视图投影变换的设置技巧
目录 1. 具体实例 2. 解决方案 1) Cube.html 2) Cube.js 3) 运行结果 3. 详细讲解 1) 模型变换 2) 视图变换 3) 投影变换 4) 模型视图投影矩阵 4. 存在 ...
随机推荐
- iKcamp新书上市《Koa与Node.js开发实战》
内容摘要 Node.js 10已经进入LTS时代!其应用场景已经从脚手架.辅助前端开发(如SSR.PWA等)扩展到API中间层.代理层及专业的后端开发.Node.js在企业Web开发领域也日渐成熟,无 ...
- delphi常用函数和方法
uses ShellApi, ActiveX, ComObj, ShlObj; function HasText(Text: string; const Values: array of strin ...
- pyorient
简介 pyorient是orientdb的python库 该库提供两种访问orientdb的方式:1.client 的方式 2.ogm 的方式(类似于ORM) 由于OGM 封装了client,且由于O ...
- Concurrency and Race Conditions
1.当多个线程访问共享硬件或软件资源的任何时候,由于线程之间可能产生对资源的不一致观察,所以必须显式管理对资源的访问. 2.内核中的并发管理设施: (1). 信号量: P操作将信号量的值减 1 ,判断 ...
- subprocess 粘包问题
1.执行命令: 在py代码中去如何调用操作系统的命令 新模块:subprocess r = subprocess.Popen('ls',shell=True,stdout=subprocess.PIP ...
- [leetcode]349. Intersection of Two Arrays数组交集
Given two arrays, write a function to compute their intersection. Example 1: Input: nums1 = [1,2,2,1 ...
- jmeter 常见问题汇总
文件读取中文乱码: 读取CSV文件,出现中文乱码,纠正方式如下: txt文件乱码 在用到该变量的请求上加上UTF-8 post请求 返回“ Content type 'application/x-ww ...
- linux下memcache安装
安装配置 1. 安装libevent # tar zxf libevent-1.4.6-stable.tar.gz # cd libevent-1.4.6-stable # ./configure # ...
- How to Install and Configure Bind 9 (DNS Server) on Ubuntu / Debian System
by Pradeep Kumar · Published November 19, 2017 · Updated November 19, 2017 DNS or Domain Name System ...
- JAVA Get UUID
UUID是通用唯一标识码(Universally Unique Identifier),通过开源软件基金会(OSF)设立的一种算法生成.它的主要作用就是保证生成的字符串在同一时空中所有机器上都是唯一的 ...
