OpenGL三维图形编程技术(转)

人们对三维图形技术的研究已经经历了一个很长的历程,而且涌现了许多三维图形开发工具,其中SGI公司推出的GL(Graphics Library)三维图形库表现尤为突出,它易于使用且功能强大。随着计算机技术的迅速发展,GL已经进一步发展成为OpenGL,现在OpenGL被认为是高性能图形和交互式视景处理的标准。


OpenGL(即开放性图形库Open Graphics Library),是一个三维的计算机图形和模型库,最初是美国SGI公司为图形工作站开发的一种功能强大的三维图形机制(或者说是一种图形标准)。它源于SGI公司为其图形工作站开发的IRIS GL,在跨平台移植过程中发展成为OpenGL。SGI在1992年7月发布1.0版,后成为工业标准,由成立于1992年的独立财团OpenGL Architecture Review Board (AR控制。SGI等ARB成员以投票方式产生标准,并制成规范文档(Specification)公布,各软硬件厂商据此开发自己系统上的实现。只有通过了ARB规范全部测试的实现才能称为OpenGL。1995年12月ARB批准了1.1版本,最新版规范是1999年5月通过的1.2.1。

OpenGL被设计成独立于硬件,独立于窗口系统,在运行各种操作系统的各种计算机上都可用,并能在网络环境下以客户/服务器模式工作,是专业图形处理、科学计算等高端应用领域的标准图形库。它低端应用上的主要竞争对手是MS-Direct3D,该图形库是以COM接口形式提供的,所以极为复杂,稳定性差,另外微软公司拥有该库版权,目前只在Windows平台上可用。Direct3D的优势在速度上,但现在低价显卡都能提供很好的OpenGL硬件加速,所以做3D图形开发使用Direct3D已没有特别的必要,在专业图形处理特别是高端应用方面目前还没有出现以Direct3D技术为基础的例子,而游戏等低端应用也有转向OpenGL的趋势。

微软在Windows NT对OpenGL的支持始于3.51,在Windows9x中的支持始于Win95 OEM Service Release 2。Windows下常用的OpenGL库有两种,MS实现的和SGI实现的,MS-OpenGL调用会自动检测是否存在显示卡制造商提供的ICD(Installable Client DeviceDriver)驱动程序,有则调用ICD中的例程,否则使用CPU进行计算,所以能利用显示卡的OpenGL加速能力。对开发者来说使用方法并没有区别,只是有ICD驱动时更快些。SGI的版本是纯软件实现,不能利用硬件加速并且SGI已经在1999年宣布停止支持,但这套图形库便于调试程序,仍有不少开发者使用。

近日SGI宣布与Intel联手针对当前及未来IA体系的Internet流化SIMD扩展优化OpenGL。这显然意味着OpenGL未来在intel体系及internet应用领域将大放光彩。

SGI曾经宣布研发OpenGL++,该图形库最大的特点是面向对象,提供了树形场景支持,大大节省了使用OpenGL处理复杂场景的工作量。1999年SGI宣布与MS合作开发Ferihant,即Windows的下一代图形处理体系,包括DirectX与OpenGL的低级图形处理接口和以场景图支持为特点的高级接口,并且就此停止对其在Windows下的OpenGL实现的支持以示决心。此举令世人瞩目,大家都以为Windows图形处理快要过上幸福生活了,然而,不久,SGI宣布中止合作,并撤回派出的科学家,Ferihant基本上夭折。SGI 称终止合作的原因是MS不肯积极合作,光想把SGI 的技术合并进DirectX,但是真正内幕不详。不过以SGI在图形处理界的老大地位来说,还是有几分可信度的,因为MS最初支持OpenGL就不积极。

利用OpenGL可以创作出具有照片质量的、独立于窗口系统(Windowing System)、操作系统(Operating System)和硬件平台的三维彩色图形和动画。OpenGL的核心库包括100多个用于3D图形操作的函数,主要负责处理对象外形描述、矩阵变换、灯光处理、着色、材质等和三维图形图像密切相关的事情。OpenGL工具库所包含的辅助函数是OpenGL基本函数的补充。这些函数的功能相对高级,可以用于处理坐标变换、错误处理、绘制球体、锥体、柱体、曲线、曲面等图形实体。

计算机硬件性能的提高和OpenGL本身的不断发展,使得OpenGL不再只属于专用图形工作站。如今,开发人员可以在各种硬件平台利用OpenGL进行图形软件开发。

OpenGL可以运行在当前各种流行操作系统之上,如Mac OS、Unix、Windows 95/98、Windows NT/2000、Linux、OPENStep、Python、BeOS等。各种流行的编程语言都可以调用OpenGL中的库函数,如C、C++、Fortran、Ada、Java。OpenGL完全独立于各种网络协议和网络拓扑结构。目前,Microsoft公司、SGI公司、ATT公司的Unix软件实验室、IBM公司、DEC公司、SUN公司、HP公司等几家在计算机市场占主导地位的大公司都采用了OpenGL图形标准。值得一提的是,由于Microsoft公司在Windows NT和Windows 95/98中提供OpenGL标准,使得OpenGL在微机中得到了广泛应用。尤其是在OpenGL三维图形加速卡和微机图形工作站推出后,人们可以在微机上实现CAD设计、仿真模拟、三维游戏等,从而使得应用OpenGL及其应用软件来创建三维图形变得更有机会、更为方便。

二、OpenGL的基本特点

在计算机发展初期,人们就开始从事计算机图形的开发,但直到20世纪80年代末、90年代初,三维图形才开始迅速发展。于是各种三维图形工具软件包相继推出,如GL,RenderMan等。这些三维图形工具软件包有些侧重于使用方便,有些侧重于绘制效果或与应用软件的连接,但没有一种软件包能在交互式三维图形建模能力和编程方便程度上与OpenGL相比拟。

OpenGL作为一个性能优越的图形应用程序设计界面(API),适用于广泛的计算机环境。从个人计算机到工作站和超级计算机,OpenGL都能实现高性能的三维图形功能。由于许多在计算机界具有领导地位的计算机公司纷纷采用OpenGL作为三维图形应用程序设计界面,所以OpenGL应用程序具有广泛的移植性。因此,OpenGL已成为目前的三维图形开发标准,是从事三维图形开发工作的技术人员所必须掌握的开发工具。
OpenGL应用领域十分宽广,如军事、电视广播、CAD/CAM/CAE、娱乐、艺术造型、医疗影像、虚拟世界等。它具有以下特点:

l 工业标准
OARB(OpenGL Architecture Review Board)联合会领导OpenGL技术规范的发展,OpenGL有广泛的支持,它是业界唯一的真正开发的、跨平台的图形标准。

2 可靠度高
利用OpenGL技术开发的应用图形软件与硬件无关,只要硬件支持OpenGL API标准就行了,也就是说,OpenGL应用可以运行在支持OpenGL API标准的任何硬件上。

3 可扩展性
OpenGL是低级的图形API,它具有充分的可扩展性。如今,许多OpenGL开发商在OpenGL核心技术规范的基础上,增强了许多图形绘制功能,从而使OpenGL能紧跟最新硬件发展和计算机图形绘制算法的发展。对于硬件特性的升级可以体现在OpenGL扩展机制以及OpenGL API中,一个成功的OpenGL扩展会被融入在未来的OpenGL版本之中。

4 可伸缩性
基于OpenGL API的图形应用程序可以运行在许多系统上,包括各种用户电子设备、PC、工作站以及超级计算机。

5 容易使用
OpenGL的核心图形函数功能强大,带有很多可选参数,这使得源程序显得非常紧凑;OpenGL可以利用已有的其它格式的数据源进行三维物体建模,大大提高了软件开发效率;采用OpenGL技术,开发人员几乎可以不用了解硬件的相关细节,便可以利用OpenGL开发照片质量的图形应用程序。

6 灵活性
尽管OpenGL有一套独特的图形处理标准,但各平台开发商可以自由地开发适合于各自系统的OpenGL执行实例。在这些实例中,OpenGL功能可由特定的硬件实现,也可用纯软件例程实现,或者以软硬件结合的方式实现。

客观世界和各种事物的形状虽然千变万化,但用计算机将之描述出来却只需要把一系列基本操作组合起来。
OpenGL提供了以下基本操作:

l 绘制物体
真实世界里的任何物体都可以在计算机中用简单的点、线、多边形来描述。OpenGL提供了丰富的基本图元绘制命令,从而可以方便地绘制物体。

2 变换
可以说,无论多复杂的图形都是由基本图元组成并经过一系列变换来实现的。OpenGL提供了一系列基本的变换,如取景变换、模型变换、投影变换及视口变换。

3 光照处理
正如自然界不可缺少光一样,绘制有真实感的三维物体必须做光照处理。

4 着色
OpenGL提供了两种物体着色模式,一种是RGBA颜色模式,另一种是颜色索引模式。

5 反走样
在OpenGL绘制图形过程中,由于使用的是位图,所以绘制出的图像的边缘会出现锯齿形状,称为走样。为了消除这种缺陷,OpenGL提供了点、线、多边形的反走样技术。

6 融合
为了使三维图形更加具有真实感,经常需要处理半透明或透明的物体图像,这就需要用到融合技术。

7 雾化
正如自然界中存在烟雾一样,OpenGL提供了"fog"的基本操作来达到对场景进行雾化的效果。

8 位图和图像
在图形绘制过程中,位图和图像是非常重要的一个方面。OpenGL提供了一系列函数来实现位图和图像的操作。

9 纹理映射
在计算机图形学中,把包含颜色、alpha值、亮度等数据的矩形数组称为纹理。而纹理映射可以理解为将纹理粘贴在所绘制的三维模型表面,以使三维图形显得更生动。

l0 动画
出色的动画效果是OpenGL的一大特色,OpenGL提供了双缓存区技术来实现动画绘制。

OpenGL并没有提供三维模型的高级命令,它也是通过基本的几何图元--点、线及多边形来建立三维模型的。目前,有许多优秀的三维图形软件(如3DMAX)可以较方便地建立物体模型,但又难以对建立的模型进行控制,若把这些模型转化为OpenGL程序,则可随心所欲地控制这些模型来制作三维动画,实现仿真数据的可视化和虚拟现实。

三、讲 OpenGL体系结构

  OpenGL是一套图形标准,它严格按照计算机图形学原理设计而成,符合光学和视觉原理,非常适合可视化仿真系统。

首先,在OpenGL中允许视景对象用图形方式表达,如由物体表面顶点坐标集合构成的几何模型,这类图形数据含有丰富的几何信息,得到的仿真图像能充分表达出其形体特征;而且在OpenGL中有针对三维坐标表示的顶点的几何变换,通过该变换可使顶点在三维空间内进行平移和旋转,对于由顶点的集合表达的物体则可以实现其在空间的各种运动。

其次,OpenGL通过光照处理能表达出物体的三维特性,其光照模型是整体光照模型,它把顶点到光源的距离、顶点到光源的方向向量以及顶点到视点的方向向量等参数代入该模型,计算顶点颜色。因此,可视化仿真图像的颜色体现着物体与视点以及光源之间的空间位置关系,具有很强的三维效果。

另外,为弥补图形方法难于生成复杂自然背景的不足,OpenGL提供了对图像数据的使用方法,即直接对图像数据读、写和拷贝,或者把图像数据定义为纹理与图形方法结合在一起生成视景图像以增强效果。为增强计算机系统三维图形的运算能力,有关厂家已研制出了专门对OpenGL进行加速的三维图形加速卡,其效果可与图形工作站相媲美。
一个完整的窗口系统的OpenGL图形处理系统的结构为:最底层为图形硬件,第二层为操作系统,第三层为窗口系统,第四层为OpenGL,第五层为应用软件。见图1.1所示。


图1.1 OpenGL图形处理系统的层次结构

OpenGL是网络透明的,在客户机/服务器体系结构中,允许本地或远程调用OpenGL。所以在网络系统中,OpenGL在X窗口、Windows或其它窗口系统下都可以以一个独立的图形窗口出现。
由于OpenGL是一个与平台无关的三维图形接口,操作系统必须提供像素格式管理和渲染环境管理。下面以Windows NT操作系统为例具体介绍OpenGL运行的体系结构。
OpenGL在Windows NT上的实现是基于Client/Server模式的,应用程序发出OpenGL命令,由动态链接库OpenGL32.DLL接收和打包后,发送到服务器端的WINSRV.DLL,然后由它通过DDI层发往视频显示驱动程序。如果系统安装了硬件加速器,则由硬件相关的DDI来处理。
OpenGL/NT的体系结构图如图1.2所示。
从程序员的角度看,在编写基于Windows的OpenGL应用程序之前必须清除两个障碍,一个是OpenGL本身是一个复杂的系统,这可以通过简化的OpenGL辅助库函数来学习和掌握;另一个是必须清楚地了解和掌握Windows与OpenGL的接口。


图1.2 OpenGL/NT体系结构

1.3.2 渲染上下文(RC)
OpenGL的绘图方式与Windows的一般的绘图方式是不同的,其区别主要表现在以下三个方面:
(1) Windows采用的是GDI绘图;
(2) OpenGL采用的是渲染上下文RC(Render Context,又称渲染描述表)绘图;
(3) OpenGL使用的是特殊的像素格式。
在Windows中使用GDI绘图时必须指定在哪个设备上下文(Device Context,又称设备描述表)中绘制,同样地,在使用OpenGL函数时也必须指定一个所谓的渲染上下文。正如设备上下文DC要存储GDI的绘制环境信息如笔、刷和字体等,渲染上下文RC也必须存储OpenGL所需的渲染信息如像素格式等。
渲染上下文主要由以下六个wgl函数来管理,下面分别对其进行介绍。
l HGLRC wglCreateContext(HDC hdc)
该函数用来创建一个OpenGL可用的渲染上下文RC。Hdc必须是一个合法的支持至少16色的屏幕设备描述表DC或内存设备描述表的句柄。该函数在调用之前,设备描述表必须设置好适当的像素格式。成功创建渲染上下文之后,hdc可以被释放或删除。函数返回NULL值表示失败,否则返回值为渲染上下文的句柄。
2 BOOL wglDeleteContext(HGLRC hglrc)
该函数删除一个RC。一般应用程序在删除RC之前,应使它成为非现行RC。不过,删除一个现行RC也是可以的。此时,OpenGL系统冲掉等待的绘图命令并使之成为非现行RC,然后删除之。注意在试图删除一个属于别的线程的RC时会导致失败。
3 HGLRC wglGetCurrentContext(void)
该函数返回线程的现行RC,如果线程无现行RC则返回NULL。
4 HDC wglGetCurrentDC(void)
该函数返回与线程现行RC关联的DC,如果线程无现行RC则返回NULL。
5 BOOL wglMakeCurrent(HDC hdc, HGLRC hglrc)
该函数把hdc和hglrc关联起来,并使hglrc成为调用线程的现行RC。如果传给hglrc的值为NULL,则函数解除关联,并置线程的现行RC为非现行RC,此时忽略hdc参数。
传给该函数的hdc可以不是调用wglCreateContext时使用的值,但是,它们所关联的设备必须相同并且拥有相同的像素格式。注意,如果hglrc是另一个线程的现行RC,则调用失败。
6 BOOL wglUseFontBitmaps(HDC hdc, DWORD dwFirst, DWORD dwCount, DWORD dwBase)
该函数使用hdc的当前字体,创建一系列指定范围字符的显示表。可以利用这些显示表在OpenGL窗口画GDI文本。如果OpenGL窗口是双缓冲的,那么这是往后缓冲区中画GDI文本的唯一途径。
一般地,在使用单个RC的应用程序中,在相应WM_CREATE消息时创建RC,当WM_CLOSE或WM_DESTROY到来时再删除它。在使用OpenGL命令往窗口中绘图之前,必须先建立一个RC,并使之成为现行RC。OpenGL命令无需提供RC,它将自动使用现行RC。若无现行RC,OpenGL将简单地忽略所有的绘图命令。
一个RC是指现行RC,这是针对调用线程而言的。一个线程在拥有现行RC进行绘图时,别的线程将无法同时绘图。一个线程一次只能拥有一个现行RC,但是可以拥有多个RC;一个RC也可以由多个线程共享,但是它每次只能在一个线程中是现行RC。
在使用现行RC时,不应该释放或者删除与之关联的DC。如果应用程序在整个生命期内保持一个现行RC,则应用程序也一直占有一个DC资源。注意,Windows系统只有有限的DC资源。
下面介绍两种管理RC与DC的方法。
方法一:RC由WM_CREATE消息响应时创建,创建后立即释放DC;当WM_PAINT消息到来时,程序再获取DC句柄,并与RC关联起来,绘图完成后,立即解除RC与DC的关联,并释放DC;当WM_DESTROY消息到来时,程序只需简单地删除RC即可。如图1.3所示。


图1.3 RC与DC的管理方法一

方法二:RC在程序开始时创建并使之成为现行RC。它将保持为现行RC直至程序结束。相应地,GetDC在程序开始时调用,ReleaseDC在程序结束时才调用。此种方法的好处是在响应WM_PAINT消息时,无需调用十分耗时的wglMakeCurrent函数,一般它要消耗几千个时钟周期。如图1.4所示。
如果应用程序需要使用动画或实时图形,建立采用第二种方法。


图1.4 RC与DC的管理方法二

四、OpenGL像素格式管理

1、Windows下的调色板
OpenGL可以使用16色、256色、64K和16M真彩色。真彩模式下不需要调色板,而在16色模式下根本不可能得到较为满意的效果,因此对OpenGL而言,调色板只有在256色模式下才有意义。
我们知道,Windows把调色板分为系统调色板和逻辑调色板。每个应用程序都拥有一套自己的逻辑调色板(或使用缺省调色板),当该应用程序拥有键盘输入焦点时可以最多使用从16M种色彩中选取的256种颜色(20种系统保留颜色和236种自由选取的颜色),而失去焦点的应用程序可能会有某些颜色显示不正常。系统调色板由Windows内核来管理,它是由系统保留的20种颜色和经仲裁后各个应用程序设置的颜色组成,并与硬件的256个调色板相对应。应用程序的逻辑调色板与硬件的调色板没有直接的对应关系,而是按照最小误差的原则映射到系统调色板中,因此即使应用程序自由选取256种不同颜色构成自己的逻辑调色板,也有可能某些颜色显示到屏幕上时是一样的。
当应用程序的窗口接收到键盘输入焦点时,Windows会向它发送一条WM_QUERYNEWPALETTE消息,让它设置自己的逻辑调色板,此时Windows会在系统调色板中尽量多地加入该应用程序需要的颜色,并生成相应的映射关系。接着Windows会向系统中所有的覆盖型窗口和顶级窗口(包括拥有键盘输入焦点的窗口)发送一条WM_PALETTECHANGED消息,让它们设置逻辑调色板和重绘客户区,以便能更充分地利用系统调色板,已拥有键盘输入焦点的窗口不应再处理这条消息,以避免出现死循环。
2、OpenGL的颜色表示与转换
OpenGL内部用浮点数来表示和处理颜色,红绿蓝和Alpha值这四种成份每种的最大值为1.0,最小值为0.0。在256色模式下,OpenGL把一个像素颜色的内部值按线性关系转换为8比特(Bit)来输出到屏幕上,其中红色占最低位的3比特,绿色占中间的3比特,蓝色占最高位的2比特,Windows将这个8比特值看作逻辑调色板的索引值。例如OpenGL的颜色值(1.0,0.14,0.6667)经过转换后二进制值为10001111(红色为111,绿色为001,蓝色为10),即第143号调色板,该调色板指定的颜色的RGB值应与(1.0,0.14,0.6667)有相同的比率,为(255,36,170),如果不是该值,那么显示出来的颜色就会有误差。
3、调色板的生成算法
很明显,OpenGL输出的8比特值中直接表明了颜色的组成,为了使图形显示正常,我们应以线性关系来设置逻辑调色板,使其索引值直接表明颜色的组成。因此生成调色板时,把索引值从低位到高位分成3-3-2共三个部分,将每一部分映射到0-255中去,这样3比特映射为{0,36,73,109,146,182,219,255},2比特映射为{0,85,170,255},最后把三部分组合起来成为一种颜色。
经过上面的处理后,256种颜色均匀分布在颜色空间中,并没有完全包含系统保留的20种颜色(只包含了7种),这意味着将会有数种颜色显示成一样,从而影响效果。一个较好的解决办法是按照最小均方误差的原则把13种系统颜色纳入到逻辑调色板中。
从原理上来说,并非一定要使用线性映射,还可以用其它一些映射关系,如加入Gamma校正以便更能符合人眼的视觉特性,不过这些映射关系应用得并不广泛,在此不再讨论。
1.3.4 像素格式设置
像素格式是OpenGL窗口的重要属性,它包括是否使用双缓冲,颜色位数和类型以及深度位数等。像素格式可由Windows系统定义的所谓像素格式描述子结构来定义(PIXELFORMATDESCRIPTOR),该结构定义在windows.h中。
在该结构中包含有26个属性信息,其形式为:
typedef struct tagPIXELFORMATDESCRIPTOR
{
WORD nSize;
WORD nVersion;
DWORD dwFlags;
BYTE iPixelType;
BYTE cColorBits;
BYTE cRedBits;
BYTE cRedShift;
BYTE cGreenBits;
BYTE cGreenShift;
BYTE cBlueBits;
BYTE cBlueShift;
BYTE cAlphaBits;
BYTE cAlphaShift;
BYTE cAccumBits;
BYTE cAccumRedBits;
BYTE cAccumGreenBits;
BYTE cAccumBlueBits;
BYTE cAccumAlphaBits;
BYTE cDepthBits;
BYTE cStencilBits;
BYTE cAuxBuffers;
BYTE iLayerType;
BYTE bReserved;
DWORD dwLayerMask;
DWORD dwVisibleMask;
DWORD dwDamageMask;
} PIXELFORMATDESCRIPTOR;
各变量的含义如下:
nSize:该结构所占内存空间。
nVersion:版本号,当前为1。
dwFlags:指定像素格式属性,可选参量如表1.1所示。


表1.1 像素格式属性

标识符 解释
PFD_DRAW_TO_BITMAP 支持内存中绘制位图
PFD_DRAW_TO_WINDOW 支持屏幕绘图
PFD_DOUBLEBUFFER 支持双缓冲
PFD_CENERIC_FORMAT 指定选择GDI支持的像素格式
PFD_NEED_PALETTE 指定需要逻辑调色板
PFD_NEED_SYSTEM_PALETTE 指定需要硬件调色板
PFD_STEREO NT不支持
PFD_SUPPORT_OPENGL 支持OpenGL
PFD_SUPPORT_GDI 支持GDI,此时不可使用PFD_DOUBLEBUFFER
iPixelType:像素颜色模式,可选项为PFD_TYPE_RGBA或PFD_TYPE_INDEX,分别对应于RGBA模式和颜色索引模式。
cColorBits:指定颜色的位数。
cRedBits:采用RGBA模式时,红色组分占用位数。
cRedShift:采用RGBA模式时,红色组分偏移量。
cGreenBits:采用RGBA模式时,绿色组分占用位数。
cGreenShift:采用RGBA模式时,绿色组分偏移量。
cBlueBits:采用RGBA模式时,蓝色组分占用位数。
cBlueShift: 采用RGBA模式时,蓝色组分偏移量。
cAlphaBits:采用RGBA模式时,Alpha组分占用位数。
cAlphaShift:采用RGBA模式时,Alpha组分偏移量。
cAccumBits:指定累积缓冲区表示一个像素所用位数。
cAccumRedBits:指定累积缓冲区表示红色组分占用位数。
cAccumGreenBits:指定累积缓冲区表示绿色组分占用位数。
cAccumBlueBits:指定累积缓冲区表示蓝色组分占用位数。
cAccumAlphaBits:指定累积缓冲区表示Alpha组分占用位数。
cDepthBits:指定深度缓冲区表示一个像素所用位数。
cStencilBits:指定模板缓冲区表示一个像素所用位数。
cAuxBuffers:指定辅助缓冲区,Windows9x、NT不支持。
iLayerType:Windows9x、NT下只能是PFD_MAIN_PLANE。
bReserved:=0。
dwLayerMask:指定覆盖层的屏蔽,Windows9x、NT不支持。
dwVisibleMask:Windows9x、NT不支持。
dwDamageMask:Windows9x、NT不支持。
Windows提供了四个像素格式管理函数,分别介绍如下:

(1) int ChoosePixelFormat(HDC hdc,
PIXELFORMATDESCRIPTOR *ppdf)
该函数比较传过来的像素格式描述和OpenGL支持的像素格式,返回一个最佳匹配的像素格式索引。该索引值可传给SetPixelFormat为DC设置像素格式。返回值为0表示失败。
在比较像素格式时,匹配优先级顺序为像素格式描述子结构中的下述各域:
dwFlags->cColorBits->cAlphaBits->cAccumBits
->cDepthBits->cStencilBits->cAuxBuffers->iLayerType
硬件支持的像素格式优先。
(2) int DescribePixelFormat(HDC hdc, int iPixelFormat, UINT nBytes,
LPPIXELFORMATDESCRIPTOR *ppfd)
该函数用格式索引iPixelFormat说明的像素格式来填写由ppfd所指向的像素格式描述子结构,利用该函数可以枚举像素格式。
(3) int GetPixelFormat(HDC hdc)
该函数用于获取hdc的格式索引。
(4) BOOL SetPixelFormat(HDC hdc, int iPixelFormat,
LPPIXELFORMATDESCRIPTOR *ppfd)
该函数用格式索引iPixelFormat来设置hdc的像素格式。在使用该函数之前应该调用ChoosePixelFormat来获取像素格式索引。另外,OpenGL窗口风格必须包含WS_CLIPCHILDREN和WS_CLIPSIBLINGS类型,否则设置失败。
应该注意的是ChoosePixelFormat函数并不一定返回一个最佳的像素格式值,可以利用DescribePixelFormat来枚举系统所支持的所有像素格式。OpenGL的通常支持24种不同的像素格式,如果系统安装了OpenGL硬件加速器,它可能会支持其它的像素格式。
设置DC的像素格式的步骤如图1.5所示。


图1.5 设置像素格式的一般步骤

五、OpenGL的工作流程

OpenGL的工作流程如图1.6。



图1.6 OpenGL的工作流程

1. 几何操作
(1) 针对每个顶点的操作
每个顶点的空间坐标需要经过模型取景矩阵变换、法向矢量矩阵变换,若允许纹理自动生成,则由变换后的顶点坐标所生成的新纹理坐标替代原有的纹理坐标,再经过当前纹理矩阵变换,传递到几何要素装配步骤。
(2) 几何要素装配
不同的几何要素类型决定采取不同的几何要素装配方式。若使用平直明暗处理,线或多边形的所有顶点颜色则相同;若使用裁剪平面,裁剪后的每个顶点的空间坐标由投影矩阵进行变换,再由标准取景平面进行裁剪,再进行视口和深度变换操作。如果几何要素是多边形,还要做剔除检验,最后生成点图案、线宽、点尺寸的像素段,并赋上颜色、深度值。
2. 像素操作
由主机读入的像素首先解压缩成适当的组份数目,然后进行数据放大、偏置,并经过像素映射处理,根据数据类型限制在适当的取值范围内,像素最后写入纹理内存,使用纹理映射或光栅化生成像素段;如果像素数据由帧缓冲区读入,则执行放大、偏置、映射、调整等像素操作,再以适当的格式压缩。像素拷贝操作相当于解压缩和传输操作的组合,只是压缩和解压缩不是必须的,数据写入帧缓冲区前的传输操作只发生一次。
3. 像素段操作
当使用纹理映射时,每个像素段将产生纹素,再进行雾效果计算、反走样处理。接着进行裁剪处理、一致性检验(只在RGBA模式下使用)、模板检验、深度缓冲区检验和抖动处理。若采用颜色索引模式,像素还要进行逻辑操作;在RGBA模式下则进行混合操作。
根据着色模式不同,决定像素段采取颜色屏蔽还是指数屏蔽,屏蔽操作之后的像素段将写入到适当的帧缓冲区。如果像素写入模板或深度缓冲区,则进行模板和深度检验屏蔽,而不用执行混合、抖动和逻辑操作。
对于创建一个三维图形的基本步骤,大致可以包括以下三个主要环节:
(1)建模:包括几何建模和行为建模,几何建模处理物体的几何和形状的表示,行为建模处理物体的运动和行为的描述;
(2)设置视点:描述观察者的空间位置;
(3)设置环境:描述环境的特征,如:光源、空气能见度等。
OpenGL的绘制过程多种多样,内容非常丰富,主要提供以下几种对三维物体的绘制方式:
(1) 线框绘制方式(Wire frame):绘制三维物体的网格轮廓线。
(2) 深度优先线框绘制方式(Depth cued):采用线框方式绘图,使远处的物体比近处的物体暗一些,以模拟人眼看物体的效果。
(3) 反走样线框绘制方式(Antialiased):采用线框方式绘图,绘制时采用反走样技术,以减少图形线条的参差不齐。
(4) 平面明暗处理方式(Flat shading):对模型的平面单元按光照进行着色,但不进行光滑处理。
(5) 光滑明暗处理方式(Smooth shading):对模型按光照绘制的过程进行光滑处理,这种方式更接近于现实。
(6) 加阴影和纹理的方式(Shadow and Texture):在模型表面贴上纹理甚至加上光照阴影效果,使三维场景像照片一样逼真。
(7) 运动模糊绘制方式(Motion blured):模拟物体运动时人眼观察所觉察到的动感模糊现象。
(8) 大气环境效果(Atmosphere effects):在三维场景中加入雾等大气环境效果,使人有身临其境之感。
(9) 深度域效果(Depth of effects):类似于照相机镜头效果,模拟在聚焦点处清晰。

六、 OpenGL库函数与运行方式

1.4.1 OpenGL开发组件
Windows9x/NT下的OpenGL组件有两种,一种是SGI公司提供的,一种是Microsoft公司提供的。两者的开始库大体上没有什么区别,都是由由三大部分组成:
(1) 函数的说明文件:gl.h、glu.h、glut.h和glaux.h
(2) 静态链接库文件:glu32.lib、glut32.lib、glaux.lib和opengl32.lib
(3) 动态链接库文件:glu.dll、glu32.dll、glut.dll、glut32.dll和opengl32.dll
所有开发OpenGL应用程序的库文件在本书所附光盘中可以找到。
1.4.2 OpenGL函数
开发基于OpenGL的应用程序,必须先了解OpenGL的库函数。OpenGL库函数的命名方式非常有规律,每个库函数均有前缀gl、glu、aux,分别表示该函数属于OpenGL基本库、实用库和辅助库。
OpenGL的库函数大致可以分为六类:
1.OpenGL核心库
包含有115个函数,函数名的前缀为gl。
这部分函数用于常规的、核心的图形处理。由于许多函数可以接收不同数据类型的参数,因此派生出来的函数原形多达300多个。
2.OpenGL实用库
包含有43个函数,函数名的前缀为glu。
这部分函数通过调用核心库的函数,为开发者提供相对简单的用法,实现一些较为复杂的操作。如:坐标变换、纹理映射、绘制椭球、茶壶等简单多边形。
OpenGL中的核心库和实用库可以在所有的OpenGL平台上运行。
3.OpenGL辅助库
包含有31个函数,函数名前缀为aux。
这部分函数提供窗口管理、输入输出处理以及绘制一些简单三维物体。
OpenGL中的辅助库不能在所有的OpenGL平台上运行。
4.OpenGL工具库
包含大约30多个函数,函数名前缀为glut。
这部分函数主要提供基于窗口的工具,如:多窗口绘制、空消息和定时器,以及一些绘制较复杂物体的函数。由于glut中的窗口管理函数是不依赖于运行环境的,因此OpenGL中的工具库可以在所有的OpenGL平台上运行。
5.Windows专用库
包含有16个函数,函数名前缀为wgl。
这部分函数主要用于连接OpenGL和Windows 95/NT,以弥补OpenGL在文本方面的不足。Windows专用库只能用于Windows 95/98/NT环境中。
6.Win32 API函数库
包含有6个函数,函数名无专用前缀。
这部分函数主要用于处理像素存储格式和双帧缓存。这6个函数将替换Windows GDI中原有的同样的函数。Win32API函数库只能用于Windows 95/98/NT环境中。

1.5 OpenGL程序运行方式
运行OpenGL主要有以下三种方式:
1.OpenGL硬件加速方式
一些显示芯片如3Dlabs公司的GliNT进行了优化,OpenGL的大部分功能均可由硬件实现,仅有少量功能由操作系统来完成。这样极大地提高了图形显示的性能,并且能够获得工作站级的图形效果,但是这样的图形硬件价格十分昂贵,非一般用户所能承担。
2.三维图形加速模式
一些中低档的图形芯片往往也具备一定的三维加速功能,由硬件来完成一些较为复杂的图形操作。一些重要的OpenGL操作,例如Z缓存等就能够直接由显示卡硬件来完成,显示卡所不能支持的图形功能,则通过软件模拟的方式在操作系统中进行模拟。采用这种方法,显示速度尽管无法与硬件加速方法相比,但与采用纯软件模拟方式相比,速度要快得多。
3.纯软件模式
对于不具备三维加速功能的显示卡,要想运行OpenGL,只能采用纯软件模拟方式。由于所有复杂的OpenGL图形功能均通过主机来模拟,所以速度将会受到很大的影响。但正是由于有了软件模拟方式,才使得更多的用户能够领略OpenGL的强大功能,并能在硬件性能较差的机器上对OpenGL进行开发。
采用了OpenGL技术,大大降低了开发高质量图形软件对软、硬件的依赖程度。
OpenGL对硬件的要求如下:
CPU:Pentinum或Pentinum Pro
时钟频率:90MHz以上
内存:16/32/64MB以上
硬盘:512MB以上
其它可选。
OpenGL对软件环境的最低要求是:
操作系统:Windows NT4.0以上或Windows 95以上
OpenGL库:Visual Studio 5.0以上版本已包含该库。
以当前的计算机发展水平,达到以上软、硬件配置水平实在易之又易。由此对于OpenGL对系统的低要求也可略见一斑。
文章题目:why OPENGL

--------------------------------------------------------------------------------

版权所有: puzzy 2003-5-29 0:16:04 加贴在 3D Game Design 察看该网友的资料 编辑本帖 给他(她)发信

    GL&D3D API探源

     ----从OPENGL32.DLL说起

     

    OPENGL32.DLL是一个 API调用层。 也是一个OPENGL1.1的实现库。

    OPENGL32.DLL可以用软件实现OPENGL1.1规范的内容。而不需要硬件支持。

    下面解释硬件关系。以NVIDIA产品做例子。

    在NT/2K/XP下安装NVIDIA 3D卡后,会找到一个NVOGLNT.DLL的文件。

    这就是硬件厂商实现的OPENGL硬件调用模块。

    假设你在应用程序APP.EXE调用了glVeretx3d(1,1,1);

    系统调用顺序:

    APP.EXE ---> OPENGL32.DLL ---> NVOGLNT.DLL --->NV底层驱动

    --->AGP 3d card这里OPENGL32.DLL只实现函数的转调用功能。

    由NVOGLNT.DLL完成主要OPENGL功能。而OPENGL32.DLL里只完成

    一些必要的状态机,资源调度等功能。这也可以解释为什么实现

    OPENGL的硬件为什么要必须用硬件实现OPENGL1.1全部功能。

    这个要求对于早期硬件厂商来说过高。所以D3D借这个机会进入

    游戏硬件业。

    APP_d3d.EXE---> DX COM LAYER(HAL) ----> NV D3D DRIVER

    --->NV 底层驱动 -->。。。

    因为不象OPENGL1.1的规范,DX COM接口规范全由MS自己指定,所以针对

    当时硬件生产水平,DX定出了一个广大硬件商以廉价代价就可以实现的

    3D API调用规范。所以,支持D3D硬件更便宜和广泛的出现了。这个3D

    API接口不是以C函数给出,而以MS自己的COM接口给出。

    显然,实现DrawPrimitive比实现 glVertex3d 在当时要便宜和容易多了。

    这也是为什么D3D接口从来就比OPENGL丑陋难用得多。D3D必须把本来

    OPENGL硬件可以实现的功能暴露给 PROGRAMMER自己来实现。说到这里,

    得提一下PS2的显示功能。号称有史以来最难开发的PS2,其显卡功能

    相当于一个8MB的VOODOO。但其游戏和画面仍然令人夺目。原因除了它

    飞快的象素填充率(16个象素/周期)。还有就是PS GS把所有硬件都暴

    露给程序,甚至FRAME BUFFER,DMA本身。加上专用向量运算单元(相

    当于功能更强大N倍的VERTEX SHADER),使得开发难度和效果都不是

    和一般PC(3-4年前)一个数量级的。

    我们都知道当今图形硬件飞速发展,几个月后就有全新功能的3D硬件出现。

    在软件编写上,只靠OPENGL32.DLL实现的GL1.1规范显然不够用。

    于是有OPENGL EXTENSION来及时扩展GL功能。当时用

    wglGetAppProcess("扩展函数名")后。你可以得到硬件厂商实现最

    新功能的OPENGL 调用函数。以ARB,EXT,NV,ATI,SGIS等前缀打头的

    扩展函数,可以实现从顶点SHADER,象素SHADER到阴影,3D贴图等

    各种新的功能。这时 APP.EXE对扩展GL 函数的调用,就直接从

    NVOGLNT.DLL中得到。

    因为是C函数库。每当有新功能增加后,硬件厂家可以随时和

    及时更新NVOGLNT.DLL。以便及时让APP.EXE使用上最新GL调用的硬件

    功能。

    D3D采用COM接口规范。二进制兼容的COM规范以纯虚函数形式提供用

    户更新的3D API。但由于是MS软件商自己维护,它要协同几个大硬

    件商,统一并等待他们一起把DX下个版本的功能实现,才会推出新

    DX版本。简单讲,GL由GL组织与硬件厂商一起维护。D3D由MS与硬件

    厂商一起维护。这种3D硬件使用功能完全由MS来规划和统一,并给硬件

    指定标准的做法,一方面统一3D游戏开发接口。另一方面对新硬件功

    能支持慢,借自己操作系统产品欺凌霸市。并且不提供跨操作系统平

    台功能。而OPENGL在MAC,UNIX,LINUX操作系统,PC,SGI,MAC,SUN,HP,

    COMPAG ALPHA64等各种硬件平台上都有实现。OPENGL一般比相同功能

    版本的D3D强大一些。可利用厂商自己的GL 扩展,实现D3D实现不了

    的功能。另外,GL 一开始就有的SISSOR TEST功能,直到10年后D3D为了

    STENCIL SHADOW VOLUME优化才加入。而更进一步SHADOW VOLUME优化

    的DEPTH RANGE TEST功能(NV FX5900 实现),D3D9也无法实现了。

    更不用说glVertexPointer在GL这么基本的顶点数组指定功能,

    直到DX8的VERTEX STREAM才加入。如今GL硬件生产与D3D的成本早

    已差别不大。在过去几年里GL规范更新比D3D慢了一些。GL1。2。1

    以后规范迟迟不出,导致大量3D游戏开发人员使用D3D。如今ARB制

    定组织经过艰苦努力,破除MS的阻挠(ARB_VERTEX_PROGRAM规范的

    加入延迟听说是由于MS阻挠)。已统一了顶点编程与象素编程,

    AGP BUFFER模式等适应3D硬件发展的规范。

    对于开发者来说,对技术和规范的选择永远是趋炎附势。只有最强者

    才可以控制规范,而不是被规范控制。IDSOFTWARE充满传奇的发展史,

    与之持之以恒使用GL而排斥D3D交融在一起。被业内很多人捧为敢于向

    强权叫板的英雄。从VOODOO专门为之写MINI GL驱动,到NV与ATI在

    DOOM3演示平台选择上,Q3 、D3驱动优化作弊上的尔虞我诈,都能看出

    CAMARK以一人之力而独档软硬件行业强权控制的特异本领。

    现在D3D功能基本与OPENGL差别不大,实现上D3D终于靠一些UTILITY

    LIB和D3DX等辅助库勉强与GL的易用性差的不太远。但对于从现在起

    立志进入3DGAME 开发的初学者来讲,D3D仍然是个级差的选择。因

    为其D3D发展初期定下的接口结构,本身由于要适应当时水平极低的PC

    硬件生产,而极端丑陋和令人费解。很容易使人陷入接口技术细节而忘记

    RENDERING 本质技术研究,或者引擎大框架的构造。使初学者进极慢。

    GL是为了成为REALTIME 3D RENDERING业界的标准而设计,思想合理,

    接口简单且强大。无论是初学或以之为职业,都是最好的选择。

    最重要的是,当3D硬件商把通向未来3D游戏世界的新功能提供给你后,选择它们的是你。而不是M$。
以上这好文章比较了Opengl与D3D并且说明了双方的优缺点以及作者为什么要选择Opengl的原因,非常精辟,我也很同意作者的观点,转载自 [url]www.hardcore3d.net[/url] 网站的游戏制作论坛,这论坛有不少编程方面帖子,喜欢图形编程的人可以去那儿的论坛,会找到不少有价值的资料的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值