本文以SDI文档结构为例,列出绘制OpenGL图形的关键步骤;
(1)在单文档窗口的创建过程中设置好显示的像素格式,并按OpengL的要求设置好窗口的属性和风格
(2)获得Windows设备描述表CDC的成员变量,然后将其与OpengL的绘制描述表RC联系起来
(3)调用OpenGL命令进行图形绘制
(4)退出OpengL图形窗口时,释放OpengL的绘制描述表RC和Windows设备描述表DC
手动添加的代码用magenta表示。这里先叙述一下创建步骤:
1.新建一个MFC向导程序,命名为GLFrame,单文档,去除打印支持,其余默认,生成一个OpenGL框架.
2.得到简单的窗口风格.
在CMianFrame中添加PreCreateWindow的代码:
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
if( !CFrameWnd::PreCreateWindow(cs) )
return FALSE;
cs.cx =500;
cs.cy =400;
cs.lpszName =_T("OpenGL 框架程序");
cs.style &=~FWS_ADDTOTITLE;//不把标题加到标题栏
return TRUE;
}
3.添加OpenGL支持:
在CGLFrameView.h中添加头文件如下:
#include "gl\gl.h"
#include "gl\glu.h"
#include "gl\glaux.h"
在工程->设置->Project Settings对话框话中选择Link选项卡,在对象模块库中加入glaux.lib glu32.lib opengl32.lib .
(TIP:当然,你也可以选择工程->添加到工程->添加文件命令,弹出的Insert Files into Project对话框中,转换到VC98\lib目录下面,选中glaux.lib , glu32.lib, opengl32.lib 这几个文件,按下OK,把它们添加到项目文件.)
以下操作均在CGLFrameView中进行
4.给视图添加一个RC句柄和DC句柄,一个protected的变量
class CGLFrameView:public CView
{
protected:
...//其他变量
HGLRC m_hrc;
CClientDC *m_pDC;
...//其他变量
}
5.给视图添加消息处理:
添加WM_CREATE,WM_DESTROY,WM_SIZE,WM_PAINT,WM_ERASEBKGND 这5个消息的处理函数.
6.修改CGFrameView的PreCreateWindow() 函数如下:
BOOL CGLFrameView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
cs.style |=WS_CLIPSIBLINGS|WS_CLIPCHILDREN; //不要画到兄弟窗口或子窗口
return CView::PreCreateWindow(cs);
}
7.修改CGFrameView的OnCreate()函数如下: ------------作用是设置RC的像素格式
int CGLFrameView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
//===================================
int pixelformat;
m_pDC = new CClientDC(this);//在客户区作图,获得设备描述表DC
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 ) //测试硬件是否支持该pdf
{
MessageBox("在该DC上找不到与PFD接近的位图结构");
return -1;
}
if (SetPixelFormat(m_pDC->GetSafeHdc(), pixelformat, &pfd) == FALSE)//测试硬件是否支持该pdf
{
MessageBox("无法在该DC上设置位图结构");
return -1;
}
m_hrc = wglCreateContext(m_pDC->GetSafeHdc());//将RC与DC联系起来
wglMakeCurrent(m_pDC->GetSafeHdc(), m_hrc);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
return 0; //OpenGL窗口构造成功
}
8.修改CGFrameView的OnDestroy()函数如下:
void CGLFrameView::OnDestroy()
{
CView::OnDestroy();
// TODO: Add your message handler code here
if(wglGetCurrentContext()!=NULL) //释放RC以及DC
::wglMakeCurrent(NULL, NULL);
if (m_hrc)
::wglDeleteContext(m_hrc);
if (m_pDC)
delete m_pDC;}
9.修改CGFrameView的OnSize()函数如下:
void CGLFrameView::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy);
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);
}
}
10.修改CGFrameView的OnPaint()函数如下
void CGLFrameView::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 CView::OnPaint() for painting messages
}
11.修改CGFrameView的OnEraseBkgnd()函数如下
BOOL CGLFrameView::OnEraseBkgnd(CDC* pDC)
{
// TODO: Add your message handler code here and/or call default
return TRUE; //消除屏幕闪烁
//return CView::OnEraseBkgnd(pDC);
}
以上是用OpenGL编程所必须做好的基本工作^_*,希望对大家有帮助!