转载地址:https://blog.csdn.net/u013232740/article/details/47904115

------------------------------------------------------------------------------------------------------------

本例在Visual Studio 2013环境下使用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); // 用于创建渲染描述表

此时在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), //结构体长度
, //版本
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, //在窗口中绘图|支持进行OpenGL调用|双缓存模式
PFD_TYPE_RGBA, //RGBA颜色模式
, //使用24位颜色
, , , , , , , , , , , ,,
, //深度缓冲区大小
, ,
PFD_MAIN_PLANE,
, , ,
}; //填充PIXELFORMATDESCRIPTOR像素格式
int ipixelformat;
//获取最佳匹配的像素格式索引
if((ipixelformat = ChoosePixelFormat(pDrawDC->GetSafeHdc(),&pfd)) == )
{
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指向当前DC
ASSERT(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) == -)
return -; // TODO: Add your specialized creation code here
GLSetting(); //该函数用来创建渲染描述表
return ;
}

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

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

void CTestGLView::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy); // TODO: Add your message handler code here
if(cy>)
{
glMatrixMode(GL_PROJECTION); //启动投影矩阵,4×4
glLoadIdentity(); //初始化为单位矩阵
gluPerspective(45.0f,cx/cy,0.0f,30.0f); //设置透视投影变换,指定视场
glViewport(, , 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 here
HGLRC 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 default
if(bRotate)
{
SetTimer(,,NULL); //设置定时器1,100ms触发一次
}
else
{
KillTimer(); //移除定时器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 == )
{
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的角度,有时间间隔短,所以看上去就会产生三棱锥旋转的效果。当鼠标在此单击左键时,定时器被取消,图形停止旋转。

===================================================================================================================================

原贴地址:https://blog.csdn.net/u013232740/article/details/47904115

MFC+OpenGL基础绘制<转>的更多相关文章

  1. OpenGL基础图形编程

    一.OpenGL与3D图形世界1.1.OpenGL使人们进入三维图形世界 我们生活在一个充满三维物体的三维世界中,为了使计算机能精确地再现这些物体,我们必须能在三维空间描绘这些物体.我们又生活在一个充 ...

  2. opengl基础学习专题 (二) 点直线和多边形

    题外话 随着学习的增长,越来越觉得自己很水.关于上一篇博文中推荐用一个 学习opengl的 基于VS2015的 simplec框架.存在 一些问题. 1.这个框架基于VS 的Debug 模式下,没有考 ...

  3. 【转】OpenGL基础图形编程(一)

    原文:http://blog.chinaunix.net/uid-20638550-id-1909183.html  分类: 一.OpenGL与3D图形世界 1.1.OpenGL使人们进入三维图形世界 ...

  4. OpenGL学习-------绘制简单的几何图形

    本次课程所要讲的是绘制简单的几何图形,在实际绘制之前,让我们先熟悉一些概念. 一.点.直线和多边形我们知道数学(具体的说,是几何学)中有点.直线和多边形的概念,但这些概念在计算机中会有所不同.数学上的 ...

  5. opengl基础学习专题 (一 )编程环境搭建

    题外话: 第一次在博客园上同大家分享博文.水的的地方,错别字的地方.环境交流.批评.知道了马上改. 以前在百度空间中写技术分享博文,后来百度啥也没说就把整个空间封了.当时感觉 还是有点寒心.只想黑一下 ...

  6. openGl 基础

    最近由于手机项目中需要用到OpenGL ES的知识,所以这段时间正在研究OpenGL的相关知识.因为OpenGL ES是OpenGL的剪裁版本,所以我直接从OpenGL入手,然后再去看OpenGL E ...

  7. 【AR实验室】OpenGL ES绘制相机(OpenGL ES 1.0版本)

    0x00 - 前言 之前做一些移动端的AR应用以及目前看到的一些AR应用,基本上都是这样一个套路:手机背景显示现实场景,然后在该背景上进行图形学绘制.至于图形学绘制时,相机外参的解算使用的是V-SLA ...

  8. CSharpGL(6)在OpenGL中绘制UI元素

    CSharpGL(6)在OpenGL中绘制UI元素 2016-08-13 由于CSharpGL一直在更新,现在这个教程已经不适用最新的代码了.CSharpGL源码中包含10多个独立的Demo,更适合入 ...

  9. 使用OpenGL ES绘制3D图形

    如果应用定义的顶点不在同一个平面上,并且使用三角形把合适的顶点连接起来,就可以绘制出3D图形了. 使用OpenGL  ES绘制3D图形的方法与绘制2D图形的步骤大致相同,只是绘制3D图形需要定义更多的 ...

随机推荐

  1. 学习笔记之GitHub

    GitHub https://github.com/ GitHub - Wikipedia https://en.wikipedia.org/wiki/GitHub GitHub (originall ...

  2. solusvm安装过程

    openvz solusvm ** Testing connectivity PING solusvm.com (69.168.233.94) 56(84) bytes of data. 64 byt ...

  3. Spring MVC controller返回值类型

    SpringMVC controller返回值类型: 1 String return "user":将请求转发到user.jsp(forword) return "red ...

  4. Hive调优

    Hive存储格式选择 和Hive 相关优化: 压缩参考 Hive支持的存储数的格式主要有:TEXTFILE .SEQUENCEFILE.ORC.PARQUET. 文件存储格式 列式存储和行式存储 行存 ...

  5. tomcat安全加固和规范

    tomcat是一个开源Web服务器,基于Tomcat的Web运行效率高,可以在一般的硬件平台上流畅运行,因此,颇受Web站长的青睐.不过,在默认配置下其存在一定的安全隐患,可被恶意攻击.以下是一些安全 ...

  6. CF865D Buy Low Sell High

    /* 贪心来选择, 如果能找到比当前小的, 就用最小的来更新当前的 优先队列即可 */ #include<cstdio> #include<algorithm> #includ ...

  7. rpm和yum的区别

    rpm 只能安装已经下载到本地机器上的rpm 包, yum能在线下载并安装rpm包,能更新系统,且还能自动处理包与包之间的依赖问题,这个是rpm 工具所不具备的.

  8. crawlspider 多分页处理

    提问:如果想要通过爬虫程序去爬取”糗百“全站数据新闻数据的话,有几种实现方法? 方法一:基于Scrapy框架中的Spider的递归爬取进行实现(Request模块递归回调parse方法). 方法二:基 ...

  9. 定时任务Job

    package com.cfets.ts.u.limitapi.job; import java.text.SimpleDateFormat; import java.util.Date; impor ...

  10. 【Jenkins学习】安装配置和使用(一)

    为了能够频繁地将软件的最新版本,及时.持续地交付给测试团队及质量控制团队,以供评审,所以引入持续集成工具Jenkins,从而实现公司新产品持续集成,自动化部署. 环境准备 ●操作系统:Windows1 ...