学习OpenGL过程中
所编写的学习程序,从网上搜集整理改写而成,如果你第一次接触OpenGL,希望这个例子对你有所帮助,欢迎同行共同探讨。
在Dialog中的控件上画一个简单的四棱锥,如下图所示,
首先,在stdafx.h文件中包含相关头文件gl.h和glu.h,
然后,在项目属性页中添加opengl32.lib和glu32.lib,
所需的动态连接库opengl32.dll和glu32.dll位于目录c:\windows\system32下,
相关代码如下,
// FirstOpenGl.cpp : 定义应用程序的类行为。
#include "stdafx.h"
#include "FirstOpenGl.h"
#include "MainFrm.h"
#include "FirstOpenGlDoc.h"
#include "FirstOpenGlView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
///////////////////////////////////////////////////////////////////////////////
// CFirstOpenGlApp
BEGIN_MESSAGE_MAP(CFirstOpenGlApp, CWinApp)
ON_COMMAND(ID_APP_ABOUT, &CFirstOpenGlApp::OnAppAbout)
// 基于文件的标准文档命令
ON_COMMAND(ID_FILE_NEW, &CWinApp::OnFileNew)
ON_COMMAND(ID_FILE_OPEN, &CWinApp::OnFileOpen)
END_MESSAGE_MAP()
///////////////////////////////////////////////////////////////////////////////
// CFirstOpenGlApp 构造
CFirstOpenGlApp::CFirstOpenGlApp()
{ // TODO: 在此处添加构造代码,
// 将所有重要的初始化放置在 InitInstance 中
}
///////////////////////////////////////////////////////////////////////////////
// 唯一的一个 CFirstOpenGlApp 对象
CFirstOpenGlApp theApp;
///////////////////////////////////////////////////////////////////////////////
// CFirstOpenGlApp 初始化
BOOL CFirstOpenGlApp::InitInstance()
{ // 如果一个运行在 Windows XP 上的应用程序清单指定要
// 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,
//则需要 InitCommonControlsEx()。否则,将无法创建窗口。
INITCOMMONCONTROLSEX InitCtrls;
InitCtrls.dwSize = sizeof(InitCtrls);
// 将它设置为包括所有要在应用程序中使用的
// 公共控件类。
InitCtrls.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&InitCtrls);
CWinApp::InitInstance();
// 初始化 OLE 库
if (!AfxOleInit())
{ AfxMessageBox(IDP_OLE_INIT_FAILED);
return FALSE;
}
AfxEnableControlContainer();
// 标准初始化
// 如果未使用这些功能并希望减小
// 最终可执行文件的大小,则应移除下列
// 不需要的特定初始化例程
// 更改用于存储设置的注册表项
// TODO: 应适当修改该字符串,
// 例如修改为公司或组织名
SetRegistryKey(_T("应用程序向导生成的本地应用程序"));
LoadStdProfileSettings(4); // 加载标准 INI 文件选项(包括 MRU)
// 注册应用程序的文档模板。文档模板
// 将用作文档、框架窗口和视图之间的连接
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CFirstOpenGlDoc),
RUNTIME_CLASS(CMainFrame), // 主 SDI 框架窗口
RUNTIME_CLASS(CFirstOpenGlView));
if (!pDocTemplate)
return FALSE;
AddDocTemplate(pDocTemplate);
// 分析标准外壳命令、DDE、打开文件操作的命令行
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
// 调度在命令行中指定的命令。如果
// 用 /RegServer、/Register、/Unregserver 或 /Unregister 启动应用程序,则返回 FALSE。
if (!ProcessShellCommand(cmdInfo))
return FALSE;
// 唯一的一个窗口已初始化,因此显示它并对其进行更新
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();
// 仅当具有后缀时才调用 DragAcceptFiles
// 在 SDI 应用程序中,这应在 ProcessShellCommand 之后发生
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////
// 用于应用程序“关于”菜单项的 CAboutDlg 对话框
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// 对话框数据
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
virtual BOOL OnInitDialog();
// 实现
protected:
DECLARE_MESSAGE_MAP()
public:
GLfloat fRotate;
HDC hDC1;
HWND hEdit1;
HGLRC hRC1;
BOOL SetWindowPixelFormat(HDC hDC);
void RenderScene();
afx_msg void OnBnClickedOk();
afx_msg void OnClose();
afx_msg void OnDestroy();
afx_msg void OnPaint();
afx_msg void OnTimer(UINT_PTR nIDEvent);
};
///////////////////////////////////////////////////////////////////////////////
// 用于运行对话框的应用程序命令
void CFirstOpenGlApp::OnAppAbout()
{ CAboutDlg aboutDlg;
aboutDlg.DoModal();
}
///////////////////////////////////////////////////////////////////////////////
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
ON_WM_CLOSE()
ON_WM_DESTROY()
ON_WM_PAINT()
ON_WM_TIMER()
ON_BN_CLICKED(IDOK, &CAboutDlg::OnBnClickedOk)
END_MESSAGE_MAP()
///////////////////////////////////////////////////////////////////////////////
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{ fRotate = 10.0f; // rotation
hDC1 = NULL;
hEdit1 = NULL;
hRC1 = NULL;
}
///////////////////////////////////////////////////////////////////////////////
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{ CDialog::DoDataExchange(pDX);
}
///////////////////////////////////////////////////////////////////////////////
BOOL CAboutDlg::OnInitDialog()
{ CDialog::OnInitDialog();
//TODO: 在此添加额外的初始化
CEdit *pScene = (CEdit *)GetDlgItem(IDC_TEST);
ASSERT(pScene);
hEdit1 = pScene->GetSafeHwnd();
hDC1 = pScene->GetDC()->GetSafeHdc();
// OpenGL Initialization
glShadeModel(GL_SMOOTH); // Enable Smooth Shading
glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black Background
glClearDepth(1.0f); // Depth Buffer Setup
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
SetWindowPixelFormat(hDC1);
hRC1 = wglCreateContext(hDC1);
wglMakeCurrent(hDC1, hRC1);
glDrawBuffer(GL_BACK);
SetTimer(1, 1, NULL); // 在中OnTimer()绘图
return TRUE; // return TRUE unless you set the focus to a control
// 异常: OCX 属性页应返回 FALSE
}
///////////////////////////////////////////////////////////////////////////////
// CFirstOpenGlApp 消息处理程序
void CAboutDlg::OnBnClickedOk()
{ // TODO: 在此添加控件通知处理程序代码
OnOK();
}
///////////////////////////////////////////////////////////////////////////////
void CAboutDlg::OnClose()
{ // TODO: 在此添加消息处理程序代码和/或调用默认值
CDialog::OnClose();
}
///////////////////////////////////////////////////////////////////////////////
void CAboutDlg::OnDestroy()
{ CDialog::OnDestroy();
// TODO: 在此处添加消息处理程序代码
if(wglGetCurrentContext()!=NULL)
wglMakeCurrent(NULL, NULL);
if(hRC1!=NULL)
{ wglDeleteContext(hRC1);
hRC1 = NULL;
}
if(hEdit1!=NULL)
::ReleaseDC(hEdit1, hDC1);
}
///////////////////////////////////////////////////////////////////////////////
void CAboutDlg::OnPaint()
{ CPaintDC dc(this); // device context for painting
// TODO: 在此处添加消息处理程序代码
// 移到中 OnTimer(UINT_PTR nIDEvent) 处理
//RenderScene();
//SwapBuffers(hDC1);
// 不为绘图消息调用 CDialog::OnPaint()
}
///////////////////////////////////////////////////////////////////////////////
//BOOL CAboutDlg::SetWindowPixelFormat(HDC hDC)
//{ PIXELFORMATDESCRIPTOR pixelDesc;
// pixelDesc.nSize = sizeof(PIXELFORMATDESCRIPTOR);
// pixelDesc.nVersion = 1;
//
// //pixelDesc.dwFlags = PFD_DRAW_TO_WINDOW | PFD_DRAW_TO_BITMAP |
// // PFD_SUPPORT_OPENGL | PFD_SUPPORT_GDI | PFD_STEREO_DONTCARE;
// pixelDesc.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL |
// PFD_DOUBLEBUFFER | PFD_STEREO_DONTCARE;
// pixelDesc.iPixelType = PFD_TYPE_RGBA;
// pixelDesc.cColorBits = 32;
// pixelDesc.cRedBits = 8;
// pixelDesc.cRedShift = 16;
// pixelDesc.cGreenBits = 8;
// pixelDesc.cGreenShift = 8;
// pixelDesc.cBlueBits = 8;
// pixelDesc.cBlueShift = 0;
// pixelDesc.cAlphaBits = 0;
// pixelDesc.cAlphaShift = 0;
// pixelDesc.cAccumBits = 64;
// pixelDesc.cAccumRedBits = 16;
// pixelDesc.cAccumGreenBits = 16;
// pixelDesc.cAccumBlueBits = 16;
// pixelDesc.cAccumAlphaBits = 0;
// pixelDesc.cDepthBits = 32;
// pixelDesc.cStencilBits = 8;
// pixelDesc.cAuxBuffers = 0;
// pixelDesc.iLayerType = PFD_MAIN_PLANE;
// pixelDesc.bReserved = 0;
// pixelDesc.dwLayerMask = 0;
// pixelDesc.dwVisibleMask = 0;
// pixelDesc.dwDamageMask = 0;
//
// int m_GLPixelIndex = ChoosePixelFormat(hDC, &pixelDesc);
// if(m_GLPixelIndex==0) // Let's choose a default index.
// { m_GLPixelIndex = 1;
// if(DescribePixelFormat(hDC, m_GLPixelIndex, sizeof(PIXELFORMATDESCRIPTOR), &pixelDesc)==0)
// return FALSE;
// }
//
// if(SetPixelFormat(hDC, m_GLPixelIndex, &pixelDesc)==FALSE)
// return FALSE;
//
// return TRUE;
//}
BOOL CAboutDlg::SetWindowPixelFormat(HDC hDC)
{ PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
1, // version number
PFD_DRAW_TO_WINDOW | // support window
PFD_SUPPORT_OPENGL | // support OpenGL
PFD_DOUBLEBUFFER, // double buffered
PFD_TYPE_RGBA, // RGBA type
24, // 24-bit color depth
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
};
int iPixelFormat = 0;
// get the device context's best, available pixel format match
if((iPixelFormat = ChoosePixelFormat(hDC, &pfd))==0)
return FALSE;
// make that match the device context's current pixel format
if(SetPixelFormat(hDC, iPixelFormat, &pfd) == FALSE)
return FALSE;
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////
// we will draw a simple 3D-Triangle
void CAboutDlg::RenderScene()
{ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glRotatef(fRotate, 1.0f, 0.0f, 0.0f);
glBegin(GL_TRIANGLES);
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex3f(0, 0.8f, 0); // top
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex3f(-0.5f, -0.5f, 0.5); // left
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex3f(0.5f, -0.5f, 0.5f); // right
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex3f(0.0f, 0.8f, 0.0f); // Top Of Triangle (Right)
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex3f(0.5f, -0.5f, 0.5f); // Left Of Triangle (Right)
glColor3f(0.0f, 0.5f, 0.0f); // Green
glVertex3f(0.5f, -0.5f, -0.5f); // Right Of Triangle (Right)
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex3f(0.0f, 0.8f, 0.0f); // Top Of Triangle (Back)
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex3f(0.5f, -0.5f, -0.5f); // Left Of Triangle (Back)
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex3f(-0.5f, -0.5f, -0.5f); // Right Of Triangle (Back)
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex3f(0.0f, 0.8f, 0.0f); // Top Of Triangle (Left)
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex3f(-0.5f, -0.5f, -0.5f); // Left Of Triangle (Left)
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex3f(-0.5f, -0.5f, 0.5f); // Right Of Triangle (Left)
glEnd();
fRotate += 1.0f;
}
///////////////////////////////////////////////////////////////////////////////
void CAboutDlg::OnTimer(UINT_PTR nIDEvent)
{ // TODO: 在此添加消息处理程序代码和/或调用默认值
if(nIDEvent==1)
{ RenderScene();
SwapBuffers(hDC1);
}
CDialog::OnTimer(nIDEvent);
}
///////////////////////////////////////////////////////////////////////////////
可执行文件如下,
文章评论(0条评论)
登录后参与讨论