opengl笔记(6)

2019-01-26 21:33

0,0,0,0,0,0,0,//没有alpha缓存和累积缓存 32,//32位深度缓存

0,0,//没有模板缓存和辅助缓存 PFD-MAIN-PLANE,//主层类型 0,//保留结构数

0,0,0,//不支持结构数 };

设置像素格式

当初始化PIXELFORMATDESCRIPTOR结构后,就要设置像素格式。下面几段从VC++ 2.0的MFC程序中摘出的代码就是设置像素格式的方式。代码如下: CClientDC clientDC(this);

int pixelFormat=ChoosePixelFormat(clientDC.m_hDC,&pfd);

BOOL result=SetPixelFormat(clientDC.m_hDC,pixelFormat,&pfd); 第一行语句说明得到一个应用窗口客户区的设置描述表。

第二行调用ChoosePixelFormat()选择一个像素格式,并将像素格式索引号返回给pixelFormat变量;函数中第一个参数是选择像素格式的设置描述表的句柄,第二个参数是PIXELFORMATDESCRIPTOR结构的地址。如果调用失败则返回0;否则返回像素格式索引号。

第三行调用SetPixelFormat()设置像素格式,三个参数分别是设备描述表的句柄、像素格式索引号和PIXELFORMATDESCRIPTOR结构的地址。如果调用成功则返回TURE;否则返回FALSE。

gluPerspective和gluLookAt的关系

函数原型

gluLookAt(GLdoble eyex,GLdouble eyey,GLdouble eyez,GLdouble centerx,GLdouble centery,GLdouble centerz,GLdouble upx,GLdouble upy,GLdouble upz);

gluPerspective(GLdouble fovy,GLdouble aspect,GLdouble zNear,GLdouble zFar)

首先得设置gluPerspective,来看看它的参数都表示什么意思

fovy,这个最难理解,我的理解是,眼睛睁开的角度,即,视角的大小,如果设置为0,相当你闭上眼睛了,所以什么也看不到,如果为180,那么可以认为你的视界很广阔,

aspect,这个好理解,就是实际窗口的纵横比,即x/y zNear,这个呢,表示你近处,的裁面, zFar表示远处的裁面,

zNear,眼睛距离近处的距离,假设为10米远,请不要设置为负值 zFar表示远处的裁面,假设为1000米远,

现在来看gluLookAt(GLdoble eyex,GLdouble eyey,GLdouble eyez,GLdouble centerx,GLdouble centery,GLdouble centerz,GLdouble upx,GLdouble upy,GLdouble upz);

它共接受三对坐标, 分别为eye,center,up

故名思义,eye表示我们眼睛在\世界坐标系\中的位置, center表示眼睛\看\的那个点的坐标,

最后那个up坐标表示观察者本身的方向,如果将观察点比喻成我们的眼睛,那么这个up则表示我们是正立还是倒立异或某一个角度在看,所看的影像大不相同,故此时需要指明我们现在正立,那么X,Z轴为0,Y轴为正即可,通常将其设置为1,只要表示一个向上的向量(方向)即可 Opengl流水线

1、模视矩阵(ModelView Matrix)的作用是将模型从局部坐标系变换到世界坐标系,并最终变换到视点坐标系中。它由模型变换矩阵和视点变换矩阵组成。 2、gluLookAt影响的是视点矩阵,它显式的标明了视点坐标系与世界坐标系的关系,即视点被安置在世界坐标系的哪个位置,视线的方向朝向何处。

3、gluPerspective用于规定视景体范围,与模视矩阵无关,它影响的是投影矩阵和规一化矩阵。投影矩阵的作用是使模型产生近大远小的效果,规一化矩阵是将模型的z值规一化到0~1之间。

4、在编程的时候,需要glMatrixMode来指定矩阵堆栈的类型,然后对该矩阵进行修改。

glMatrixMode(GL_MODELVIEW); glLoadIdentity();

的作用是初始化模视矩阵,将坐标原点重新设置在世界坐标系的原点。之后的glTranslate、glScale、glRotate都会改变模视矩阵中的模型变换矩阵。而glLookAt则设置视点变换矩阵。它们共同作用,使得模型能在世界坐标系中正确安放,并能从合适的角度去观察。

glViewport - 设置视口

void glViewport( GLint x,

GLint y,

GLsizei width, GLsizei height) 参数

x,y 指定视口矩形的左下角坐标,单位为像素.缺省值为(0,0). width,height 指定视口矩形的宽度和高度. 说明

glViewport函数指定x和y从单位设备坐标到窗口坐标的转换,令(x_nd,y_nd)为单位设备坐标,那么计算到的窗口坐标(x_w,y_w)为: x_w = (x_nd + 1)[width/2] + x y_x = (y_nd + 1)[height/2] + y

根据实现,视口的宽度和高充被箝位在某一范围,这个范围使用glGet命令,变量为GL_MAX_VIEWPORT_DIMS进行查询.

下列函数用来检索与glViewport相关的信息: glGet,变量为 GL_VIEWPORT.

glGet,变量为 GL_MAX_VIEWPORT_DIMS. 错误

如果width或height的值为负数,则会产生GL_INVALID_VALUE错误;

如果在glBegin和对应的glEnd语句之间调用glViewport函数,则会产生GL_INVALID_OPERATION错误. 缓存的分类 1. 颜色缓存

指程序员绘图所用的缓存,分为:

左、右缓存——用于立体感视图(必须要有左缓存); 前、后缓存——用于双缓存(必须要有前缓存); 4个辅助缓存——可选择的、不可显示(程序员可以自己定义和使用它们)。 2. 深度缓存

用来存储每个象素的深度值,也称为Z缓存。 3. 模板缓存

可以将作图限制在屏幕的某些部分中进行。 4.累积缓存

包含RGBA颜色数据,通常用于将一系列图象累加成一幅最终的合成图象。 象素不能直接绘制到累积缓存中,累加操作常常先在矩形块中进行,然后再与颜色缓存交换数据。 双缓冲技术

在计算机上的动画与实际的动画有些不同:实际的动画都是先画好了,播放的时候直接拿出来显示就行。计算机动画则是画一张,就拿出来一张,再画下一张,再拿出来。如果所需要绘制的图形很简单,那么这样也没什么问题。但一旦图形比较复杂,绘制需要的时间较长,问题就会变得突出。

让我们把计算机想象成一个画图比较快的人,假如他直接在屏幕上画图,而图形比较复杂,则有可能在他只画了某幅图的一半的时候就被观众看到。而后面虽然他把画补全了,但观众的眼睛却又没有反应过来,还停留在原来那个残缺的画面上。也就是说,有时候观众看到完整的图象,有时却又只看到残缺的图象,这样就造成了屏幕的闪烁。

如何解决这一问题呢?我们设想有两块画板,画图的人在旁边画,画好以后把他手里的画板与挂在屏幕上的画板相交换。这样以来,观众就不会看到残缺的画了。这一技术被应用到计算机图形中,称为双缓冲技术。即:在存储器(很有可能是显存)中开辟两块区域,一块作为发送到显示器的数据,一块作为绘画的区域,在适当的时候交换它们。由于交换两块内存区域实际上只需要交换两个指针,这一方法效率非常高,所以被广泛的采用。

注意:虽然绝大多数平台都支持双缓冲技术,但这一技术并不是OpenGL标准中的内容。OpenGL为了保证更好的可移植性,允许在实现时不使用双缓冲技术。当然,我们常用的PC都是支持双缓冲技术的。

深度缓存就好像是屏幕,每一个像素对应一个深度值。将视锥台的近切面到远切面分成n等份,比如深度缓存设为8位,那就分成256份,这256份从0.0到1.0平均分配,就是深度值。一开始你把深度缓存清1.0,表示全部像素都在最远处;然后根据你画物体的位置,求出物体每一点对应的深度值z,再和深度缓存中对应点的深度值(stored Z)比较,如果z <= stored Z(GL_LEQUAL),深度测试通过,就画出来,否则就不画。 这个0.0到1.0,可以用glDepthRange更改。

“深度测试”在绘制三维场景的时候特别有用。在不使用深度测试的时候,如果我们先绘制一个距离较近的物体,再绘制距离较远的物体,则距离远的物体因为

后绘制,会把距离近的物体覆盖掉,这样的效果并不是我们所希望的。

如果使用了深度测试,每当一个像素被绘制,OpenGL就记录这个像素的“深度”(深度可以理解为:该像素距离观察者的距离。深度值越大,表示距离越远),如果有新的像素即将覆盖原来的像素时,深度测试会检查新的深度是否会比原来的深度值小。如果是,则覆盖像素,绘制成功;如果不是,则不会覆盖原来的像素,绘制被取消。这样一来,即使我们先绘制比较近的物体,再绘制比较远的物体,则远的物体也不会覆盖近的物体了。

实际上,只要存在深度缓冲区,无论是否启用深度测试,OpenGL在像素被绘制时都会尝试将深度数据写入到缓冲区内,除非调用了glDepthMask(GL_FALSE)来禁止写入。这些深度数据除了用于常规的测试外,还可以有一些有趣的用途,比如绘制阴影等等。

光栅化是将一个图元转变为一个二维图像的过程。二维图像上每个点都包含了颜色、深度和纹理数据。将该点和相关信息叫做一个片元 坐标系

a 世界坐标系:

通常世界坐标系是一个三维笛卡儿坐标系。它是一个全局坐标系统,一般为右手坐标系。该坐标系主要用于图形场景中的所有图形对象的空间定位、观察者(视点)的位置和视线的定义等等。计算机图形系统中所涉及的其它坐标系基本上都是参照它进行定义的。

b 局部坐标系:

为了几何造型和观察物体方便起见,独立于世界坐标系定义的二维或三维笛卡儿坐标系称为局部坐标系。在局部坐标系中定义的\局部\物体,通过指定局部坐标系在世界坐标系中的方位,利用几何变换,就可以将\局部\定义的物体变换到世界坐标系内,使之升级成为世界坐标系中的物体。

c 观察坐标系:

观察坐标系通常是以视点的位置为原点,通过用户指定的一个向上的观察向量来定义的一个坐标系,缺省为左手坐标系。观察坐标系主要用于从观察者的角度对整个世界坐标系内的图形对象进行观察,以便简化几何物体在视平面(又成为成像面或投影面)的成像的数学演算。

d 视平面(成像面)坐标系:

它是一个二维直角坐标系统,主要用于计算物体在成像面上的投影。一般是通过指定视方向和视点到成像面之间的距离来定义成像面(投影面)。可进一步在投影面上定义一个称之为窗口的矩形区域来实现部分成像。

e 屏幕坐标系:

屏幕坐标系也称为设备坐标系,它主要用于某一特定的计算机图形显示设备(如光栅显示器)的表面的点的定义。在多数情况下,对于每一个具

体的显示设备,都有一个单独的设备坐标系。

在定义了成像窗口的情况下,可进一步在屏幕坐标系统中定义称为视区的有界区域,视区中的成像即为实际所观察到的图形对象。换句话说,在世界坐标系中要显示的区域称为窗口,而显示器上相应的图形输出区域称为视区(或视口)。将世界坐标系中的一部分区域中的场景映射到设备坐标系的过程称为观察变换;将二维观察变换简单地称为窗口到视区的变换,简称为窗视变换。它可以分为以下几个步骤(见图3.1):

图3.1二维观察流程

场景建模=>将世界坐标转换为观察坐标=>窗视变换=>将规范化视区映射到设备坐标

OpenGL 绘图的机制是: 先用 OpenGL 的绘图上下文 Rendering Context (简称为 RC )把图画好,再把所绘结果通过 SwapBuffer() 函数传给 Window 的 绘图上下文 Device Context (简记为 DC).要注意的是,程序运行过程中,可以有多个 DC,但只能有一个 RC。因此当一个 DC 画完图后,要立即释放 RC,以便其它的 DC 也使用。

glFlush:将GL命令队列中的命令发送给显卡并清空命令队列,发送完立即返回;

glFinish:将GL命令队列中的命令发送给显卡并清空命令队列,显卡完成这些命令(也就是画完了)后返回。

因此,在绘图命令比较冗长的情况下,可以分段调用glFlush以清空命令队列并让显卡开始先执行这些命令,最后调用glFinish来同步。举个例子:我的渲染器一共有9种shader,渲染时从shader0一直渲染到shader8,以前是在所有shader渲染完成后才调用glFinish,那么CPU就要等GPU绘图,浪费了大把大把的时间;现在改成每个shader完成后调用一次glFlush,强制GPU开始执行命令队列中的GL命令,最后调用glFinish等待GPU完成当前帧渲染,然后调用wglSwapBuffer调换前后缓存。


opengl笔记(6).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:[精选资料]关于如何培养学生勤俭节约习惯的研究

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: