Visual Studio2010与OpenGL基础绘制

2024-09-01 10:32

本文主要是介绍Visual Studio2010与OpenGL基础绘制,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本例在Visual Studio 2010环境下使用OpenGL,提供一个基本的开发应用程序框架。

第一步:OpenGL基础设置:

1.创建一个单文档的MFC应用程序,命名为TestGL,然后在TestGLView.h头文件中添加以下两条include包含语句:

#include "gl/gl.h"
#include "gl/glu.h"

2.设置程序为静态运行方式

执行菜单命令:项目->属性,弹出属性对话框,选择配置属性->常规->MFC使用->在静态库中使用MFC,然后单击确定。这样做会使程序变得很大,但是它编译生成的可执行程序可以在其他计算机中运行。


3.链接OpenGL库文件

执行菜单命令:项目->属性打开属性对话框,选择配置属性->链接器->常规->附加库路径,输入OpenGL的库文件所在的路径,单击确定。比如我的机子如下:


再选择配置属性->链接器->输入->附加依赖库,在弹出的对话框中输入OpenGL的库文件OpenGL32.lib和glu32.lib,如下:


然后确定结束属性配置。编译运行,如果没有错误则表明配置正确。


第二步:在Visual Studio下用OpenGL绘制三棱锥:

绘制步骤如下:

*通过PIXELFORMATDESCRIPTOR结构设置设备描述表DC的像素格式和属性;

*创建渲染描述表RC,并和DC建立联系;

*使用OpenGL做图;

*释放所占用的资源,包括解除DC和RC的联系,删除RC及其与之关联的DC;

为应用程序添加变量和函数,对相关变量进行初始化,然后在函数中实现DC像素格式设置,RC的创建及其与DC 的关联,图形绘制以及资源释放等功能。

1.添加成员变量和成员函数:

为CTestGLView类添加公共变量:

CClientDC* pDrawDC;     // 用于指向当前DC的指针
通过向导自动添加后,会在CTestGLView类的构造函数中将其初始化为NULL:

CTestGLView::CTestGLView(): pDrawDC(NULL)
{// TODO: 在此处添加构造代码}

然后为CTestGLView添加三个公共成员函数:

void DrawGraphics(void);// 用于后续图形绘制
BOOL PixelformatSetting(void);	// 用于设置像素格式
void GLSetting(void);	// 用于创建渲染描述表
2.添加消息响应函数:

右击CTestGLView类选择属性命令,在属性对话框中选择消息页面。然后选择WM_CREATE消息,单击其后的下拉菜单按钮并选择"<添加>OnCreate"选项,为CTestGLView类添加消息响应函数OnCreate(),如下所示:

此时在TestGLView.cpp文件中可以看到添加消息的消息映射宏ON_WM_CREATE()和对应的OnCreate()函数。该消息响应在建立一个窗体前将被调用,因此可在其中做一些初始设置。

同样的方法添加另外两个消息响应函数:

OnDestroy():响应WM_DESTROY消息,宏为ON_WM_DESTROY(),窗口销毁时响应此函数,因此应该在此释放函数中所占用的资源。

OnSize():响应WM_SIZE消息,宏为ON_WM_SIZE()。改变窗口大小时响应此函数,因此可在此函数中调整视场。

3.为成员函数和消息响应函数添加代码:

1)设置像素格式。在BOOL CTestGLView::PixelformatSetting(void)函数中添加如下代码:

// 用于设置像素格式
BOOL CTestGLView::PixelformatSetting(void)
{static PIXELFORMATDESCRIPTOR pfd={sizeof(PIXELFORMATDESCRIPTOR),  //结构体长度1,    //版本PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, //在窗口中绘图|支持进行OpenGL调用|双缓存模式PFD_TYPE_RGBA,  //RGBA颜色模式24,  //使用24位颜色0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,0,32,  //深度缓冲区大小0, 0,PFD_MAIN_PLANE,0, 0, 0, 0};  //填充PIXELFORMATDESCRIPTOR像素格式int ipixelformat;//获取最佳匹配的像素格式索引if((ipixelformat = ChoosePixelFormat(pDrawDC->GetSafeHdc(),&pfd)) == 0){MessageBox(_T("Choose pixel format failed!"));return TRUE;}//把DC的像素格式设置成由索引值ipixelformat指向的像素格式if(SetPixelFormat(pDrawDC->GetSafeHdc(),ipixelformat,&pfd) == FALSE){MessageBox(_T("Set pixel format failed !"));return FALSE;}return TRUE;
}

2).创建渲染描述表:

在函数void CTestGLView::GLSetting(void)中调用PixelformatSetting(void)设置像素格式,然后创建和DC关联的渲染描述表,代码如下:

// 用于创建渲染描述表
void CTestGLView::GLSetting(void)
{HGLRC hRC;   //渲染描述表句柄pDrawDC = new CClientDC(this);  //使pDrawDC指向当前DCASSERT(pDrawDC !=NULL);  //断言pDrawDC不为空if(!PixelformatSetting())  //设置像素格式return;//创建和当前DC兼容的RC,并和当前DC关联hRC = wglCreateContext(pDrawDC->GetSafeHdc());wglMakeCurrent(pDrawDC->GetSafeHdc(),hRC);
}

3).在消息响应函数OnCreate()函数中调用GLSetting()函数,使上述设置生效,代码如下:

int CTestGLView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{if (CView::OnCreate(lpCreateStruct) == -1)return -1;// TODO:  Add your specialized creation code hereGLSetting();  //该函数用来创建渲染描述表return 0;
}

4).投影变换和视口变换。

在OnSize()中添加代码设置投影变换和视口变换,如下所示:

void CTestGLView::OnSize(UINT nType, int cx, int cy)
{CView::OnSize(nType, cx, cy);// TODO: Add your message handler code hereif(cy>0){glMatrixMode(GL_PROJECTION);  //启动投影矩阵,4×4glLoadIdentity();   //初始化为单位矩阵gluPerspective(45.0f,cx/cy,0.0f,30.0f);  //设置透视投影变换,指定视场glViewport(0, 0, cx, cy);  //设置视场,即定义显示范围}RedrawWindow();   //显示更新
}

5).绘制三棱锥:

在void CTestGLView::DrawGraphics(void)函数中,添加代码绘制3个三角形,构成一个三棱锥,如下:

void CTestGLView::DrawGraphics(void)
{glTranslatef(0.0f, 0.0f, -6.0f);  //移动物体到显示区glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);   //以边线方式绘制三角形//绘制3个三角形的三个顶点glBegin(GL_TRIANGLES);glVertex3f(-0.6f, 0.0f, 0.0f);glVertex3f(0.6f, 0.0f, 0.0f);glVertex3f(0.0f, 0.15f, 0.6f);glVertex3f(-0.6f, 0.0f, 0.0f);glVertex3f(0.0f, 0.15f, 0.6f);glVertex3f(0.0f, 0.9f, 0.6f);glVertex3f(0.0f, 0.9f, 0.6f);glVertex3f(0.0f, 0.15f, 0.6f);glVertex3f(0.6f, 0.0f, 0.0f);glEnd();
}

6).在OnDraw()函数中设置背景并调用DrawGraphics()函数绘制图形。

通常使用CView类的成员函数OnDraw()绘制用户界面,此外还可以在该函数中添加代码完成背景色设置,然后调用DrawGraphics()函数完成绘制。

void CTestGLView::OnDraw(CDC* /*pDC*/)
{CTestGLDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);if (!pDoc)return;// TODO: 在此处为本机数据添加绘制代码static BOOL bBusy = FALSE;  //定义开关变量//绘制完成后才可以更新缓存if(bBusy)return;bBusy =TRUE;glClearColor(0.0f, 0.0f, 0.5f, 0.5f);  //设置背景颜色glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  //清除深度缓存和颜色缓存glMatrixMode(GL_MODELVIEW);  //启动模型矩阵glLoadIdentity();   //初始化为单位矩阵DrawGraphics();   //绘制图形SwapBuffers(wglGetCurrentDC());  //更新缓存bBusy=FALSE;
}

7).删除渲染描述表。

在消息响应函数OnDestroy()中删除渲染描述表及其绑定的设备描述表,代码如下:

void CTestGLView::OnDestroy()
{CView::OnDestroy();// TODO: Add your message handler code hereHGLRC hRC;hRC=::wglGetCurrentContext();   //获取当前RC句柄::wglMakeCurrent(NULL,NULL);  //解除当前RC和DC的关联,并把当前RC非当前化if(hRC){::wglDeleteContext(hRC);  //删除RC}if(pDrawDC){delete pDrawDC;   //删除DC}
}

编译运行项目,如果没有错,可得结果如下:

4.添加旋转功能:

实现一个交互功能,即单击鼠标开始/停止三棱锥旋转。

1).添加消息响应函数。

为CTestGLView类添加鼠标左键消息WM_LBUTTONDOWN和定时器消息WM_TIME,鼠标左键消息响应函数OnLButtonDown(),宏ON_WM_LBUTTONDOWN()。定时器消息响应函数为OnTimer(),宏ON_WM_TIMER().
2).为CTestGLView类添加两个共有属性的成员变量,

BOOL bRotate;   // 控制图形旋转
float RotateAngle;   // 旋转角度
Visual Studio会自动在CTestGLView类的构造函数中将bRotate初始化为FALSE,将RotateAngle初始化为0.手动将bRotate的初始值改为TRUE。

3).在void CTestGLView::OnLButtonDown(UINT nFlags, CPoint point)函数中添加如下代码,通过单击启动/停止定时器,

void CTestGLView::OnLButtonDown(UINT nFlags, CPoint point)
{// TODO: Add your message handler code here and/or call defaultif(bRotate){SetTimer(1,100,NULL);   //设置定时器1,100ms触发一次}else{KillTimer(1);  //移除定时器1}bRotate = !bRotate;   //更新bRotate的值CView::OnLButtonDown(nFlags, point);
}

4).设置旋转角度。在定时器消息响应函数OnTimer()中添加如下代码,实现每次定时到达时都能将图形旋转10度

void CTestGLView::OnTimer(UINT_PTR nIDEvent)
{// TODO: Add your message handler code here and/or call default//若定时器1到达预定时刻,则旋转角度增加10度if(nIDEvent == 1){RotateAngle += 10.0f;Invalidate(FALSE);  //使当前窗口失效,重新绘制}CView::OnTimer(nIDEvent);
}
在OnTimer()函数中使用的Invalidate()函数作用是将整个客户区失效,从而被重新绘制,而最终的重绘工作由OnDraw()函数完成。此处用函数Invalidate()函数调用了OnDraw()函数来绘制旋转后的图形。

5).每次按照设置的角度重绘图形。重绘窗口由OnDraw()函数完成,而OnDraw()函数调用DrawGraphics()函数绘制图形。因此在函数DrawGraphics()函数中需添加如下代码:

glRotated(RotateAngle,1.0, 1.0, 1.0);  //按设定的角度RotateAngle旋转图形
将这句代码放在glTranslatef()函数语句之后。使得每次重绘时将图形绕着从原点指向(1.0,1.0,1.0)的射线旋转RotateAngle的角度,而RotateAngle的值在定时器函数OnTimer()中更新。这样就可以实现每次单击鼠标左键,定时器开始计时,每个100ms后响应定时器消息的函数OnTimer()将RotateAngle的值增加10度,同时Invalidate()函数使界面失效而被重绘,重绘是将图形选择RotateAngle的角度,有时间间隔短,所以看上去就会产生三棱锥旋转的效果。当鼠标在此单击左键时,定时器被取消,图形停止旋转。



参考文献:张俊华.<医学图像三维重建和可视化——VC++实现>.科学出版社


这篇关于Visual Studio2010与OpenGL基础绘制的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1126681

相关文章

从基础到进阶详解Python条件判断的实用指南

《从基础到进阶详解Python条件判断的实用指南》本文将通过15个实战案例,带你大家掌握条件判断的核心技巧,并从基础语法到高级应用一网打尽,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一... 目录​引言:条件判断为何如此重要一、基础语法:三行代码构建决策系统二、多条件分支:elif的魔法三、

Python WebSockets 库从基础到实战使用举例

《PythonWebSockets库从基础到实战使用举例》WebSocket是一种全双工、持久化的网络通信协议,适用于需要低延迟的应用,如实时聊天、股票行情推送、在线协作、多人游戏等,本文给大家介... 目录1. 引言2. 为什么使用 WebSocket?3. 安装 WebSockets 库4. 使用 We

从基础到高阶详解Python多态实战应用指南

《从基础到高阶详解Python多态实战应用指南》这篇文章主要从基础到高阶为大家详细介绍Python中多态的相关应用与技巧,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、多态的本质:python的“鸭子类型”哲学二、多态的三大实战场景场景1:数据处理管道——统一处理不同数据格式

MySQL数据类型与表操作全指南( 从基础到高级实践)

《MySQL数据类型与表操作全指南(从基础到高级实践)》本文详解MySQL数据类型分类(数值、日期/时间、字符串)及表操作(创建、修改、维护),涵盖优化技巧如数据类型选择、备份、分区,强调规范设计与... 目录mysql数据类型详解数值类型日期时间类型字符串类型表操作全解析创建表修改表结构添加列修改列删除列

Python 函数详解:从基础语法到高级使用技巧

《Python函数详解:从基础语法到高级使用技巧》本文基于实例代码,全面讲解Python函数的定义、参数传递、变量作用域及类型标注等知识点,帮助初学者快速掌握函数的使用技巧,感兴趣的朋友跟随小编一起... 目录一、函数的基本概念与作用二、函数的定义与调用1. 无参函数2. 带参函数3. 带返回值的函数4.

python panda库从基础到高级操作分析

《pythonpanda库从基础到高级操作分析》本文介绍了Pandas库的核心功能,包括处理结构化数据的Series和DataFrame数据结构,数据读取、清洗、分组聚合、合并、时间序列分析及大数据... 目录1. Pandas 概述2. 基本操作:数据读取与查看3. 索引操作:精准定位数据4. Group

Visual Studio 2022 编译C++20代码的图文步骤

《VisualStudio2022编译C++20代码的图文步骤》在VisualStudio中启用C++20import功能,需设置语言标准为ISOC++20,开启扫描源查找模块依赖及实验性标... 默认创建Visual Studio桌面控制台项目代码包含C++20的import方法。右键项目的属性:

使用Python绘制3D堆叠条形图全解析

《使用Python绘制3D堆叠条形图全解析》在数据可视化的工具箱里,3D图表总能带来眼前一亮的效果,本文就来和大家聊聊如何使用Python实现绘制3D堆叠条形图,感兴趣的小伙伴可以了解下... 目录为什么选择 3D 堆叠条形图代码实现:从数据到 3D 世界的搭建核心代码逐行解析细节优化应用场景:3D 堆叠图

从基础到进阶详解Pandas时间数据处理指南

《从基础到进阶详解Pandas时间数据处理指南》Pandas构建了完整的时间数据处理生态,核心由四个基础类构成,Timestamp,DatetimeIndex,Period和Timedelta,下面我... 目录1. 时间数据类型与基础操作1.1 核心时间对象体系1.2 时间数据生成技巧2. 时间索引与数据

安装centos8设置基础软件仓库时出错的解决方案

《安装centos8设置基础软件仓库时出错的解决方案》:本文主要介绍安装centos8设置基础软件仓库时出错的解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录安装Centos8设置基础软件仓库时出错版本 8版本 8.2.200android4版本 javas