开发环境: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>
四、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; }