正文

OpenGL基本框架2006-08-05 21:25:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/vfdff/17303.html

分享到:

摘于:http://cracker007.programfan.com       

 

 对于windows下的编程,似乎无论是win32 app还是dll,或者mfc,最重要的,也是最难的,都是那个框架。OpenGL也是如此。好在我已经饱经mfc的洗礼,明白如何下手分析框架。不过发现网上的很多程序框架都不是完全一样,不知道这里有没有什么标准?有些代码段去掉之后也仍然没有问题的。这似乎印证了csdn上的一句话:OpenGL出了错,什么都不会做; DirectX出了错,什么都做的出来。^-^

研究了很多例子之后,我自己总结出了一个最简单、易懂的通用框架,并且给出了重要部分的注释:
 
/******************************by CRACKER007*******************************/
 
 
BOOL CGdlg::InitialPixelFormat()    //此函数被后面的CreateRC调用
{
 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用来选择与pDC最匹配的硬件像素格式
 if((pixelformat=ChoosePixelFormat(pDC->GetSafeHdc(),&pfd))==0)
 {
  MessageBox("ChoosePixelFormat failed");
  return FALSE;
 }
 if(SetPixelFormat(pDC->GetSafeHdc(),pixelformat,&pfd)==FALSE)
 {
  MessageBox("SetPixelFormat failed");
  return FALSE;
 }
 return TRUE;
}
----------------------------------------------------------------------------
void CGdlg::CreateRC()    //创建RC的一系列操作
{
 PIXELFORMATDESCRIPTOR pdf; 
 int n;
 HGLRC hrc;  //rc句柄
 pDC=new CClientDC(this);  //pDC声明于类定义中: CClientDC *pDC
 ASSERT(pDC!=NULL);
 if(!InitialPixelFormat())  //调用前面定义的函数设置像素格式
 {
  return;
 }
 n=::GetPixelFormat(pDC->GetSafeHdc()); //这两行用于测试像素格式
 ::DescribePixelFormat(pDC->GetSafeHdc(),n,sizeof(pfd),&pfd);
 hrc=wglCreateContext(pDC->GetSafeHdc());//创建rc
 wglMakeCurrent(pDC->GetSafeHdc(),hrc); //使rc当前化
}
---------------------------------------------------------------------------
void CGdlg::FirstDraw()   //初始化
{
        glClearDepth(1.0f);  //设置深度缓存
        glEnable(GL_DEPTH_TEST);  //启用深度测试
        glDepthFunc(GL_LEQUAL);  //深度测试的类型
        glMatrixMode(GL_MODELVIEW);
 glLoadIdentity();
}
---------------------------------------------------------------------------
void CGdlg::ReleaseRC()    //释放RC
{
 HGLRC hrc;
 hrc=::wglGetCurrentContext();
 ::wglMakeCurrent(NULL,NULL);
 if(hrc)
 {
  ::wglDeleteContext(hrc);
 }
 if(pDC)
 {
  delete pDC;
 }
}
----------------------------------------------------------------------------
void CGdlg::ReDraw()    //用于OnDraw/OnPaint
{
 static BOOL bBusy=FALSE;
 if(bBusy)
 {
  return;
 }
        bBusy=TRUE;
 glClearColor(0.2f,0.2f,0.5f,1.0f);  //设置背景色
 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);//刷新深度缓存
                                                         //以及背景色    
        glMatrixMode(GL_MODELVIEW);
 glLoadIdentity();
 //DrawOG();       //具体绘图(如果用glClearColor设置了背景色,
                          //那么要记得用glClear刷新
 glFinish();
 SwapBuffers(wglGetCurrentDC());
 bBusy=FALSE;
}
---------------------------------------------------------------------------
开始OpenGl操作所对应的消息函数内容应该包含:
CreateRC();
FirstDraw();
Invalidate(); (或者RedrawWindow(),关于两者的区别,请看注)
----------------------------------------------------------------------------
结束OpenGl操作所对应的消息函数内容应该包含:
ReleaseRC();
----------------------------------------------------------------------------
OnDraw/OnPaint的内容应该包含:
ReDraw();
----------------------------------------------------------------------------
注一:
1 使用Invalidate(..)可以触发WM_PAINT,但系统并不立即重绘,这是因为WM_PAINT的2个特性:low priority、Windows combines multiple WM_PAINT messages in the  message queue into a single message, 如果想立即重绘,那么就需要调用UpdateWindow();
2 RedrawWindow()可以实现立即重绘;
3 如果更新的是一个区域RGN的时候它没法调用Invalidate实现,因为Invalidate只对矩形有效,但是RedrawWindow可以。
注二:
如果要使用GDI函数,必须在glFinish()和SwapBuffers(wglGetCurrentDC())函数之后调用,否则会产生闪烁。
如果一定要在绘制OpenGL结束之前使用GDI函数,那么想要除去闪烁则只能使用SingleBuffer模式。

阅读(417) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册