分享
 
 
 

Win95/NT下OpenGL编程原理

王朝system·作者佚名  2008-06-01
窄屏简体版  字體: |||超大  

----科学计算可视化,计算机动画和虚拟现实是现在计算机图形学的三个热点。而这三个热点的核心都是三维真实感图形的绘制。由于OpenGL(

OpenGraphicsLibrary)具有跨平台性、简便、高效、功能完善,目前已经成为了三维图形制作方法中事实上的工业标准。自从WindowsNT3.51在微

机平台上支持OpenGL以后,现在微软公司在Windows95OSR2、WindowsNT4.0中连续性的提供OpenGL开发环境。VisualC++从4.2版本以后已经完全支持

OpenGLAPI,使三维世界的"平民化"已成为必然。

----Windows操作系统对OpenGL的支持

----具有Windows编程经验的人都知道,在Windows下用GDI作图必须通过设备上下文(DeviceContext简写DC)调用相应的函数;用OpenGL作图也是

类似,OpenGL函数是通过"渲染上下文"(RenderingContext简写RC)完成三维图形的绘制。Windows下的窗口和设备上下文支持"位图格式"(

PIXELFORMAT)属性,和RC有着位图结构上的一致。只要在创建RC时与一个DC建立联系(RC也只能通过已经建立了位图格式的DC来创建),OpenGL的

函数就可以通过RC对应的DC画到相应的显示设备上。这里还有以下需要注重的方面:

----1.一个线程只能拥有一个渲染上下文(RC),也就是说,用户假如在一个线程内对不同设备作图,只能通过更换与RC对应的DC来完成,而RC在

线程中保持不变。(当然,删除旧的RC后再创建新的是可以的)与此对应,一个RC也只能属于一个线程,不能被不同线程同时共享。

----2.设定DC位图格式等于设定了相应的窗口的位图格式,并且DC和窗口的位图格式一旦确定就不能再改变。这一点只能期望以后的Windows版本改

进了。

----3.一个RC虽然可以更换DC,在任何时刻只能利用一个DC(这个DC称为RC的当前DC),但由于一个窗口可以让多个DC作图从而可以让多个线程利

用多个RC在该窗口上执行OpenGL操作。

----4.现在的Windows下的OpenGL版本对OpenGL和GDI在同一个DC上作图有一定的限制。当使用双缓存用OpenGL产生动画时,不能使用GDI函数向该DC

作图。

----5.不建议用ANSIC在Windows下编写OpenGL程序。这样的程序虽然具有跨平台的可移植性(比如很多SGI的例子程序),但是它们不能利用

Windows操作系统的很多特性,实用价值不大。

----用VC来编写OpenGL程序

----经过上面的分析,用VC来调用OpenGL作图的方法就很显然了。步骤如下:

----1.先设置显示设备DC的位图格式(PIXELFORMAT)属性。这通过填充一个PIXELFORMATDESCRIPTOR的结构来完成(关于PIXELFORMATDESCRIPTOR中

各项数据的意义,请参照VC的帮助信息),该结构决定了OpenGL作图的物理设备的属性,比如该结构中的数据项dwFlags中PFD_DOUBLEBUFFER位假如

没有设置(置1),通过该设备的DC上作图的OpenGL命令就不可能使用双缓冲来做动画。有一些位图格式(PIXELFORMAT)是DC支持的,而有一些DC

就不支持了。所以程序必须先用ChoosePixelFormat来选择DC所支持的与指定位图格式最接近的位图格式,然后用SetPixelFormat设置DC的位图格式

----2.利用刚才的设备DC建立渲染上下文RC(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_OVERLAPPEDWINDOWWS_CLIPCHILDRENWS_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在Windows的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_)

#define AFX_OPENGLWND_H__3FB1AB28_0E70_11D2

_9ACA_48543300E17D__INCLUDED_

#if _MSC_VER >= 1000

#pragma once

#endif // _MSC_VER >= 1000

#include < afxwin.h >

#include "SimpleGLApp.h"

#include "resource.h"

// OpenGLWnd.h : header file

//

///////////////////////////////////////

//////////////////////////////////////

// COpenGLWnd frame

class COpenGLWnd : public CFrameWnd

{

DECLARE_DYNCREATE(COpenGLWnd)

public:

COpenGLWnd();

// protected constrUCtor used by dynamic creation

protected:

HGLRC m_hrc;

CClientDC *m_pDC;

// Attributes

public:

// Operations

public:

// Overrides

// ClassWizard generated virtual function overrides

//{{AFX_VIRTUAL(COpenGLWnd)

protected:

virtual BOOL PreCreateWindow(CREATESTRUCT& cs);

//}}AFX_VIRTUAL

// Implementation

public:

virtual ~COpenGLWnd();

// Generated message map functions

//{{AFX_MSG(COpenGLWnd)

afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);

afx_msg void OnSize(UINT nType, int cx, int cy);

afx_msg void OnDestroy();

afx_msg BOOL OnEraseBkgnd(CDC* pDC);

afx_msg void OnPaint();

//}}AFX_MSG

DECLARE_MESSAGE_MAP()

};

///////////////////////////////////////

//////////////////////////////////////

//{{AFX_INSERT_LOCATION}}

// Microsoft Developer Studio will insert

additional declarations immediately before the previous line.

#endif // !defined(AFX_OPENGLWND_H__3FB1AB28_

0E70_11D2_9ACA_48543300E17D__INCLUDED_)

主窗口类的实现(OpenGLWnd.cpp):

// OpenGLWnd.cpp : implementation file

//

#include "stdafx.h"

#include "OpenGLWnd.h"

#include "SimpleGLApp.h"

#include "gl\glu.h"

#include "gl\gl.h"

#include "gl\glaux.h"

#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE

static char THIS_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()

BOOL COpenGLWnd::PreCreateWindow(CREATESTRUCT& cs)

{

// TODO: Add your specialized

code here and/or call the base class

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);

}

int COpenGLWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)

{

if (CFrameWnd::OnCreate(lpCreateStruct) == -1)

return -1;

int pixelformat;

m_pDC = new CClientDC(this);//在客户区作图

ASSERT(m_pDC != NULL);

static PIXELFORMATDESCRIPTOR pfd =

{

sizeof(PIXELFORMATDESCRIPTOR), //固定值

1, //固定值

PFD_DRAW_TO_WINDOW // support window

PFD_SUPPORT_OPENGL // support OpenGL

PFD_TYPE_RGBA, // RGBA模式,不用调色板

16, //程序在16位色彩下运行

0, 0, 0, 0, 0, 0, // color bits ignored

0, // no alpha buffer

0, // shift bit ignored

0, // no accumulation buffer

0, 0, 0, 0, // accum bits ignored

32, // 32-bit z-buffer

0, // no stencil buffer

0, // no auxiliary buffer

PFD_MAIN_PLANE, // main layer

0, // reserved

0, 0, 0 // layer masks ignored

};

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(), m_hrc);

glClearDepth(1.0f);

glEnable(GL_DEPTH_TEST);

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

glMatrixMode(GL_MODELVIEW);

return 0;//OpenGL窗口构造成功

}

void COpenGLWnd::OnSize(UINT nType, int cx, int cy)

{

CFrameWnd::OnSize(nType, cx, cy);

// TODO: Add your message handler code here

if(cy > 0)

{

glViewport(0, 0, cx, cy);

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

if (cx < = cy)

glOrtho(-3.0,3.0,-3.0 * (GLfloat)cx/(GLfloat)cy,

3.0 * (GLfloat)cx/(GLfloat)cy,-3.0,3.0);

else

glOrtho(-3.0,3.0,-3.0 * (GLfloat)cy/(GLfloat)cx,

3.0 * (GLfloat)cy/(GLfloat)cx,-3.0,3.0);

glMatrixMode(GL_MODELVIEW);

}

}

void COpenGLWnd::OnDestroy()

{

CFrameWnd::OnDestroy();

::wglMakeCurrent(NULL, NULL);

if (m_hrc)

::wglDeleteContext(m_hrc);

if (m_pDC)

delete m_pDC;

// TODO: Add your message handler code here

}

BOOL COpenGLWnd::OnEraseBkgnd(CDC* pDC)

{

// TODO: Add your message

handler code here and/or call default

return TRUE;

//return CFrameWnd::OnEraseBkgnd(pDC);

}

void COpenGLWnd::OnPaint()

{

CPaintDC dc(this); // device context for painting

GLfloat light_position[]={2.0f,0.0f,4.0f,0.0f};

// TODO: Add your message handler code here

glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

glClear(GL_COLOR_BUFFER_BIT GL_DEPTH_BUFFER_BIT);

glPushMatrix();

glTranslatef(0.0f, 0.0f, -2.0f);

glLightfv(GL_LIGHT0,GL_POSITION,light_position);

glEnable(GL_LIGHTING);

glEnable(GL_LIGHT0);

glDepthFunc(GL_LESS);

glEnable(GL_DEPTH_TEST);

auxSolidSphere(1.0);

glPopMatrix();

glFinish();

// Do not call CFrameWnd::OnPaint() for painting messages

}

应用程序类的定义(SimpleGLApp.h):

#if !defined(AFX_SIMPLEGLAPP_H__3FB1AB29

_0E70_11D2_9ACA_48543300E17D__INCLUDED_)

#define AFX_SIMPLEGLAPP_H__3FB1AB29_0E70

_11D2_9ACA_48543300E17D__INCLUDED_

#if _MSC_VER >= 1000

#pragma once

#endif // _MSC_VER >= 1000

// SimpleGLApp.h : header file

//

#include < afxwin.h >

#include "OpenGLWnd.h"

#include "resource.h"

///////////////////////////////////////

//////////////////////////////////////

// CSimpleGLApp thread

class CSimpleGLApp : public CWinApp

{

DECLARE_DYNCREATE(CSimpleGLApp)

public:

CSimpleGLApp();

// protected constructor used by dynamic creation

// Attributes

public:

// Operations

public:

// Overrides

// ClassWizard generated virtual function overrides

//{{AFX_VIRTUAL(CSimpleGLApp)

public:

virtual BOOL InitInstance();

virtual int ExitInstance();

//}}AFX_VIRTUAL

// Implementation

public:

virtual ~CSimpleGLApp();

// Generated message map functions

//{{AFX_MSG(CSimpleGLApp)

afx_msg void OnAppExit();

//}}AFX_MSG

DECLARE_MESSAGE_MAP()

};

///////////////////////////////////////

//////////////////////////////////////

//{{AFX_INSERT_LOCATION}}

// Microsoft Developer Studio will insert

additional declarations

immediately before the previous line.

#endif // !defined(AFX_SIMPLEGLAPP_H__3FB1AB29_

0E70_11D2_9ACA_48543300E17D__INCLUDED_)

应用程序类的实现(SimpleGLApp.cpp):

// SimpleGLApp.cpp : implementation file

//

#include "stdafx.h"

#include "SimpleGLApp.h"

#include "OpenGLWnd.h"

#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE

static char THIS_FILE[] = __FILE__;

#endif

///////////////////////////////////////

//////////////////////////////////////

// CSimpleGLApp

IMPLEMENT_DYNCREATE(CSimpleGLApp, CWinApp)

CSimpleGLApp::CSimpleGLApp()

{

}

CSimpleGLApp::~CSimpleGLApp()

{

}

BOOL CSimpleGLApp::InitInstance()

{

// TODO: perform and per-thread initialization here

m_pMainWnd = new COpenGLWnd();

m_pMainWnd- >ShowWindow(m_nCmdShow);

m_pMainWnd- >UpdateWindow();

return TRUE;

}

int CSimpleGLApp::ExitInstance()

{

return CWinApp::ExitInstance();

}

BEGIN_MESSAGE_MAP(CSimpleGLApp, CWinApp)

//{{AFX_MSG_MAP(CSimpleGLApp)

ON_COMMAND(ID_APP_EXIT, OnAppExit)

//}}AFX_MSG_MAP

END_MESSAGE_MAP()

///////////////////////////////////////

//////////////////////////////////////

// CSimpleGLApp message handlers

void CSimpleGLApp::OnAppExit()

{

// TODO: Add your command handler code here

CWinApp::OnAppExit();

}

CSimpleGLApp SimpleGLApp;

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有