MFC中的OpenGL基本框架小结

开发环境:VS2013

操作系统:Windows7  


创建步骤:

一、创建MFC项目

当前笔者环境是 单文档、MFC界面风格,其他部分默认



二、工程属性设置

打开“链接器--输入”项
        在“附加依赖项”中增加:
        OpenGL32.lib
        glu32.lib
        glut32.lib


三、C***View.h文件中加入OpenGL头文件

注:glut.h头文件包含了头文件gl.h和glu.h

//OpenGL Headers

#include <gl/glut.h>

#include <gl/glaux.h>

MFC中的OpenGL基本框架小结_第1张图片

四、C***View.cpp文件中改写OnPreCreate函数



五、为视图类(View类)添加成员函数和成员变量

protected类型成员函数   BOOL C***View::SetWindowPixelFormat(HDC hDC)

成员变量    int   m_GLPixelIndex

(设置窗口像素格式)

protected类型成员函数   BOOL C***View::CreateViewGLContext(HDC hDC)

成员变量    HGLRC   m_hGLContext

(产生绘制环境RC并使之成为当前绘制环境)

注:两个成员变量在C***View中的构造函数中初始化

this->m_GLPixelIndex = 0;

this->m_hGLContex = NULL;

protected类型成员函数   BOOL C***View::DrawGLScene()

(所有绘图代码都在这里)

protected类型成员函数   BOOL C***View::InitGL(GLVoid)

(OPENGL初始化函数,对OpenGL 进行所有的设置,设置清除屏幕时所用的颜色、打开深度缓存,启用smooth shading (阴影平滑)等等:)

六、

1 添加WM_ERASEBACKGROUND的消息处理函数OnEraseBkgnd(CDC* pDC)

作用:防止闪屏。清屏的动作不由窗口去完成,而由OpenGL去完成。

BOOL C***View::OnEraseBkgnd(CDC* pDC) 
{
    //Tell Windows not to erase the background
    return TRUE;
}

2 添加WM_CREATE的消息处理函数OnCreate(LPCREATESTRUCT  lpCreateStruct)

OnCreate中完成的工作如下:当然我们也可以把设置像素格式的工作、创建RC(Render Context,绘图上下文)的工作放到InitGL()中

这里InitGL()完成的工作有

HWND hwnd = this->GetSafeHwnd();
HDC hDC = ::GetDC(hwnd);
this->SetWindowPixelFoemat(hDC) 
this->CreateViewGLContext(hDC) 
this->InitGL()

3 添加WM_DESTROY的消息处理函数OnDestroy()

  if(wglGetCurrentContext()!=NULL)
    {
        wglMakeCurrent(NULL,NULL);
    }
  if(this->m_hGLContext!=NULL)
   {
        wglDeleteContext(this->m_hGLContext);
        this->m_hGLContext = NULL;
    }

4 添加WM_SIZE的消息处理函数OnSize(UINT nType,int cx,int cy)

一般用来设置视口和视锥,因为这些和窗口大小相关。基本操作包括设置视口,选择投影矩阵,设置投影矩阵,设置模型视图矩阵。

void C****View::OnSize(UINT nType, int cx, int cy) 
{
    CView::OnSize(nType, cx, cy);
    
    // TODO: Add your message handler code here
    GLsizei width,height;
    GLdouble aspect;
    width = cx;
    height = cy;
    if(cy==0)
    {
        aspect = (GLdouble)width;
    }
    else
    {
        aspect = (GLdouble)width/(GLdouble)height;
    }
    glViewport(0,0,width,height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0.0,500.0*aspect,0.0,500.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
} 

glViewport(0,0,width,height)定义了视口和视口坐标。

函数原型为glViewport(GLint x,GLint y,GLsizei width,GLsizei height)

x,y以像素为单位,指定了视口的左上角位置

width,height表示这个视口矩形的宽度和高度,根据窗口的实时变化重绘窗口。

关于此部分的进一步解释参考《OpenGL编程指南》第三章 视图

glMatrixMode()是用来设置矩阵模式,三个选项分别为GL_PROJECTION(投影)、GL_MODELVIEW(模型视图)、GL_TEXTURE(纹理)

对应的随后操作矩阵是投影矩阵、模型矩阵、纹理矩阵。

glMatrixMode(GL_PROJECTION);//将当前矩阵指定为投影矩阵

glLoadIdentity();//把矩阵设为单位矩阵

然后调用glFrustum()或gluPerspective(),它们生成的矩阵会与当前的矩阵相乘,生成透视的效果。

使用举例:

切换当前矩阵

如果要使用透视(3D),那么要先设置透视投影。

glMatrixMode(GL_PROJECTION);

//添加  设置透视投影   代码

设置完成后开始画图,需要切换到  模型视图矩阵 才能正确画图

glMatrixMode(GL_MODELVIEW);

//添加  画图代码(看起来是3D的)

如果这个时候需要画一个2D效果的物体,那么又需要透视投影

5 添加WM_PAINT的消息处理函数OnPaint()

绘制场景一般包括如下步骤:1)清空缓存 2)绘制场景 3)Flush掉渲染流水线 4)若设置了双缓冲,则交换前后台缓冲区。

this->DrawGLScene();

SwapBuffers(dc.m_hDC);


框架中存在的问题:

一、试着拖动窗口以改变大小的时候,窗口发生严重的闪屏现象。

原因:发生闪烁的原因是Windows先绘制背景,然后再是OpenGL绘制,因为我们已经让OpenGL负责清空背景色,因此我们不需要Windows去清空背景了

BOOL C*****View::OnEraseBkgnd(CDC* pDC) 
{
    //Tell Windows not to erase the background
    return TRUE;
}





你可能感兴趣的:(OpenGL)