所 附 的 程 序 用 M F C 完 成 了 一 個(gè) 簡(jiǎn) 單 的OpenGL 作 圖, 用OpenGL 的 輔 助 庫(kù) 畫 了 一 個(gè) 有 光 照 的 實(shí) 心 圓 球。OpenGL 本 身 的 函 數(shù) 這 里 就 不 解 釋 了, 僅 對(duì) 用MFC 編OpenGL 時(shí) 需 要 注 意 的 內(nèi) 容 做 一 個(gè) 簡(jiǎn) 要 的 說 明:
---- 1. 一 旦 設(shè) 定 了 一 個(gè)DC 的 位 圖 格 式, 該DC 所 聯(lián) 系 的 窗 口 的 位 圖 格 式 隨 之 設(shè) 定。 該 窗 口 若 含 有 子 窗 口 或 者 有 兄 弟 窗 口, 這 些 兄 弟/ 子 窗 口 的 位 圖 格 式 沒 有 設(shè) 成 與 對(duì) 應(yīng)RC 一 致 的 格 式,OpenGL 在 它 們 上 面 作 圖 就 容 易 出 錯(cuò)。 故 而OpenGL 作 圖 的 窗 口 必 須 具 有WS_CLIPCHILDREN 和 WS_CLIPSIBLINGS 風(fēng) 格, 程 序 中 在 主 框 窗 的 構(gòu) 造 函 數(shù) 中 用LoadFrame(IDR_MAINFRAME,WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,NULL,NULL ); 指 定 了 主 窗 口 的 風(fēng) 格。
---- 2. 在ANSI C 的OpenGL 編 程 中, 由auxReshapeFunc 定 義 設(shè) 置OpenGL 視 口 大 小 和 作 圖 尺 寸 的 回 調(diào) 函 數(shù)。 在MFC 中 應(yīng) 該 由WM_SIZ 消 息 的 處 理 函 數(shù) 來 完 成。 在ANSI C 的OpenGL 編 程 中, 由EauxMainLoop 定 義 作 圖 的 回 調(diào) 函 數(shù)。 在MFC 中 應(yīng) 該 由WM_PAINT 消 息 的 處 理 函 數(shù) 來 處 理。 相 應(yīng) 的, 由OpenGL 定 義 的 鍵 盤、 鼠 標(biāo) 處 理 函 數(shù) 都 應(yīng) 該 由 相 應(yīng) 的Windows 處 理 函 數(shù) 來 響 應(yīng)。
---- 3. OpenGL 自 己 有 刷 新 背 景 的 函 數(shù)glClear, 故 而 應(yīng) 禁 止Windows 刷 新 窗 口 背 景。 否 則, 當(dāng) 窗 口 需 要 重 畫 時(shí),Windows 會(huì) 自 動(dòng) 先 發(fā) 送WM_ERASEBKGND, 而 缺 省 的 處 理 函 數(shù) 使 用 白 色 的 背 景 刷。 當(dāng)OpenGL 使 用 的 背 景 顏 色 不 是 白 色 時(shí), 作 圖 時(shí) 有 一 幀 白 色 的 閃 爍。 這 種 現(xiàn) 象 在 做 動(dòng) 畫 時(shí) 特 別 明 顯。 程 序 中 只 需 要 在WM_ERASEBKGND 的 消 息 處 理 函 數(shù) 中 禁 止 父 窗 口 類 的 消 息 處 理, 簡(jiǎn) 單 的 返 回 一 個(gè)TRUE 即 可。
---- 4. 由 于OpenGL 的 跨 平 臺(tái) 性, 它 必 須 用 操 作 系 統(tǒng) 的 調(diào) 色 板。 所 以 如 果GL_INDEX_MODE 作 圖 時(shí), 必 須 用VC 自 己 定 義 調(diào) 色 板。 不 過 一 般 情 況 下, 用GL_RGBA_MODE 模 式 比 較 方 便, 很 少 用 到GL_INDEX_MODE 模 式。
---- 5. 在OpenGL 作 圖 期 間,RC 對(duì) 應(yīng) 的DC 不 能 刪 除 或 者 釋 放。
---- 6. 由 于OpenGL 作 圖 時(shí) 需 要 長(zhǎng) 時(shí) 間 占 用DC, 所 以 最 好 把 作 圖 窗 口 類 設(shè) 成CS_OWNDC。MFC 缺 省 的 窗 口 類 風(fēng) 格 中 沒 有 設(shè) 這 一 屬 性, 程 序 中 在 主 窗 口C++ 類 的PreCreateWindow 方 法 中 自 己 注 冊(cè) 了 一 個(gè) 窗 口 類, 除 了 設(shè) 定 了CS_OWNDC 屬 性 以 外, 還 設(shè) 定 了CS_HREDRAW、CS_VREDRAW 和CS_SAVEBITS。 設(shè) 定CS_HREDRAW、CS_VREDRAW 是 為 了 讓 窗 口 縮 放 時(shí) 產(chǎn) 生WM_PAINT 消 息, 修 正OpenGL 視 口 和 作 圖 尺 寸; 由 于OpenGL 作 圖 需 要 很 多 計(jì) 算, 設(shè) 定CS_SAVEBITS 是 為 了 在OpenGL 窗 口 被 遮 蓋 后 顯 現(xiàn) 出 來 時(shí), 不 產(chǎn) 生WM_PAINT 消 息, 用 內(nèi) 存 存 儲(chǔ) 的 圖 象 來 填 充, 從 而 用 空 間 消 耗 換 取 計(jì) 算 時(shí) 間。
---- 7. 本 程 序 中 沒 有 對(duì)OpenGL 函 數(shù) 的 出 錯(cuò) 情 況 作 出 處 理。OpenGL 出 錯(cuò) 后 返 回 錯(cuò) 誤 碼, 不 會(huì) 拋 出 異 常; 而 且 在 某 一 個(gè) 函 數(shù) 出 錯(cuò) 以 后, 后 繼 函 數(shù) 也 一 般 不 會(huì) 出 現(xiàn) 異 常, 只 是 返 回 錯(cuò) 誤 碼, 一 不 小 心 就 可 能 忽 略 某 些 錯(cuò) 誤。 而 對(duì) 每 一 個(gè)OpenGL 函 數(shù) 都 做 出 錯(cuò) 與 否 的 判 斷 比 較 麻 煩, 所 以 編 程 序 時(shí) 對(duì)OpenGL 的 函 數(shù) 應(yīng) 當(dāng) 非 常 小 心。
---- 參 考 書 籍:
---- 《OpenGL Programmer's Guide》 SGI inc.
---- 《OpenGL 三 維 圖 形 程 序 設(shè) 計(jì)》 廖 朵 朵、 張 華 軍 著, 星 球 地 圖 出 版 社
---- 《Visual C++ 5.0 聯(lián) 機(jī) 幫 助》
---- 附 程 序:
---- 程 序 運(yùn) 行 時(shí) 必 須 確 定OpenGL32.dll、glu.dll、glaux.dll 在Windows 的System 目 錄 下。 如 果 找 不 到 這 些 文 件, 可 以 從Windows 95 OSR2 的 機(jī) 器 上 面 將 這 些 文 件 拷 貝 過 來 即 可。 OpenGL 運(yùn) 行 不 需 要 注 冊(cè) 庫(kù) 信 息。 在VC 的STUDIO 中 運(yùn) 行 程 序 時(shí), 工 程 文 件 中 必 須 加 入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_)
主窗口類的實(shí)現(xiàn)(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);//在客戶區(qū)作圖
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模式,不用調(diào)色板
16, //程序在16位色彩下運(yùn)行
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接近的位圖結(jié)構(gòu)");
return -1;
}
if (SetPixelFormat(m_pDC- >
GetSafeHdc(), pixelformat, &pfd) == FALSE)
{
MessageBox("無法在該DC上設(shè)置位圖結(jié)構(gòu)");
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窗口構(gòu)造成功
}
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
}
應(yīng)用程序類的定義(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_)
應(yīng)用程序類的實(shí)現(xiàn)(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;
聯(lián)系客服