OpenGL在MFC的Picture Control中显示

OpenGL在MFC中的配置与前面文章所述基本一样,不再赘述。本篇主要记录如何用OpenGL在MFC的Picture Control控件中绘图。假定已经配置好了环境,而且已经在MFC中创建了ID为“IDC_STATIC_SHOW”的Picture Control控件。

需要做的不是很多,就下面几步:

  1. 设定像素格式,为OpenGL与HDC连接做准备
  2. 创建OpenGL渲染上下文,使得OpenGL可在上面绘制
  3. 在OnTimer(UINT_PTR nIDEvent)函数中调用绘图函数进行绘制
具体的,在MFC的类头文件中添加函数和相关变量:
BOOL SetWindowPixelFormat(HDC hDC);//设定像素格式,为OpenGL与HDC连接做准备
BOOL CreateViewGLContext(HDC hDC);//创建OpenGL渲染上下文,使得OpenGL可在上面绘制
void RenderScene();//绘制场景
void Reshape(int width, int height);//改变窗口大小时对视窗进行的操作

HDC hrenderDC;//设备上下文
HGLRC hrenderRC;//OpenGL渲染上下文
int PixelFormat;//像素格式
	
Mat imgbgr;
Mat imgbgra;
具体函数定义:
BOOL xxx::SetWindowPixelFormat(HDC hDC)//设置像素格式
{
	PIXELFORMATDESCRIPTOR pixelDesc;

	pixelDesc.nSize = sizeof(PIXELFORMATDESCRIPTOR);
	pixelDesc.nVersion = 1;

	pixelDesc.dwFlags = PFD_DRAW_TO_WINDOW |
		PFD_SUPPORT_OPENGL |
		PFD_DOUBLEBUFFER |
		PFD_TYPE_RGBA;

	pixelDesc.iPixelType = PFD_TYPE_RGBA;
	pixelDesc.cColorBits = 32;
	pixelDesc.cRedBits = 0;
	pixelDesc.cRedShift = 0;
	pixelDesc.cGreenBits = 0;
	pixelDesc.cGreenShift = 0;
	pixelDesc.cBlueBits = 0;
	pixelDesc.cBlueShift = 0;
	pixelDesc.cAlphaBits = 0;
	pixelDesc.cAlphaShift = 0;
	pixelDesc.cAccumBits = 0;
	pixelDesc.cAccumRedBits = 0;
	pixelDesc.cAccumGreenBits = 0;
	pixelDesc.cAccumBlueBits = 0;
	pixelDesc.cAccumAlphaBits = 0;
	pixelDesc.cDepthBits = 0;
	pixelDesc.cStencilBits = 1;
	pixelDesc.cAuxBuffers = 0;
	pixelDesc.iLayerType = PFD_MAIN_PLANE;
	pixelDesc.bReserved = 0;
	pixelDesc.dwLayerMask = 0;
	pixelDesc.dwVisibleMask = 0;
	pixelDesc.dwDamageMask = 0;

	PixelFormat = ChoosePixelFormat(hDC, &pixelDesc);
	if (PixelFormat == 0) // Choose default 
	{
		PixelFormat = 1;
		if (DescribePixelFormat(hDC, PixelFormat,
			sizeof(PIXELFORMATDESCRIPTOR), &pixelDesc) == 0)
		{
			return FALSE;
		}
	}
	if (SetPixelFormat(hDC, PixelFormat, &pixelDesc) == FALSE)
	{
		return FALSE;
	}
	return TRUE;
}
BOOL xxx::CreateViewGLContext(HDC hDC)//创建OpenGL渲染描述表,使得OpenGL可在上面绘制
{
	hrenderRC = wglCreateContext(hDC);
	if (hrenderRC == NULL)
		return FALSE;
	if (wglMakeCurrent(hDC, hrenderRC) == FALSE)
		return FALSE;
	return TRUE;
}
void xxx::RenderScene()
{
	//将纹理映射到四边形上
	glBegin(GL_QUADS);
	//纹理的坐标和四边形顶点的对应,可以通过设置四边形的位置调整图像在窗体的位置
	glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, 1.0, 0.0);
	glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, -1.0, 0.0);
	glTexCoord2f(1.0, 1.0); glVertex3f(1.0, -1.0, 0.0);
	glTexCoord2f(1.0, 0.0); glVertex3f(1.0, 1.0, 0.0);
	glEnd();
	glFlush();
	SwapBuffers(hrenderDC);
}
void xxx::Reshape(int width, int height)//改变窗口大小时对视窗进行的操作
{
	glViewport(0, 0, width, height);
}
设置MFC程序响应计时器消息
在初始化函数OnInitDialog()中加入初始化代码:
imgbgr = imread("demo.jpg");
cvtColor(imgbgr, imgbgra, COLOR_BGR2RGBA);
CWnd* wnd = GetDlgItem(IDC_STATIC_SHOW);
hrenderDC = ::GetDC(wnd->m_hWnd);
if (SetWindowPixelFormat(hrenderDC) == FALSE)
	return 0;
if (CreateViewGLContext(hrenderDC) == FALSE)
	return 0;
//根据图像数据生成一个2D纹理
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, imgbgra.cols, imgbgra.rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, imgbgra.data);
//设置纹理参数,放大和缩小采取的插值方式为线性插值
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
//启用一个2D纹理
glEnable(GL_TEXTURE_2D);
//定时显示
SetTimer(1, 30, 0);
编译运行就可以了。
如果要调整显示窗口的大小,需要重新调整视窗。代码如下:
CRect rect;
CWnd* wnd = NULL;
wnd = GetDlgItem(IDC_STATIC_SHOW);//下边窗口
rect.left = 0;
rect.right = 800;
rect.bottom = 500;
rect.top = 0;
wnd->MoveWindow(&rect);
Reshape(800,500);
如果要切换显示的图像。代码如下:
glDisable(GL_TEXTURE_2D);
imgbgr = imread("1.bmp");
cvtColor(imgbgr, imgbgra, COLOR_BGR2RGBA);
//根据图像数据生成一个2D纹理
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, imgbgra.cols, imgbgra.rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, imgbgra.data);
//设置纹理参数,放大和缩小采取的插值方式为线性插值
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
//启用一个2D纹理
glEnable(GL_TEXTURE_2D);
imgbgr.release();
imgbgra.release();
遇到问题:

不知道为什么只能在OnTimer函数中调用OpenGL显示,直接在多线程中调用只能看到一片黑色

参考文章:https://blog.csdn.net/qq_29477855/article/details/52260314

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 使用MFCOpenGL来读取并显示STL三维模型需要以下几个步骤: 1. 创建一个新的MFC项目,选择对话框应用程序作为模板。 2. 将OpenGL库文件添加到项目,并进行相关配置,以便在对话框使用OpenGL绘图。 3. 在对话框添加一个静态文本框和一个自定义的OpenGL绘图区域。 4. 创建一个自定义的OpenGL绘图类,用于在绘图区域显示STL模型。在该类,定义一个透视投影矩阵、模型矩阵和视图矩阵,通过OpenGL函数来加载和渲染STL文件的三角形。 5. 在对话框类,添加一个自定义的OpenGL绘图类的成员变量,并在OnInitDialog()函数对其进行初始化。 6. 在OnInitDialog()函数,调用自定义OpenGL绘图类的初始化函数,传入STL模型文件的路径,将模型加载到内存。 7. 在OnPaint()函数,调用自定义OpenGL绘图类的绘制函数,将模型渲染到OpenGL绘图区域。 8. 处理对话框的事件,例如按钮点击事件,调用自定义OpenGL绘图类的相应函数进行操作,如旋转、平移等。 9. 在应用程序类的InitInstance()函数,创建对话框类的对象,并显示对话框。 通过以上步骤,可以实现在MFC应用程序读取并显示STL三维模型。 ### 回答2: MFC是Microsoft Foundation Classes的缩写,是一种用于Windows平台的C++应用程序框架。OpenGL是一种跨平台的图形API,用于开发图形和计算机视觉应用程序。STL(Standard Template Library)是C++的一部分,提供了一组通用的数据结构和算法。 要在MFC应用程序读取并显示STL三维模型,可以按照以下步骤进行操作: 1. 首先,创建一个MFC应用程序项目,并在项目添加OpenGL支持。这可以通过在项目属性启用OpenGL选项来实现。 2. 在MFC应用程序创建一个窗口,用于显示3D模型。这可以通过创建一个自定义的CStatic控件,并在其上绘制OpenGL图形来实现。 3. 接下来,编写代码来读取STL文件的数据。STL文件包含三角形网格的顶点和法线信息。可以使用标准的文件处理函数来读取和解析STL文件的内容,并将其存储在一个适当的数据结构。 4. 通过OpenGL的API函数,将STL模型数据绘制到窗口。可以使用OpenGL的顶点数组和绘制函数来绘制三角形网格的各个面。 5. 最后,将OpenGL绘制的结果显示MFC窗口。可以通过重载绘图消息处理函数,并在其调用OpenGL的绘制函数来实现。 需要注意的是,由于MFCOpenGL都是底层的图形库,对于初学者来说,可能需要一定的编程经验和对图形编程的理解。这个过程可能需要一些时间和尝试来完善和调试。 ### 回答3: 在 MFC 使用 OpenGL 来读取并显示 STL 三维模型可以通过以下步骤实现: 1. 添加准备创建 OpenGL 窗口的代码。在 MFC 的窗体类,可以使用 `COpenGLControl` 类或 `CView` 类来实现 OpenGL 窗口。 2. 创建一个函数来读取 STL 三维模型文件。你可以使用 STL 文件解析库,例如 `std::ifstream` 类来读取 STL 文件的内容。 3. 在创建的 OpenGL 窗口,使用 OpenGL 函数来绘制三维模型。你可以使用 `glBegin`、`glEnd` 和 `glVertex3f` 等函数来绘制模型的顶点和三角面片。 4. 在 OpenGL 窗口,将读取到的 STL 三维模型数据传入 OpenGL 函数来进行绘制。你可以使用 `glColor3f` 函数来设置模型的颜色。 5. 在 MFC 的窗体类,实现绘制 OpenGL 窗口的函数。通过重写 `OnDraw` 或 `OnPaint` 函数,调用 OpenGL 窗口的绘制函数。 6. 在 MFC 的窗体类,重写 `OnCreate` 函数来初始化 OpenGL 窗口,调用读取和显示 STL 模型的函数。 7. 在 MFC 的窗体类,为了在窗口显示 OpenGL 窗口,重写 `OnSize` 函数,并调用 OpenGL 窗口的调整大小函数。 通过上述步骤,你可以在 MFC 使用 OpenGL 来读取并显示 STL 三维模型。你可以进一步优化代码,例如添加相机控制、光照设置等来增强模型的显示效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值