本文大部分内容摘自:https://blog.csdn.net/MissXy_/article/details/75671515,作者是:MissXy_。
在控制台程序中使用opengl画图并显示可以非常方便,opengl自带窗口显示功能。现在我想在MFC中使用opengl画图,那如何让OpenGL画出的图形在MFC的视类窗口显示出来呢?
Windows GDI是通过设备句柄(Device Context(设备描述表)以下简称”DC”)来绘图,而OpenGL则需要绘制环境(Rendering Context(着色描述表),以下简称”RC”)。每一个GDI命令需要传给它一个DC,但与GDI不同,OpenGL使用当前绘制环境(RC)。但是RC并不能直接完成绘图,只能与特定的DC联系起来,从而完成具体的绘图工作。一旦在一个线程中指定了一个当前RC,在此线程中其后所有的OpenGL命令都使用相同的当前RC。虽然在单一窗口中可以使用多个RC,但在单一线程中只有一个当前RC。
MFC中画图的东西叫做HDC,而OpenGL中渲染图形的东西叫做HGLRC,这两者通过函数wglMakeCurrent建立联系。
下面我将首先产生一个OpenGL RC并使之成为当前RC。这将分为三个步骤:
- 设置窗口像素
- 产生RC
- 设置为当前RC
以下为用到的一些头文件和库文件,及变量的定义。
#include <GL/glu.h>
#include <GL/gl.h>
#include <GL/glut.h>
#pragma comment( lib, "opengl32.lib" )
#pragma comment( lib, "glu32.lib" )
#pragma comment( lib, "glut32.lib" )
#pragma comment( lib, "glaux.lib" )
HGLRC m_hRC; //Rendering Context着色描述表
CClientDC* m_pDC; //Device Context设备描述表
产生RC的第一步是定义窗口的像素格式。像素格式决定窗口着所显示的图形在内存中是如何表示的。由像素格式控制的参数包括:颜色深度、缓冲模式和所支持的绘画接口。
static PIXELFORMATDESCRIPTOR pfd =
{
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 pixelFormat;
// 为设备描述表得到最匹配的像素格式
if((pixelFormat = ChoosePixelFormat(m_pDC->GetSafeHdc(), &pfd)) == 0)
{
MessageBox( _T("ChoosePixelFormat failed") );
return FALSE;
}
// 设置最匹配的像素格式为当前的像素格式
if(SetPixelFormat(m_pDC->GetSafeHdc(), pixelFormat, &pfd) == FALSE)
{
MessageBox( _T("SetPixelFormat failed") );
return FALSE;
}
第二步、产生绘制环境(RC)并使之成为当前绘制环境。
PIXELFORMATDESCRIPTOR pfd;
int n;
m_pDC=new CClientDC(this);
ASSERT(m_pDC != NULL);
// 设置当前的绘图像素格式
if(!SetupPixelFormat())
{
return FALSE;
}
n=::GetPixelFormat(m_pDC->GetSafeHdc());
::DescribePixelFormat(m_pDC->GetSafeHdc(), n,sizeof(pfd),&pfd);
// 创建绘图描述表
m_hRC=wglCreateContext(m_pDC->GetSafeHdc());
if(m_hRC == NULL)
{
return FALSE;
}
// 使绘图描述表为当前调用现程的当前绘图描述表
if( wglMakeCurrent(m_pDC->GetSafeHdc(),m_hRC) == FALSE)
{
return FALSE;
}
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
return TRUE;
第三步、绘图
在view类中的OnDraw函数中渲染图形,例如绘制正方形,代码如下:
glBegin(GL_QUADS); // 绘制正方形
glColor3f(255.0f, 0.0f, 0.0f);
glVertex3f(-1.0f, 1.0f, 0.0f); // 左上
glColor3f(0.0f, 255.0f, 0.0f);
glVertex3f(1.0f, 1.0f, 0.0f); // 右上
glColor3f(0.0f, 0.0f, 255.0f);
glVertex3f(1.0f, -1.0f, 0.0f); // 左下
glColor3f(255.255f, 255.0f, 255.0f);
glVertex3f(-1.0f, -1.0f, 0.0f); // 右下
glEnd();
glBegin和glEnd之间开可以绘制更加复杂的图形。
第四步、释放渲染环境的句柄
::wglMakeCurrent(NULL, NULL);
if (_hRC) ::wglDeleteContext(_hRC);