OpenGL是一个优秀的专业化的3D的API(Application Programming Interface,应用编程接口)
下面通过一个简单的例子说明如何在MFC中建立OpenGL的视场
1.建立一个单文档工程Point
2.单击Project菜单中的Setting...命令,打开Project Setting对话框,单击Link属性页,在Object/library modules中加入opengl32.lib glu32.lib
3.在PointView.cpp文件中加入头文件:
#include "gl/gl.h"
#include "gl/glu.h"
4.在PointView.h文件中加入所需的成员变量和函数:
public:
CClientDC *m_pDC;
void Init();
BOOL bSetupPixelFormat(void);
void DrawScene(void);
5.在PointView.cpp文件中,在CPointView的构造函数中加入:
m_pDC=NULL;
6.在PointView.cpp文件中,加入相应的成员函数:
void CPointView::Init()
{
PIXELFORMATDESCRIPTOR pfd;
int n;
HGLRC hrc;
m_pDC=new CClientDC(this);
ASSERT(m_pDC != NULL);
if(!bSetupPixelFormat())
return;
n=::GetPixelFormat(m_pDC->GetSafeHdc());
::DescribePixelFormat(m_pDC->GetSafeHdc(), n,sizeof(pfd),&pfd);
hrc=wglCreateContext(m_pDC->GetSafeHdc());
wglMakeCurrent(m_pDC->GetSafeHdc(),hrc);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
}
BOOL CPointView::bSetupPixelFormat()
{
static PIXELFORMATDESCRIPTOR pfd =
{
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW |
PFD_SUPPORT_OPENGL|
PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
24,
0, 0, 0, 0, 0, 0,
0,
0,
0,
0, 0, 0, 0,
32,
0,
0,
PFD_MAIN_PLANE,
0,
0, 0, 0
};
int pixelformat;
if((pixelformat = ChoosePixelFormat(m_pDC->GetSafeHdc(), &pfd)) == 0)
{
MessageBox("ChoosePixelFormat failed");
return FALSE;
}
if(SetPixelFormat(m_pDC->GetSafeHdc(), pixelformat, &pfd) == FALSE)
{
MessageBox("SetPixelFormat failed");
return FALSE;
}
return TRUE;
}
void CPointView::DrawScene(void)
{
//设置清屏颜色为黑色
glClearColor(0.0f,0.0f,0.0f,0.0f);
//清除颜色缓冲区和深度缓冲区
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//矩阵堆栈函数,和glPopMatrix()相对应
glPushMatrix();
//设置点的大小
glPointSize(10.0);
//说明几何图元为“点”,和glEnd()相对应
glBegin(GL_POINTS);
//绘制红色的点
glColor3f(1.0,0.0,0.0);
glVertex3f(-0.7,-0.7,0.0);
//绘制绿色的点
glColor3f(0.0,1.0,0.0);
glVertex3f(0.7,-0.7,0.0);
//绘制白色的点
glColor3f(1.0,1.0,1.0);
glVertex3f(0.0,0.0,0.0);
//绘制兰色的点
glColor3f(0.0,0.0,1.0);
glVertex3f(0.7,0.7,0.0);
//绘制黄色的点
glColor3f(1.0,1.0,0.0);
glVertex3f(-0.7,0.7,0.0);
glEnd();
glPopMatrix();
glFinish();
SwapBuffers(wglGetCurrentDC());
}
7.在PointView.cpp文件中,在PreCreateWindow函数中加入:
cs.style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
8.在PointView.cpp文件中,在OnDraw函数中加入:
DrawScene();
9.在CPointView中,建立如下消息的映射函数:WM_CREATE, WM_DESTROY, WM_SIZE, WM_ERASEBKGND,并加入划线的代码,如下所示:
int CPointView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
Init();
return 0;
}
void CPointView::OnDestroy()
{
CView::OnDestroy();
// TODO: Add your message handler code here
HGLRC hrc;
hrc = ::wglGetCurrentContext();
::wglMakeCurrent(NULL,NULL);
if(hrc)
::wglDeleteContext(hrc);
if(m_pDC)
delete m_pDC;
}
BOOL CPointView::OnEraseBkgnd(CDC* pDC)
{
return TRUE;
}
void CPointView::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy);
// TODO: Add your message handler code here
int w=cx;
int h=cy;
GLfloat nRange=1.0f;
//避免除数为0
if(h==0)
h=1;
//设置视口与窗口匹配
glViewport(0,0,w,h);
//重新设置坐标系统
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//建立正交变换下的剪切体
if(w
else
glOrtho(-nRange*w/h,nRange*w/h,-nRange,nRange,-nRange,nRange);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
运行程序后,如果你能看到五个点,那就表明你现在已经建立起OpenGL的视场了。
Windows应用程序是使用设备描述表(Device Context)进行图形的绘制输出,但OpenGL并不使用标准的设备描述表,它使用渲染描述表(Rendering Context)完成图形图像的映射。描述表的映射核心是像素格式的设置。
当进行OpenGL的绘图操作时,实际上是在进行设备像素的操作。OpenGL将数据转化为像素操作写入帧缓存中,就需要知道Windows的像素格式,或者说需要与其一致起来。在初始化OpenGL时,需要一个叫做PIXELFORMATDESCRIPTOR的结构来完成对像素属性的设置。Win32提供了4个函数管理像素格式。
①ChoosePixelFormat():返回和&pfd指定的像素格式最匹配的DC支持的像素格式的索引值,如果函数调用不成功,返回零。
②SetPixelFormat():在DC中设置pixelformat指定的设备的像素格式,如果函数调用成功,返回TRUE。
③GetPixelFormat():返回当前DC的像素格式的索引,如果函数调用不成功,返回零。
④DescribePixelFormat():用n指定的DC的像素格式的数据设置&pfd,如果函数调用成功,返回DC的像素格式的最大索引,否则,返回零。
OpenGL的渲染描述表保存着在窗口中用来渲染一个场景所需的信息。一个OpenGL应用程序必须有一个渲染描述表,并且在OpenGL进行绘制之前它应该是当前的。在渲染描述表存入信息后,OpenGL就可以在Windows系统中更新一个窗口的图形状态。Win32提供了5个函数管理渲染描述表。
①wglCreateContext():创建一个与给定的DC兼容的RC,调用成功返回RC的句柄,不成功返回NULL。
②wglMakeCurrent():使指定的RC成为当前的,调用成功返回GL_TRUE,否则返回GL_FALSE。
③wglGetCurrentCotext():获得当前的RC句柄。
④wglGetCurrentDC():获得和当前的RC联系的DC句柄。
⑤wglDeleteContext():删除RC。