显示部分主要由opengl实现
首先需要解决的问题是如何在MFC的对话框程序中应用opengl
参考网上内容,先做了一个小实验。
MFC对话框程序中应用opengl主要涉及到几个部分:opengl的初始化,opengl窗口的渲染,opengl窗口的创建
为了便于外部调用,新建类COpengl,继承类public CWnd,添加:
public:
virtual void RenderScene();
void Create(CRect rect,CWnd *parent);
virtual ~COpengl();
protected:
CRect m_rect;
CWnd* m_parent;
int InitGL();
void KillGLWindow();
HDC m_hDC;
HGLRC m_hRC;
DEVMODE m_DMsaved;
并在opengl.cpp中添加如下代码:
#include <gl/freeglut.h>//我用的是freeglut 省略了在连接依赖库中添加东西
COpengl::~COpengl()
{
KillGLWindow();
}
void COpengl::Create(CRect rect,CWnd *parent) //通过窗体父句柄创建opengl类,传递给m_rect,在这个矩形内画图
{
ASSERT(rect);
ASSERT(parent);
m_rect=rect;
m_parent=parent;
CString className = AfxRegisterWndClass(
CS_HREDRAW | CS_VREDRAW | CS_OWNDC,
NULL,
(HBRUSH)GetStockObject(BLACK_BRUSH),
NULL); //注册类
CreateEx(
0,
className,
"OpenGL",
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
rect,
parent,
0);//创建这个opengl类
}
int COpengl::OnCreate(LPCREATESTRUCT lpCreateStruct) //这个基本上是固定的格式---直接从网上copy来
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;
EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &m_DMsaved); //枚举显示设置,这句是为了获得m_DMsaved,以便下用(颜色深度)
GLuint PixelFormat; // Holds The Results After Searching For A Match
static PIXELFORMATDESCRIPTOR pfd= // pfd Tells Windows How We Want Things To Be
{
sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
1, // Version Number
PFD_DRAW_TO_WINDOW | // Format Must Support Window
PFD_SUPPORT_OPENGL| // Format Must Support OpenGL
PFD_DOUBLEBUFFER, // Must Support Double Buffering
PFD_TYPE_RGBA, // Request An RGBA Format
m_DMsaved.dmBitsPerPel, // Select Our Color Depth
0, 0, 0, 0, 0, 0, // Color Bits Ignored
0, // No Alpha Buffer
0, // Shift Bit Ignored
0, // No Accumulation Buffer
0, 0, 0, 0, // Accumulation Bits Ignored
16, // 16Bit Z-Buffer (Depth Buffer)
0, // No Stencil Buffer
0, // No Auxiliary Buffer
PFD_MAIN_PLANE, // Main Drawing Layer
0, // Reserved
0, 0, 0 // Layer Masks Ignored
}; //颜色描述符设置
if ( !( m_hDC = ::GetDC ( m_hWnd ) ) )
{ // Did We Get A Device Context?
KillGLWindow (); // Reset The Display
TRACE ( "Can't Create A GL Device Context." );
return FALSE;
}
if ( !( PixelFormat = ChoosePixelFormat ( m_hDC, &pfd ) ) )
{ // Did Windows Find A Matching Pixel Format?
KillGLWindow (); // Reset The Display
TRACE ( "Can't Find A Suitable PixelFormat." );
return FALSE;
}
if ( !SetPixelFormat ( m_hDC, PixelFormat, &pfd ) )
{ // Are We Able To Set The Pixel Format?
KillGLWindow (); // Reset The Display
TRACE ( "Can't Set The PixelFormat." );
return FALSE;
}
if ( !( m_hRC = wglCreateContext ( m_hDC ) ) )
{ // Are We Able To Get A Rendering Context?
KillGLWindow (); // Reset The Display
TRACE( " Can't Create A GL Rendering Context." );
return FALSE;
}
if ( !wglMakeCurrent ( m_hDC, m_hRC ) )
{ // Try To Activate The Rendering Context
KillGLWindow (); // Reset The Display
TRACE ( "Can't Activate The GL Rendering Context." );
return FALSE;
}
if ( !InitGL () )
{ // Initialize Our Newly Created GL Window
KillGLWindow (); // Reset The Display
TRACE ( "Initialization Failed." );
return FALSE;
}
return 0;
}
void COpengl::KillGLWindow() //销毁opengl的显示
{
if (m_hRC)
{
wglMakeCurrent ( NULL, NULL );
wglDeleteContext ( m_hRC );
m_hRC=NULL;
}
if (m_hDC && !::ReleaseDC(m_hWnd,m_hDC))
{
m_hDC=NULL;
}
if (m_hWnd && !::DestroyWindow(m_hWnd))
{
m_hWnd=NULL;
}
}
int COpengl::InitGL() //opengl初始化
{
glShadeModel(GL_SMOOTH); // Enable Smooth Shading
glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black Background
glClearDepth(1.0f); // Depth Buffer Setup
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations
glEnable(GL_TEXTURE_2D); // Enable Texture Mapping
return TRUE;
}
void COpengl::RenderScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer
glLoadIdentity();
static GLfloat zrot; // Z Rotation
glPushMatrix(); // Push Matrix Onto Stack (Copy The Current Matrix)
glLoadIdentity();
glTranslatef(0.0f,0.0f,-1.0f);
glRotatef(zrot,0.0f,0.0f,1.0f);
glBegin(GL_QUADS); //我创建了一个2d的正方形,并让它不停转动
glColor3f(1.0f,0.0f,0.0f);glVertex3f(-0.5f, -0.5f, 0.0f);
glColor3f(0.0f,1.0f,0.0f);glVertex3f( 0.5f, -0.5f, 0.0f);
glColor3f(0.0f,1.0f,0.0f);glVertex3f( 0.5f, 0.5f, 0.0f);
glColor3f(0.0f,0.0f,1.0f);glVertex3f(-0.5f, 0.5f, 0.0f);
glEnd();
glPopMatrix();
zrot+=1;
SwapBuffers(m_hDC);//双缓冲需要swapbuffer
Invalidate(FALSE); //使双缓冲模式生效
}
另外,如果RenderScene中没有Invalidate(False)的话,双缓冲模式就不会生效了------
到此,opengl部分的配置就ok了,现在需要的就是在程序中引用opengl
首先在new3dDlg.h中加入
#include"Opengl.h"
在类定义中加入:
public:
CRect drawrect;
protected:
COpengl m_opengl;
转到new3dDlg.cpp中:
首先要在窗口初始化的时候对opengl进行初始化
在OnInitDialog()中加入
drawrect.top=40;
drawrect.bottom=680;
drawrect.left=280;
drawrect.right=1080;
ScreenToClient(drawrect);//规定opengl的显示区域
m_opengl.Create(drawrect,this);//根据主窗口和矩形区域调用创建opengl类的程序
SetTimer(121,50,NULL);//设置时钟对opengl显示进行刷新,相当于opengl程序中的glutMainLoop
为窗口添加WM_TIMER消息响应事件,并加入
if (nIDEvent==121)
{
m_opengl.RenderScene();
}
这样,编译连接后,一个旋转的正方形就产生了------