荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: Jobs (温少), 信区: Program
标  题: 在Windows 95/NT下用OpenGL编程
发信站: BBS 荔园晨风站 (Thu Mar 18 16:00:38 1999), 转信


              在Windows 95/NT下用OpenGL编程

    科学计算可视化、计算机动画和虚拟现实是当前计算机图形学的
三个热点,而这三个热点的核心都是三维真实感图形的绘制。由于Ope
nGL(Open Graphics Library)具有跨平台、简便、高效、功能完善等
特点,目前已经成为三维图形制作方法中事实上的工业标准。自从Win
dows NT 3.51在微机平台上支持OpenGL以后,现在微软公司在Windows
 95 OSR 2、Windows NT 4.0中也提供OpenGL开发环境。Visual C++
从4.2版本以后已经完全支持OpenGL API,使三维世界的"平民化"已成
为必然。
    Windows操作系统对OpenGL的支持
    具有Windows编程经验的人都知道,在Windows下用GDI作图必须通
过设备上下文(Dev ice Context,简写DC)调用相应的函数。用OpenGL
作图也是类似的,OpenGL函数是通过"渲染上下文"(Rendering Contex
t,简写RC)完成三维图形的绘制。Windows下的窗口和设备上下文支持
"位图格式"( PIXELFORMAT)属性,和RC有着位图结构上的一致。只要
在创建RC时与一个DC建立联系(RC也只能通过已经建立了位图格式的D
C来创建),OpenGL的函数就可以通过RC对应的DC画到相应的显示设备
上。其中,还有以下几方面需要注意:
    1. 一个线程只能拥有一个RC,即用户如果在一个线程内对不同设
备作图,只能通过更换与RC对应的DC来完成,而RC在线程中保持不变(
当然,删除旧的RC后再创建新的RC是可以的)。与此对应,一个RC也只
能属于一个线程,不能被不同线程同时共享。
    2. 设定DC位图格式等于设定了相应的窗口的位图格式,并且DC和
窗口的位图格式一旦确定就不能再改变。这一点只能期望以后的Wind
ows版本改进。
    3. 一个RC虽然可以更换DC,在任何时刻只能利用一个DC(该DC称
为RC的当前DC),但由于一个窗口可以让多个DC作图,从而可以让多个
线程利用多个RC在该窗口上执行OpenGL操作。
    4. 目前Windows下的OpenGL版本对OpenGL和GDI在同一个DC上作
图有一定的限制。当使用双缓存用OpenGL产生动画时,不能使用GDI函
数向该DC作图。
    5. 不建议用ANSI C在Windows下编写OpenGL程序。这样的程序虽
然具有跨平台的可移植性(比如很多SGI的例子程序),但是它们不能利
用Windows操作系统的很多特性,实用价值不大。
    用VC编写OpenGL程序
    经过上面的分析,不难发现用VC来调用OpenGL作图的方法是很明
显的。其步骤如下:
    1. 先设置显示设备DC的位图格式(PIXELFORMAT)属性,通过填写
一个PIXELFORMATDE SCRIPTOR的结构来完成(关于该结构中各项数据
的意义,请参照VC的帮助信息),该结构决定了OpenGL作图的物理设备
的属性,比如该结构中的数据项dwFlags中PFD_DOUBLEBUFFER  位如果
没有设置(置为1),通过该设备的DC作图的OpenGL命令就不可能使用双
缓冲来做动画。有一些位图格式(PIXELFORMAT)DC支持,而有一些DC不
支持,所以程序必须先用Choos ePixelFormat来选择与DC所支持的指
定位图格式最接近的位图格式,然后用SetPixelFor mat设置DC的位图
格式。
    2. 利用刚才的设备DC建立渲染上下文RC(wglCreateContext),使
得RC与DC建立联系(wglMakeCurrent)。
    3. 调用OpenGL函数作图。由于线程与RC一一对应,OpenGL函数的
参数中都不指明本线程RC的句柄(handle)。
    4. 作图完毕以后,先通过置当前线程的RC为NULL(::wglMakeCurr
ent(NULL, NULL) ;),断开当前线程和该渲染上下文的联系,由此断
开与DC的联系。此时RC句柄的有效性不明确,所以在后面删除RC时,要
先判断一下RC句柄的有效性(if (m_hrc) :wglDeleteCont ext(m_hrc
);),再根据情况释放(ReleaseDC)或者删除(DeleteDC)DC。
    编程实例
    本文给出的程序是用MFC完成的一个简单的OpenGL作图——用Ope
nGL的辅助库画了一个有光照的实心圆球。由于篇幅所限,这里仅对用
MFC编写OpenGL程序时需要注意的问题做一个简要的说明。
    1. 一旦设定了一个DC的位图格式,该DC所联系的窗口的位图格式
也随之设定。该窗口若含有子窗口或者有兄弟窗口,这些兄弟/子窗口
的位图格式如果没有设成与对应RC一致的格式,OpenGL在它们上面作
图就容易出错。故而OpenGL作图的窗口必须具有WS_CLIP CHILDREN
和 WS_CLIPSIBLINGS风格,程序中在主框窗的构造函数中用LoadFrame
(IDR_MA INFRAME,WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_C
LIPSIBLINGS,NULL,NULL ); 来指定主窗口的风格。
    2. 在ANSI C的OpenGL编程中,由auxReshapeFunc定义设置OpenGL
可视窗口大小和作图尺寸的回调函数;在MFC中应该由WM_SIZ消息的处
理函数来完成。在ANSI C的OpenGL编程中,由EauxMainLoop定义作图
的回调函数;在MFC中应该由WM_PAINT消息的处理函数来处理。相应的
,由OpenGL定义的键盘、鼠标处理函数都应该由相应的Windows处理函
数来响应。
    3. OpenGL自己有刷新背景的函数glClear,故而应禁止Windows刷
新窗口背景。否则,当窗口需要重画时,Windows会自动先发送WM_ERAS
EBKGND,而缺省的处理函数使用白色的背景刷。当OpenGL使用的背景
颜色不是白色时,作图时有一帧白色的闪烁。这种现象在做动画时特
别明显。程序中只需要在WM_ERASEBKGND的消息处理函数中禁止父窗
口类的消息处理,简单地返回一个TRUE即可。
    4. 由于OpenGL的跨平台性,它必须用操作系统的调色板,所以GL_
INDEX_MODE作图时必须用VC自己定义调色板。不过一般情况下,用GL_
RGBA_MODE模式比较方便,很少用到GL _INDEX_MODE模式。
    5. 在OpenGL作图期间,RC对应的DC不能删除或者释放。
    6. 由于OpenGL作图时需要长时间占用DC,所以最好把作图窗口类
设成CS_OWNDC。MF C缺省的窗口类风格中没有设这一属性,程序中在
主窗口C++类的PreCreateWindow方法中自己注册了一个窗口类,除了
设定了CS_OWNDC属性以外,还设定了CS_HREDRAW、CS_VREDR AW和CS_S
AVEBITS。设定CS_HREDRAW、CS_VREDRAW是为了让窗口缩放时产生WM_
PAINT消息,修正OpenGL可视窗口和作图尺寸;由于OpenGL作图需要很
多计算,设定CS_SAVEBITS是为了在OpenGL窗口被遮盖后显现出来时,
不产生WM_PAINT消息,用内存存储的图像来填充,从而用空间消耗换取
计算时间。
    7. 本程序中没有对OpenGL函数的出错情况作出处理。OpenGL出
错后返回错误码,不会抛出异常;而且在某一个函数出错以后,后继函
数也一般不会出现异常,只是返回错误码,一不小心就可能忽略某些错
误。但是,对每一个OpenGL函数都做出错与否的判断比较麻烦,所以编
程时对OpenGL的函数调用应当非常小心。
    程序运行时必须确定OpenGL32.dll、glu.dll、glaux.dll是在Wi
ndows的System目录下。OpenGL运行不需要注册库信息。在VC的STUDI
O中运行程序时,工程文件中必须加入OpenGL.H、glu.h、glaux.h以及
OpenGL.lib、glu.lib、glaux.lib,这些文件由VC自带。

                                  (*红茶馆*)

--
※ 来源:.BBS 荔园晨风站 bbs.szu.edu.cn.[FROM: 192.168.2.88]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店