MFC是微软件提供的一个C++编程框架,它提供了大量的类库,以更强的封装来简化C++的编程。当然,它与普通的Win32编程有些差别。
在MFC下进行OpenGL编程的步骤如下:
1、在工程中包含OGL函数库
法1. “工程”—“设置”—“连接”—“对象/库模块”中输入glaux.lib, opengl32.lib, glu32.lib。
法2. 在StdAfx.h中加入:
#pragma comment(lib,"glaux.lib")
#pragma comment(lib,"opengl32.lib")
#pragma comment(lib,"glu32.lib")
2、在stdafx.h加入OGL头文件。这样做的好处是不需要在其它的头文件重复包含OGL的这些头文件。
#include <gl/gl.h>
#include <gl/glu.h>
#include <gl/glaux.h>
#include <gl/glut.h>
3、初始化OGL场景
BOOL CGLTestView::InitializeOpenGL(CDC *pDc)
{
m_pDc=pDc;
SetupPixelFormat(); // 设置像素点格式
m_hRc=::wglCreateContext(pDc->GetSafeHdc()); // 生成绘制描述表
::wglMakeCurrent(m_pDc->GetSafeHdc(),m_hRc); // 置当前绘制描述表
return TRUE;
}
4、设置像素点格式
BOOL CGLTestView::SetupPixelFormat()
{
PIXELFORMATDESCRIPTOR pdf={
sizeof(PIXELFORMATDESCRIPTOR), // pfd结构的大小
1, // 版本号
PFD_DRAW_TO_WINDOW | // 支持在窗口中绘图
PFD_SUPPORT_OPENGL | // 支持 OpenGL
PFD_DOUBLEBUFFER, // 双缓存模式
PFD_TYPE_RGBA, // RGBA 颜色模式
24, // 24 位颜色深度
0, 0, 0, 0, 0, 0, // 忽略颜色位
0, // 没有非透明度缓存
0, // 忽略移位位
0, // 无累加缓存
0, 0, 0, 0, // 忽略累加位
32, // 32 位深度缓存
0, // 无模板缓存
0, // 无辅助缓存
PFD_MAIN_PLANE, // 主层
0, // 保留
0, 0, 0 // 忽略层,可见性和损毁掩模
};
int pixedformat;
pixedformat=::ChoosePixelFormat(m_pDc->GetSafeHdc(),&pdf);
::SetPixelFormat(m_pDc->GetSafeHdc(),pixedformat,&pdf); // 设置像素格式
if(pdf.dwFlags & PFD_NEED_PALETTE)
SetLogicalPalette(); // 设置逻辑调色板
return TRUE;
}
3. 在View类中,声明变量和函数
class CGLTestView : public CView
{
protected: // create from serialization only
CGLTestView();
DECLARE_DYNCREATE(CGLTestView)
// Attributes
public:
CGLTestDoc* GetDocument();
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CGLTestView)
public:
virtual void OnDraw(CDC* pDC); // overridden to draw this view
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
//}}AFX_VIRTUAL
// Implementation
public:
virtual ~CGLTestView();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
CDC *m_pDc;
HGLRC m_hRc;
HPALETTE m_hPalette;
GLfloat fAspect;
GLuint SelectBuff[512];
int xPos,yPos;
//int z_motion, rotate;
BOOL InitializeOpenGL(CDC *pDc);
BOOL SetupPixelFormat(void);
void SetLogicalPalette(void);
BOOL RenderScene(void);
void Init(GLvoid);
void ProcessSelection(int xPos, int yPos);
CString ProcessPlanet(GLuint *pSelectBuff);
//两个全局变量,z_motion用来控制物体远近
//rotate用来控制物体旋转
protected:
// Generated message map functions
protected:
//{{AFX_MSG(CGLTestView)
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg void OnDestroy();
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnTimer(UINT nIDEvent);
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
5、Init()函数
void CGLTestView::Init(GLvoid)
{
// 光源值
GLfloat whiteLight[] = { 0.35f, 0.35f, 0.35f, 1.0f };
GLfloat sourceLight[] = { 0.65f, 0.65f, 0.65f, 1.0f };
GLfloat lightPos[] = { 0.0f, 0.0f, 0.0f, 1.0f };
glEnable(GL_DEPTH_TEST);
glFrontFace(GL_CCW);
glEnable(GL_CULL_FACE);
glEnable(GL_LIGHTING);
glLightModelfv(GL_LIGHT_MODEL_AMBIENT,whiteLight);
glLightfv(GL_LIGHT0,GL_DIFFUSE,sourceLight);
glLightfv(GL_LIGHT0,GL_POSITION,lightPos);
glEnable(GL_LIGHT0);
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
glClearColor(0.60f, 0.60f, 0.60f, 1.0f );
}
6、 在View类的OnDraw中绘制
// CGLTestView drawing
void CGLTestView::OnDraw(CDC* pDC)
{
CGLTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
RenderScene();
}
7、场影绘制
BOOL CGLTestView::RenderScene(void)
{
// glRenderMode(GL_SELECT);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清一下当前屏幕
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
//根据z_motion rotate两个参数确定变换的具体数值:
//z_motion改变时,物体从原Z坐标-25,平移z_motion个单位
glTranslatef(0.0,0.0,-30.0+z_motion);
//rotate改变时,物体延Y轴(上下方向)旋转5*rotate度
glRotatef(rotate*5.0,0.0,0.0,1.0);
glTranslatef(0.0+x_motion,0.0,0.0);
glTranslatef(0.0,0.0+y_motion,0.0);
// glMatrixMode(GL_SELECT);
// glMatrixMode(GL_PROJECTION);
glInitNames();
glPushName(0);
glPushMatrix();
glRGB(120,120,250);
glTranslatef(-6.0f,-5.0f,-20.0f);
glLoadName(1);
auxSolidSphere(3.0f);
glTranslatef(15.0f,-5.0f,-20.0f);
glLoadName(2);
auxWireTeapot(4.0f);
glPopName();
glPopMatrix();
// glTranslatef(0,0,-20);
// int x=(int)(40*2);
// glBegin(GL_LINE_LOOP);
// for(int i=-x; i<x; i+=4)
// {
// glVertex3i(-x,i,0);
// glVertex3i(x,i,0);
//
// glVertex3i(i,x,0);
// glVertex3i(i,-x,0);
// }
// glEnd();
// glBegin(GL_POLYGON);
// glVertex2f(0.0,0.0);
// glVertex2f(0.0,3.0);
// glVertex2f(3.0,0.0);
// glVertex2f(3.0,3.0);
//
// glEnd();
// glPushMatrix();
// glTranslatef(0.f,-5.0f,-40.0f);
// glBegin(GL_TRIANGLE_STRIP);//画连续填充的多个三角
// glColor3f(1.0,0.0,0.0);
// glVertex3f(15.0,0.0,0.0);
// glColor3f(0.0,1.0,0.0);
// glVertex3f(-15.0,0.0,0.0);
// glColor3f(0.0,0.0,1.0);
// glVertex3f(0.0,15.0,15.0);
// // //第一个三角
// //
// glColor3f(0.0,1.0,1.0);
// glVertex3f(10.0,15.0,-15.0);
// // //第二个三角
// //
// glColor3f(1.0,1.0,0.0);
// glVertex3f(15.0,0.0,0.0);
// // //第三个三角
// //
// glEnd();
// //
// glPopMatrix();
glPopMatrix();
glFlush();
::SwapBuffers(m_pDc->GetSafeHdc()); //交互缓冲区
return TRUE;
}
8、设置逻辑调色板
void CGLTestView::SetLogicalPalette()
{
struct
{
WORD Version;
WORD NumberOfEntries;
PALETTEENTRY aEntries[256];
} logicalPalette = { 0x300, 256 };
BYTE reds[] = {0, 36, 72, 109, 145, 182, 218, 255};
BYTE greens[] = {0, 36, 72, 109, 145, 182, 218, 255};
BYTE blues[] = {0, 85, 170, 255};
for (int colorNum=0; colorNum<256; ++colorNum)
{
logicalPalette.aEntries[colorNum].peRed = reds[colorNum & 0x07];
logicalPalette.aEntries[colorNum].peGreen =greens[(colorNum >> 0x03) & 0x07];
logicalPalette.aEntries[colorNum].peBlue = blues[(colorNum >> 0x06) & 0x03];
logicalPalette.aEntries[colorNum].peFlags = 0;
}
m_hPalette = CreatePalette ((LOGPALETTE*)&logicalPalette);
}
9、建立窗口时
int CGLTestView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
// 初始化OGL和设置定时器
z_motion=0;
x_motion=0;
y_motion=0;
rotate=0;
m_pDc = new CClientDC(this);
SetTimer(1,20,NULL); // 事件ID为1, 20毫秒间距
InitializeOpenGL(m_pDc); // 初始化场境
Init();
return 0;
}
10、适应窗口
// CGLTestView message handlers
// 在OnSize中定义当前视区,投影模型和物体模型,光源
void CGLTestView::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy);
//添加窗口缩放时的图形变换函数
glViewport(0,0,cx,cy); // 按目标窗口设置,视口设置
fAspect = (GLfloat)cx/(GLfloat)cy; // 窗口尺寸比率,为GLfloat型
glMatrixMode(GL_PROJECTION); // 设置投影模式
glLoadIdentity(); // 重置当前指定的矩阵为单位矩阵
gluPerspective(45.0f, fAspect, 1.0, 425.0); // 透视图, 视角,比例,zNear, zFar
glMatrixMode(GL_MODELVIEW); // 模型视图模式
glLoadIdentity();
}
11、关闭窗口时
void CGLTestView::OnDestroy()
{
CView::OnDestroy();
//删除调色板和渲染上下文、定时器
::wglMakeCurrent(0,0);
::wglDeleteContext(m_hRc); // 删除 绘制描述表
if (m_hPalette)
DeleteObject(m_hPalette); // 删除对象“调色板”
if (m_pDc)
{
delete m_pDc; // 删除DC
}
KillTimer(1);
}