如何在mfc中进行opengl编程初始化环境

 我来答
time陌言成殇
2015-01-29 · TA获得超过8.4万个赞
知道大有可为答主
回答量:1.4万
采纳率:91%
帮助的人:9428万
展开全部

您好,很高兴为您解答。


1:新建一个MFC的工程,单文档的工程。


2:工程建好之后,可以先编译运行一下。下面就是要把View的窗口初始化为OpenGL的编程环境。当然以下所有的操作都是在View类中进行的。
先在Project->Settings->Link中,加上opengl32.lib
glu32.lib glut.lib glaux.lib,然后在View.h的类定义中加上如下引用。

#include <gl\gl.h>

#include <gl\glu.h>   

#include <gl\glaux.h>

3:首先要让窗口支持OpenGL,那就必须要对PIXELFORMATDESCRIPTOR这个结构有所了解,先在View类中新建一个函数SetupPixFormat(CDC
*pDC),类型:看下面的函数就知道为BOOL,(方法:在classview中,找到**view类,鼠标右击,添加函数)公有私有无所谓,如下:

BOOL 
CTestGLInitialView::SetupPixFormat(CDC *pDC) 
//我建立的工程名叫TestGLInitial{static PIXELFORMATDESCRIPTOR pfd = 
//定义像素格式{   sizeof(PIXELFORMATDESCRIPTOR), // 
上述格式描述符的大小   1,         // 
版本号   PFD_DRAW_TO_WINDOW |    // 
格式支持窗口   PFD_SUPPORT_OPENGL |    // 
格式必须支持OpenGL   PFD_DOUBLEBUFFER,     // 
必须支持双缓冲   PFD_TYPE_RGBA,      // 申请 RGBA 
格式   24,         // 
24位色彩深度,即1.67千万的真彩色   0, 0, 0, 0, 0, 0,     // 
忽略的色彩位   0,         // 
无Alpha缓存   0,         // 
忽略Shift Bit   0,         
// 无累加缓存   0, 0, 0, 0,       // 
忽略聚集位   32,         // 32位 
Z-缓存 (深度缓存)   0,         
// 无蒙板缓存   0,         // 
无辅助缓存   PFD_MAIN_PLANE,      // 
主绘图层   0,         // 
Reserved   0, 0, 0        // 
忽略层遮罩};
int nIndex = ChoosePixelFormat(pDC->GetSafeHdc(), &pfd); 
//选择刚刚定义的像素格式if( nIndex == 0 ) return FALSE;return 
SetPixelFormat(pDC->GetSafeHdc(), nIndex, &pfd);   
//设置像素格式}


这个函数的主要目的就是设置窗口的像素格式,使之支持OpenGL,明白这点就行了。在创建窗口的时候,调用这个函数。


5:刚刚那个函数是用来在创建窗口是调用的,在创建窗口时,还需要对OpenGL的环境做一些初始化,再定义一个函数InitialGL(),(方法:在classview中,找到**view类,鼠标右击,添加函数)公有私有也无所谓,反正是自己调用的,如下:

BOOL 
CTestGLInitialView::InitialGL()
{
glShadeModel(GL_SMOOTH);           
// 启用阴影平滑
glClearColor(0.0f, 0.0f, 0.0f, 
0.0f);       // 
黑色背景
glClearDepth(1.0f);                            
// 
设置深度缓存
glEnable(GL_DEPTH_TEST);             
// 
启用深度测试
glDepthFunc(GL_LEQUAL);              
// 所作深度测试的类型
glHint(GL_PERSPECTIVE_CORRECTION_HINT, 
GL_NICEST);    // 告诉系统对透视进行修正
return 
TRUE;                                      
// 初始化 OK
}


这里的代码我都是抄的NeHe教程上面的代码。


6:现在可以捕获WM_CREATE消息了(方法:view-->classvizard -->messages
maps:classname
选**view,找到WM_CREATE,添加函数,编辑代码)。但是,还要先定义一个CClientDC*的成员,(方法:在classview中,找到**view类,鼠标右击,添加函数成员变量。类型:CClientDC*,名字:m_pDC)这个成员指向View窗口自己,是用来传递给SetupPixFormat(CDC
*pDC)函数的,没别的意思。


现在,来捕获WM_CREATE消息(),写上如下代码:

int 
CTestGLInitialView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if 
(CView::OnCreate(lpCreateStruct) == -1)
   return -1;
// 
TODO: Add your specialized creation code here
m_pDC = new 
CClientDC(this);
SetupPixFormat(m_pDC);
HGLRC hrc = 
wglCreateContext(m_pDC->GetSafeHdc());
wglMakeCurrent(m_pDC->GetSafeHdc(), 
hrc);
InitialGL();
return 
0;
}


当然,当窗口关闭的时候,还应该要释放一些资源。捕获WM_DESTROY消息,(方法:view-->classvizard
-->messages maps:classname 选**view,找到WM_DESTROY,添加函数,编辑代码)写下如下代码:

void 
CTestGLInitialView::OnDestroy()
{
CView::OnDestroy();
// TODO: Add 
your message handler code here
HGLRC hrc = 
wglGetCurrentContext();
wglMakeCurrent(NULL, 
0);
wglDeleteContext(hrc);
delete 
m_pDC;
}


现在可以编译一下了,没有错误。


7:现在,OpenGL的环境已经初始化差不多了。可以开始做图了,先定义一个作图的函数DrawScene(),写上如下的代码:

BOOL 
CTestGLInitialView::DrawScene()
{
glClear(GL_COLOR_BUFFER_BIT | 
GL_DEPTH_BUFFER_BIT);    // 
清除屏幕和深度缓存
glLoadIdentity();            
// 
重置当前的模型观察矩阵
SwapBuffers(m_pDC->GetSafeHdc());        
// 交换缓冲区
return TRUE;
}


然后,要在OnDraw中,调用这个函数:

void 
CTestGLInitialView::OnDraw(CDC* pDC)
{
CTestGLInitialDoc* pDoc = 
GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data 
here
DrawScene();
}


8:运行一下,黑色的背景出来了。


9:这时,可以修改DrawScene()这个作图函数,作图。画出NeHe第3课的那个三角形和正方形来。写代码如下:

BOOL 
CTestGLInitialView::DrawScene(){glClear(GL_COLOR_BUFFER_BIT | 
GL_DEPTH_BUFFER_BIT);    // 
清除屏幕和深度缓存glLoadIdentity();            
// 重置当前的模型观察矩阵
glTranslatef(-1.5f,0.0f,-6.0f);       // 左移 
1.5 单位,并移入屏幕 
6.0glBegin(GL_TRIANGLES);         // 
绘制三角形glColor3f(1.0f, 0.0f, 0.0f);glVertex3f( 0.0f, 1.0f, 
0.0f);       // 上顶点glColor3f(0.0f, 1.0f, 
0.0f);glVertex3f(-1.0f,-1.0f, 0.0f);       // 
左下glColor3f(0.0f, 0.0f, 1.0f);glVertex3f( 1.0f,-1.0f, 
0.0f);       // 
右下glEnd();            
// 
三角形绘制结束glTranslatef(3.0f,0.0f,0.0f);       
// 右移3单位glColor3f(0.0f, 0.0f, 
1.0f);glBegin(GL_QUADS);          
// 绘制正方形glVertex3f(-1.0f, 1.0f, 0.0f);       
// 左上glVertex3f( 1.0f, 1.0f, 0.0f);       // 
右上glVertex3f( 1.0f,-1.0f, 0.0f);       // 
左下glVertex3f(-1.0f,-1.0f, 0.0f);       // 
右下   
glEnd();SwapBuffers(m_pDC->GetSafeHdc());        
// 交换缓冲区return TRUE;}


   
运行一下,发现图形没有出现,这个怎么回事呢。原来是因为还没有定义投影方式和视口。即用正交投影还是透视投影。定义投影,还要捕获WM_SIZE消息。写如下代码:

void 
CTestGLInitialView::OnSize(UINT nType, int cx, int 
cy)
{
CView::OnSize(nType, cx, cy);
// TODO: Add your message 
handler code here
if (0 == 
cy)         // 
防止被零除
{
   cy = 
1;          // 
将Height设为1
}
glViewport(0, 0, cx, cy);      
// 重置当前的视口
glMatrixMode(GL_PROJECTION);     // 
选择投影矩阵
glLoadIdentity();        // 
重置投影矩阵
// 
设置视口的大小
gluPerspective(45.0f,(GLfloat)cx/(GLfloat)cy,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW);      
// 选择模型观察矩阵
   
glLoadIdentity();        // 
重置模型观察矩阵
}


   
再运行一下,图形已经出来了。以后,就可以在DrawScene()写任何画图的代码了,当窗口重绘的时候,都可以自动适应。如果要做一段可以运动的3D图画,可以再捕获WM_TIMER消息,通过在OnCreate的时候定义一个时钟,再配合一些变量,就可以做简单的动画了


如若满意,请点击右侧【采纳答案】,如若还有问题,请点击【追问】


希望我的回答对您有所帮助,望采纳!


                                                                                                                             ~ O(∩_∩)O~

推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式