Windows NT 下OpenGL 编 程 原 理.docx
- 文档编号:8276545
- 上传时间:2023-01-30
- 格式:DOCX
- 页数:17
- 大小:26.28KB
Windows NT 下OpenGL 编 程 原 理.docx
《Windows NT 下OpenGL 编 程 原 理.docx》由会员分享,可在线阅读,更多相关《Windows NT 下OpenGL 编 程 原 理.docx(17页珍藏版)》请在冰豆网上搜索。
WindowsNT下OpenGL编程原理
Windows95/NT下OpenGL编程原理
----科学 计 算可视化,计算机 动画 和虚拟现实是现在计算
机图形学的三个热点。
而 这三个热点的核心都 是三 维真
实感图 形的绘制。
由 于OpenGL(OpenGraphicsLibrary)具有跨 平
台性、简便、 高效、功 能完 善,目前 已经 成为了三 维图形
制作 方法中事实上的工业标准。
自 从Windows NT3.51在 微机
平台 上支 持OpenGL以 后,现 在微软公司在Windows95OSR2、
Windows NT4.0中连 续性的提供OpenGL开发环境。
VisualC++从4.2版
本以后已经完全支持OpenGLAPI,使三维 世界的" 平 民化"已
成为 必然。
----Windows操 作系统对OpenGL的支持
----具有Windows编程 经 验的人都知道,在Windows 下用GDI作图 必
须通过设 备 上下文(DeviceContext简写DC)调 用相 应的函 数;
用OpenGL作图也是类似,OpenGL函数 是通过"渲染上下文"
(RenderingContext 简 写RC)完成 三 维图形 的绘制。
Windows下
的窗 口和设备上下文支持"位图格式"(PIXELFORMAT) 属性,
和R C有着位 图 结 构上的 一致。
只要 在创建RC 时与一
个DC建立联系(RC也只能通 过已经 建 立了位 图格式
的 DC来 创 建),OpenGL的函数就可 以通过 RC 对应的DC
画到 相应的 显 示设 备 上。
这里还有以 下需要 注意的 方 面:
---- 1. 一个线 程 只 能拥有 一 个 渲染上 下 文(RC), 也就是
说,用户如果在一个线程内对不同设 备 作图,只 能通过更
换与R C 对应 的D C来完成,而RC在 线程中保持不 变。
(当然,删除旧的RC 后再创建新的是可以的)与 此对应,
一个 RC也只能 属于一 个 线 程, 不 能 被 不同线 程同时 共享。
---- 2.设定DC位 图格式等于设定了相应的 窗口的 位图 格 式,
并且D C和 窗口的位图格 式一旦确定就不能 再 改变。
这一
点只能 期望以后的Windows版 本改 进了。
----3.一个 RC虽 然 可以更换DC,在任何 时 刻只能利用一个
DC( 这个DC称为RC的 当前DC),但由 于 一个 窗口可以 让多个
DC作图从而可以 让多个线 程利用多个 RC在该窗口上执
行OpenGL操作。
----4.现在的Windows下的OpenGL版本对OpenGL和GDI在同一 个DC 上
作图有一定的限制。
当使用双 缓存用OpenGL 产生动画时,不
能使用GDI函数向该DC作图。
---- 5.不建 议用A NSI C在Windows下 编写OpenGL程序。
这 样
的程序虽然 具有跨平台的 可移 植性(比 如很 多SG I的例
子 程序), 但是它们不能利用Windows 操 作系统的 很多特 性, 实
用价 值不大。
----用 VC来编写OpenGL程序
---- 经 过上 面的分析, 用VC 来调 用OpenGL 作图的方法就很显
然了。
步骤如下:
----1. 先 设 置显示 设备DC的 位图格式(PIXELFORMAT) 属性。
这
通 过填充一 个PIXELFORMATDESCRIPTOR的结构来完成(关于
PIXELFORMATDESCRIPTOR中 各 项数据的 意义, 请参 照VC的 帮 助信息),
该结构决定了OpenGL 作图的物理设 备的属性,比如该结构中 的
数据项dwFlags中PFD_DOUBLEBUFFER位如果没 有设置(置 1),通 过该
设 备的D C上作图的OpenGL命令就不 可能使 用双缓冲 来做动画。
有一 些位图格式(PIXELFORMAT)是DC支持的, 而有一些DC就不支
持了。
所以程序 必须先用ChoosePixelFormat来选择DC所支 持的与
指 定位 图格 式最接近的位图格式,然后用SetPixelFormat设置DC
的位 图格式。
----2.利 用刚 才的设备DC建立 渲染上下文R C(wglCreateContext)
,使得RC 与DC建 立 联系(wglMakeCurrent)。
---- 3.调用OpenGL函 数作图。
由于线 程 与RC 一 一对应,
OpenGL函数的参数中都不 指明本线程RC 的句柄(handle)
----4.作图 完毕以后, 先通 过置当前线程 的RC为
NULL(:
:
wglMakeCurrent(NULL, NULL);), 断开当前 线程 和该渲 染上
下 文的联系, 由此断开 与 DC的联系。
此 时RC句柄的有 效性
在微软自 己的文 档中 也没 有讲清楚,所 以 在后面删 除RC的
时候要先判断以下RC句柄的有 效性(if(m_hrc):
:
wglDeleteContext(m_hrc);)。
再根据情 况释放(ReleaseDC)或者 删除(DeleteDC) DC
----所附程 序 说明
----所附的程 序用MFC 完 成了一 个 简单 的OpenGL作 图,
用OpenGL的辅助库画了一个有光照 的实 心圆球。
OpenGL本身的 函
数 这里就不解释 了, 仅对用MFC编OpenGL时需 要注意 的内 容做
一个简要的 说明:
----1.一 旦 设定了 一 个DC的位图格式,该DC所联 系的窗口的位
图格式随之设定。
该窗口若含有子窗口或者有兄弟窗口,这些
兄弟/子窗口的 位图格式没有 设成 与对 应RC 一 致的格式,OpenGL在
它们 上 面作图就 容易出错。
故而OpenGL作图的 窗口必须具有
WS_CLIPCHILDREN和WS_CLIPSIBLINGS风格,程序 中 在主框窗的构 造函
数 中 用LoadFrame(IDR_MAINFRAME,WS_OVERLAPPEDWINDOW|WS_CLIPCHILDREN| WS_CLIPSIBLINGS,NULL,NULL );
指定了主 窗口的 风格。
----2. 在ANSIC 的OpenGL编程中,由auxReshapeFunc定义设 置OpenGL
视口大小和 作图尺寸的回调函数。
在MFC中应该由WM_SIZ消息
的处理函数来完 成。
在ANSIC的OpenGL编程中, 由EauxMainLoop定
义作 图 的 回调函 数。
在MFC中应该由WM_PAINT 消息的 处 理函 数
来处理。
相应的, 由OpenGL定 义的键盘、鼠标处理函数都应
该由 相应的Windows处理函 数来响 应。
----3. OpenGL自 己有刷新背景的函数glClear,故 而应禁止Windows
刷 新窗口背景。
否则,当窗口需 要重画时,Windows 会自动先 发
送WM_ERASEBKGND,而缺省的处理函数使用 白 色的背景刷。
当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。
MFC缺省的 窗口类风 格中没有 设这一
属性, 程序 中在主窗 口C++类 的PreCreateWindow 方法中自己注
册 了一 个 窗口类,除了设 定 了CS_OWNDC属 性以外,还设 定了
CS_HREDRAW、CS_VREDRAW和CS_SAVEBITS。
设定CS_HREDRAW、CS_VREDRAW是为
了让 窗口 缩放 时产生WM_PAINT 消 息,修正OpenGL视口和作图
尺寸;由 于OpenGL作图需 要 很 多计算,设 定CS_SAVEBITS是为了
在OpenGL窗口被遮盖后显 现出 来 时, 不产生WM_PAINT消息,用
内存存储的图象来填充,从而用空间消耗换取 计 算 时间。
----7.本程序中 没有对OpenGL函数的出错情况作出 处 理。
OpenGL出错后 返回错误 码,不会 抛 出异 常; 而且 在某 一个
函 数出错以 后, 后继函数 也一般不会 出 现异常,只是返
回错 误码,一不小心就可 能忽 略某些 错误。
而 对 每一 个
OpenGL函数都 做出错与否 的判断比 较麻烦,所以编程 序时
对OpenGL的函数应当非常 小 心。
----参考书籍:
----《OpenGLProgrammer'sGuide》 SGIinc.
---- 《OpenGL三 维图形程 序 设计》廖 朵 朵、张华军 著,星球地图出版 社
----《VisualC++5.0联 机帮 助》
---- 附程序:
----程序运行时必 须 确定OpenGL32.dll、glu.dll、glaux.dll 在
indows的System目录 下。
如 果 找 不 到这些文件, 可以从
Windows95OSR2的机器上面将这些 文件拷贝过来即可。
OpenGL运行不需要注册库信 息。
在VC的STUDIO中运行程序时,
工程 文件中必须加入OpenGL.H 、glu.h、glaux.h以及OpenGL.lib、
glu.lib、glaux.lib,这 些 文件由VC自 带。
---- 主窗 口 类定义(OpenGLWnd.h):
s#if !
defined(AFX_OPENGLWND_H__3FB1AB28_0E70
_11D2_9ACA_48543300E17D__INCLUDED_)
#defineAFX_OPENGLWND_H__3FB1AB28_0E70_11D2
_9ACA_48543300E17D__INCLUDED_
#if _MSC_VER >=1000
#pragmaonce
#endif//_MSC_VER >= 1000
#include <afxwin.h>
#include "SimpleGLApp.h"
#include "resource.h"
//OpenGLWnd.h:
headerfile
//
///////////////////////////////////////
//////////////////////////////////////
//COpenGLWndframe
classCOpenGLWnd :
public CFrameWnd
{
ﻩDECLARE_DYNCREATE(COpenGLWnd)
public:
ﻩCOpenGLWnd();
//protectedconstructorused bydynamic creation
protected:
HGLRCﻩﻩﻩm_hrc;
ﻩCClientDCﻩﻩﻩ*m_pDC;
//Attributes
public:
// Operations
public:
// Overrides
//ClassWizard generatedvirtualfunctionoverrides
//{{AFX_VIRTUAL(COpenGLWnd)
ﻩprotected:
ﻩvirtual BOOLPreCreateWindow(CREATESTRUCT& cs);
//}}AFX_VIRTUAL
// Implementation
public:
virtual~COpenGLWnd();
ﻩ// Generatedmessagemapfunctions
//{{AFX_MSG(COpenGLWnd)
ﻩafx_msg int OnCreate(LPCREATESTRUCTlpCreateStruct);
afx_msg voidOnSize(UINTnType,intcx,intcy);
ﻩafx_msgvoidOnDestroy();
ﻩafx_msgBOOLOnEraseBkgnd(CDC*pDC);
afx_msgvoidOnPaint();
//}}AFX_MSG
ﻩDECLARE_MESSAGE_MAP()
};
///////////////////////////////////////
//////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
//MicrosoftDeveloperStudiowillinsert
additionaldeclarations immediatelybeforethepreviousline.
#endif// !
defined(AFX_OPENGLWND_H__3FB1AB28_
0E70_11D2_9ACA_48543300E17D__INCLUDED_)
主窗口类的实现(OpenGLWnd.cpp):
// OpenGLWnd.cpp:
implementationfile
//
#include"stdafx.h"
#include"OpenGLWnd.h"
#include"SimpleGLApp.h"
#include"gl\glu.h"
#include"gl\gl.h"
#include "gl\glaux.h"
#ifdef _DEBUG
#definenewDEBUG_NEW
#undefTHIS_FILE
static charTHIS_FILE[] =__FILE__;
#endif
///////////////////////////////////////
//////////////////////////////////////
//COpenGLWnd
IMPLEMENT_DYNCREATE(COpenGLWnd,CFrameWnd)
COpenGLWnd:
:
COpenGLWnd()
{
ﻩm_pDC= NULL;
m_hrc= 0;
LoadFrame(IDR_MAINFRAME,WS_OVERLAPPEDWINDOW
|WS_CLIPCHILDREN| WS_CLIPSIBLINGS
ﻩﻩ,NULL,NULL);
}
COpenGLWnd:
:
~COpenGLWnd()
{
}
BEGIN_MESSAGE_MAP(COpenGLWnd, CFrameWnd)
//{{AFX_MSG_MAP(COpenGLWnd)
ﻩON_WM_CREATE()
ﻩON_WM_SIZE()
ON_WM_DESTROY()
ﻩON_WM_ERASEBKGND()
ﻩON_WM_PAINT()
ﻩ//}}AFX_MSG_MAP
END_MESSAGE_MAP()
BOOLCOpenGLWnd:
:
PreCreateWindow(CREATESTRUCT&cs)
{
ﻩ// TODO:
Add yourspecialized
codehere and/orcall thebaseclass
cs.lpszClass=AfxRegisterWndClass(ﻩCS_DBLCLKSﻩ|
ﻩﻩCS_HREDRAWﻩ|
ﻩﻩﻩCS_VREDRAWﻩ|
ﻩﻩﻩﻩCS_SAVEBITS|
ﻩﻩﻩCS_NOCLOSE|
ﻩ CS_OWNDC
ﻩﻩ,AfxGetApp( )->LoadStandardCursor(IDC_ARROW),0 ,
AfxGetApp()->LoadStandardIcon(IDI_APPLICATION));
ﻩreturn CFrameWnd:
:
PreCreateWindow(cs);
}
intCOpenGLWnd:
:
OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if(CFrameWnd:
:
OnCreate(lpCreateStruct)==-1)
return-1;
ﻩ
intpixelformat;
m_pDC =newCClientDC(this);//在客户区作图
ﻩASSERT(m_pDC!
=NULL);
static PIXELFORMATDESCRIPTORpfd =
ﻩ{
sizeof(PIXELFORMATDESCRIPTOR),//固定值
1, //固定值
PFD_DRAW_TO_WINDOW| //supportwindow
PFD_SUPPORT_OPENGL| // supportOpenGL
PFD_TYPE_RGBA, //RGBA模式,不用调色板
16, //程序在16位色彩下运行
0, 0, 0,0,0,0, // colorbits ignored
0, //no alphabuffer
0, //shiftbitignored
0, //no accumulationbuffer
0,0,0,0, //accumbitsignored
32, // 32-bitz-buffer
0, //nostencilbuffer
0, //noauxiliarybuffer
PFD_MAIN_PLANE, //mainlayer
0, // reserved
0, 0,0 //layermasksignored
};
if ((pixelformat =ChoosePixelFormat(m_pDC->GetSafeHdc(), &pfd)) == 0)
{
MessageBox("在该DC上找不到与PFD接近的位图结构");
return-1;
}
if(SetPixelFormat(m_pDC->
GetSafeHdc(), pixelformat, &pfd)== FALSE)
{
MessageBox("无法在该DC上设置位图结构");
return-1;
}
m_hrc=wglCreateContext(m_pDC->GetSafeHdc());
wglMakeCurrent(m_pDC- >GetSafeHdc(),
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Windows NT 下OpenGL OpenGL