基于MFC的OpenGL绘图
基于MFC的Opengl编程

3D图形学基本概念PerspectivePerspective refers to the angles between the lines that lend the illusion of three dimensions.Colors and ShadingMoving beyond line drawing, we need to add color to create a solid object. Shading refers to the way the color is applied to the polygon. Shading can be of two types in OpenGL - Flat or Smooth.Lights and ShadowsPlain solid color doesn’t offer enough realism. By applying Lighting effects we can make objects appear as they would in reality depending on their material properties and the lighting parameters. Adding a shadow further increases realism.Texture MappingWith Texture Mapping we can have wood grains, cloth textures, brick like textures etc instead of plain materials. This technique of applying an image to the surface of a polygon is called Texture Mapping. The image we use is called the Texture and the individual elements of the texture are called Texels.FogFog is an atmospheric effect that adds haziness to objects in a scene depending on how far the objects are from the viewer.Blending and TransparencyBlending is the combination of colors of objects on the screen. This effect can be used for a variety of purposes. By varying the amount each object is blended with the scene we can make objects look transparent.Anti-AliasingAliasing is an effect that is visible on screen due to the fact that an image consists of discrete pixels. By carefully blending the lines with the background color we can eliminate jagged edges and give them a smooth appearance. This blending technique is called anti-aliasing.第一个OpenGL程序复制代码//Simple.cpp - First OpenGL Program#include <windows.h> //Required for every Windows Program#include <gl\glut.h> //Required for using the GLUT library//Perform OpenGL Initialization herevoid SetupRC(){//Set the background clearing color to blueglClearColor(0.0f,0.0f,1.0f,1.0f);//设置背景色为蓝色}//The drawing callback functionvoid RenderScene(){//Clear the color bufferglClear(GL_COLOR_BUFFER_BIT);//Flush the rendering pipelineglFlush();}void main(){//Choose the display mode settingsglutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);//初始化显示模式(单缓冲,RGB)//Create the WindowglutCreateWindow("Simple");//创建窗口//Set the RenderScsne function as the display callbackglutDisplayFunc(RenderScene);//绘制回调函数,当窗口需要绘制时,GLUT会调用此函数//Initialize OpenGLSetupRC();//初始化OpenGL//Start the GLUT frameworkglutMainLoop();//开始消息循环}WGL – Windows的OpenGL扩展层The WGL extension consists of a set of functions (wglCreateContext, wglDeleteContext etc.) and structures (such as PIXELFORMATDESCRIPTOR, GLYPHMETRICSFLOAT) etc. Thus every OpenGL implementation has a platform-specific portion which has to be set up and used according to the particular platform.设备上下文The Windows Graphical Device Interface (GDI) is capable of drawing to screen, to memory, to printers or to any other device that provides a GDI interface layer and that can process GDI calls. GDI accomplishes this by a rendering handle to the currently selected device, which is called the device context, or DC.绘制上下文A rendering context is the OpenGL equivalent of the GDI DC. All OpenGL calls are rendered to the device through a RC. The rendering context maintains OpenGL state variables such as current background color, current color etc. just as the DC maintains GDI state variables such as current pen, current brush etc.像素格式Pixel formats are the translation layer between OpenGL calls and the rendering operation that Windows performs.举个例子,若像素格式只支持很少一部分颜色值,则OpenGL在用RGB值(128,120,135)绘制一个像素时,就可能使用转换后的值(128,128,128)来绘制.The pixel format selected essentially describes such things as how colors are displayed, depth of field resolution and what additional capabilities are supported by the rendering context created.第一个基于MFC的OpenGL应用程开发环境:VC6.01,首先下载需要的GLUT头文件,DLL和Lib文件,下载链接: glutdlls37beta.zip (149 kilobytes),解压缩后把gltu.h放到"VC98/Include/GL"下,把glut.lib和glut32.lib放到"VC9/Lib" 下,glut32.dll和glut.dll放到你创建的应用程序的运行目录下2,创建一个MFC SDI应用程序,在项目属性中加入所需要链接的库文件1,在stdafx.h中加入下列语句://OpenGL Headers#include <gl/gl.h>#include <gl/glu.h>#include <gl/glut.h>#include <gl/glaux.h>2,打开ClassWizard,选择CCY457OpenGLView类,为下述消息加入消息处理函数:WM_CREATE (for OnCreate), WM_DESTROY (for OnDestroy), WM_SIZE (for OnSize),WM_ERASEBACKGROUND (for OnEraseBkground).3,在窗口创建之前我们必须设置窗口风格包含WS_CLIPCHILDREN和WS_CLIPSIBLINGS,从而避免OpenGL绘制到其他窗口中去。
PictureControl控件中使用OpenGL绘图

PictureControl控件中使用OpenGL绘图如果你已经看到这篇文章,具体使用OpenGL的原因相信你比我清楚。
我是MFC兼OpenGL初学者,以下的知识是本人摸索试验出来的,只为了解决在PictureControl中正常使用OpenGL。
想在MFC对话框中使用OpenGL首先需要OpenGL静态库的支持#include"gl\gl.h"#include"gl\glu.h"#include"gl\glaux.h"具体配置方式网上有很多,并实践可行。
这里我只说明MFC中网上缺少的必要步骤。
第一步:包含头文件。
不一定像网上说的一定要包含于stdafx.h文件中。
可以写到任何CPP文件头部。
第二步:OpenGL的初始化。
定义InitializeOpenGL();函数体如下:IDC_IMAGE_DRAW为PictureControl控件IDBOOLCopenGLDlg::InitializeOpenGL(){m_pDC=newCClientDC(GetDlgItem(IDC_IMAGE_DRAW));〃获取设备DC,该DC为PictureControl的设备if(m_pDC==NULL){〃如果返回DC为空,则创建DC失败returnFALSE;}if(!SetupPixelFormat()){//像素格式化函数,简单的说就是指定绘图要用的像素格式,必须格式化,下面有像素格式化的函数体。
returnFALSE;}//创建绘图描述表m_hRC=::wglCreateContext(m_pDC->GetSafeHdc());if(m_hRC==0){//创建失败returnFALSE;}//使绘图描述表为当前调用现程的当前绘图描述表if(::wglMakeCurrent(m_pDC->GetSafeHdc(),m_hRC)==FALSE){returnFALSE;}//设置清除色::glClearColor(0.0f,0.0f,0.0f,0.0f);::glClearDepth(1.0f);::glEnable(GL_DEPTH_TEST);returnTRUE;//到此绘图环境初始化完成第三步;像素格式化函数体BOOLCopenGLDlg::SetupPixelFormat() {staticPIXELFORMATDESCRIPTORpfd={sizeof(PIXELFORMATDESCRIPTOR),1,PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER,PFD_TYPE_RGBA,24,0,0,0,0,0,0,0,0,0,buffer //sizeofthispfd//versionnumber//supportwindow//supportOpenGL//doublebuffered //RGBAtype//24-bitcolordepth //colorbitsignored //noalphabuffer//shiftbitignored //noaccumulation0,0,0,0, 16, 0, 0,PFD_MAIN_PLANE, 0, 0,0,0 };intmnPixelFormat=::ChoosePixelFormat(m_pDC->GetSafeHdc(),&p fd);if(m_nPixelFormat==0) {returnFALSE; }if(::SetPixelFormat(m_pDC->GetSafeHdc(),m_nPixelFormat,&pfd)==FALSE){returnFALSE; }returnTRUE;//accumbitsignored //16-bitz-buffer //nostencilbuffer //noauxiliarybuffer //mainlayer //reserved//layermasksignored}//这个函数网上描述的很清除,不解释作用第四步:获取画图的位置。
如何在MFC中调用OpenGL

如何在MFC中调用OpenGL第一步:在CView类cpp中添加头文件支持:#include <gl/GL.h>#include <gl/glut.h>第二步:更改窗口样式使其支持OpenGL.在CView类成员函数PreCreateWindow中添加代码cs.style|=WS_CLIPSIBLINGS|WS_CLIPCHILDREN;第三步:重写CView中的Create函数,在函数中添加代码CString ClassName=AfxRegisterWndClass(CS_OWNDC);第四步:重新设置像素格式,并将其设置为当前像素格式在CView类中添加public型成员函数BOOL SetupPixelFormat(HDC hDC);函数体如下://step 3 重新设置像素格式BOOL CXXXMFCGLView::SetupPixelFormat(HDC hDC){//重新设置画图窗口的像素格式static PIXELFORMATDESCRIPTOR pfd ={sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd1, // version numberPFD_DRAW_TO_WINDOW | // support windowPFD_SUPPORT_OPENGL | // support OpenGLPFD_DOUBLEBUFFER, // double bufferedPFD_TYPE_RGBA, // RGBA type24, // 24-bit color depth0, 0, 0, 0, 0, 0, // color bits ignored0, // no alpha buffer0, // shift bit ignored0, // no accumulation buffer0, 0, 0, 0, // accum bits ignored32, // 32-bit z-buffer0, // no stencil buffer0, // no auxiliary bufferPFD_MAIN_PLANE, // main layer0, // reserved0, 0, 0 // layer masks ignored };int pixelformat;//分配一个像素格式号if ( (pixelformat = ChoosePixelFormat(hdc, &pfd)) == 0 ){MessageBox(L"ChoosePixelFormat failed");return FALSE;}//设置为当前的像素格式if (SetPixelFormat(hdc, pixelformat, &pfd) == FALSE){MessageBox(L"SetPixelFormat failed");return FALSE;}return TRUE;}第五步:在CView类中添加消息WM_CREATE,在OnCreate函数中添加代码HDC hDC;HGLRC hRC;hDC=::GetDC(GetSafeHwnd());SetupPixelFormat(hDC);hRC=wglCreateContext(hDC);wglMakeCurrent(hDC, hRC);第六步:初始化OpenGL重写CView类中的OnInitialUpdate,根据需要在OnInitialUpdate中添加代码这里OnInitialUpdate的作用与常用的OpenGL控制台程序中init()相同例如://初始化OpenGL//////////////////////////////////////////////////////glClearColor(1.0, 1.0, 1.0, 1.0);glEnable(GL_SMOOTH);glEnable(GL_DEPTH_TEST);//set material property1glNewList(0, GL_COMPILE);glEnable(GL_COLOR_MATERIAL);GLfloat mat_ambient[]={0.15, 0.07, 0.04, 1.0}; //原材料的环境颜色GLfloat mat_diffuse[]={0.15, 0.07, 0.04, 1.0}; //原材料的散射颜色GLfloat mat_specular[]={0.15, 0.07, 0.04, 1.0}; //原材料的反射颜色GLfloat mat_emission[]={0.15, 0.07, 0.04, 1.0}; //原材料的发散颜色glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);glMaterialf(GL_FRONT, GL_SHININESS, 50.0);glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission);glEndList();//set light0glNewList(1, GL_COMPILE);glEnable(GL_LIGHTING);GLfloat light0_position[]={1.0, 1.0, 1.0, 1.0};GLfloat light0_spot_direction[]={-1.0, -1.0, -1.0, 1.0};GLfloat light0_ambient[]={0.015, 0.007, 0.004, 1.0};GLfloat ligh0_diffuse[]={1.0, 1.0, 1.0, 1.0};GLfloat light0_specular[]={1.0, 1.0, 1.0, 1.0};glLightfv(GL_LIGHT0, GL_POSITION, light0_position);glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 45);glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, light0_spot_direction);glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient);glLightfv(GL_LIGHT0, GL_DIFFUSE, ligh0_diffuse);glLightfv(GL_LIGHT0, GL_SPECULAR, light0_specular);glEnable(GL_LIGHT0);glEndList();//////////////////////////////////////////////////////第七步:在CView类中添加WM_SIZE的消息响应函数OnSize这里OnSize的作用与OpenGL控制台编程中reshape的作用相同根据需要在其中添加代码例如://////////////////////////////////////////////////////glCallList(1);glViewport(0, 0, cx, cy);glMatrixMode(GL_PROJECTION);glLoadIdentity();if (cx <= cy)gluOrtho2D (-1.0, 1.0,-1.0*(GLfloat)cy/(GLfloat)cx, 1.0*(GLfloat)cy/(GLfloat)cx);elsegluOrtho2D (-1.0*(GLfloat)cx/(GLfloat)cy,1.0*(GLfloat)cx/(GLfloat)cy, -1.0, 1.0);glMatrixMode(GL_MODELVIEW);glLoadIdentity();//////////////////////////////////////////////////////第八步:根据需要在CView类OnDraw函数中添加代码绘图在这里OnDraw的功能与OpenGL按制台编程中的display函数相同例如://////////////////////////////////////////////////////glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);glRotatef(0, 1.0f, 0.0f, 0.0f);glRotatef(0, 0.0f, 1.0f, 0.0f);glCallList(0);glutSolidTeapot(0.5);glPushMatrix();glTranslatef(-0.8, -0.3, -0.2);glutSolidTorus(0.1, 0.2, 50, 60);glPopMatrix();glPushMatrix();glTranslatef(0.9, 0, 0);glutSolidSphere(0.2, 80, 80);glPopMatrix();glFlush();SwapBuffers(wglGetCurrentDC());//////////////////////////////////////////////////////第九步:在CView类中添加WM_DESTROYR的消息响应函数OnDestroy 在其中添加如下代码:HGLRC hRC;hRC=wglGetCurrentContext();wglMakeCurrent(NULL, NULL);if (hRC){wglDeleteContext(hRC);}到这里,一个完整的MFC调用OpenGL的程序就大功告成了。
《基于MFC的OpenGL编程》Part6

ˈЎಯϾџӊ໘ˊߑ᭄ࡴܹࠊҷۅ
YRLG &2SHQ*/9LHZ2Q.H\'RZQ 8,17 Q&KDU 8,17 Q5HS&QW 8,17 Q)ODJV ^ 72'2 $GG \RXU PHVVDJH KDQGOHU FRGH KHUH DQGRU FDOO GHIDXOW VZLWFK Q&KDU ^ FDVH 9.B83 FDVH 9.B'2:1 FDVH 9.B/()7 FDVH 9.B5,*+7 GHIDXOW ` ,QYDOLGDWH5HFW 18//)$/6( &9LHZ2Q.H\'RZQ Q&KDU Q5HS&QW Q)ODJV ` YRLG &2SHQ*/9LHZ2Q/%XWWRQ'RZQ 8,17 Q)ODJV &3RLQW SRLQW ^ 72'2 $GG \RXU PHVVDJH KDQGOHU FRGH KHUH DQGRU FDOO GHIDXOW PB0RXVH'RZQ3RLQW SRLQW 6HW&DSWXUH &9LHZ2Q/%XWWRQ'RZQ Q)ODJV SRLQW ` YRLG &2SHQ*/9LHZ2Q/%XWWRQ8S 8,17 Q)ODJV &3RLQW SRLQW ^ 72'2 $GG \RXU PHVVDJH KDQGOHU FRGH KHUH DQGRU FDOO GHIDXOW PB0RXVH'RZQ3RLQW &3RLQW 5HOHDVH&DSWXUH &9LHZ2Q/%XWWRQ8S Q)ODJV SRLQW ` YRLG &2SHQ*/9LHZ2Q0RXVH0RYH 8,17 Q)ODJV &3RLQW SRLQW ^ 72'2 $GG \RXU PHVVDJH KDQGOHU FRGH KHUH DQGRU FDOO GHIDXOW &KHFN LI ZH KDYH FDSWXUHG WKH PRXVH PB\3RV EUHDN PB\3RV EUHDN PB[3RV EUHDN PB[3RV PB[3RV I EUHDN 0HVVDJH%R[ 3UHVV WKH DUURZ NH\V RQO\ EUHDN PB[3RV I PB\3RV I PB\3RV I
在MFC框架下用OpenGL绘制金字塔及棋盘纹理

1应用程序功能要求使用多边形建模的方法构造一个金字塔(正四棱锥),并赋予黄金的黄铜材质使用Bezier曲面建模方法构建一块起伏的地板,并赋予绿色的塑料材质和类似国际象棋棋盘的纹理贴图且具有光照效果2建立工程运行VC++ 6.0,新建一个名为MyOpenGL的单文档MFC(Single document)项目,全部使用默认设置3设置环境参数通过菜单Project->Setting打开设置对话框,选择Link属性页,在Object/library modules 中输入opengl32.lib glu32.lib glaux.lib,注意中间以空格隔开,然后单击OK按钮,这是为了装载OpenGL编程所需的函数库。
也可以直接在CMyOpenGLView的头文件(即MyOpenGLView.h)中直接输入一下的编译参数:#pragma comment(lib,"opengl32.lib") //装载opengl32.lib#pragma comment(lib,"glu32.lib")#pragma comment(lib,"glaux.lib")上述设置与Setting对话框中直接设置的效果是一样的。
配置好链接库后,在CMyOpenGLView的头文件加入以下预处理命令:#include <gl/GL.H>#include <gl/GLU.H>#include <gl/GLAUX.H>之所以在MyOpenGLView.h中导入这些头文件,是因为整个图形编写过程都是在CMyOpenGLView中完成的。
完成上述配置后,就可以调用OpenGL的库函数了,否则会因为系统找不到OpenGL 的库函数,而出现一堆编译错误。
4设置窗口风格在CMyOpenGLView的PreCreateWindow()函数中,修改代码如下:BOOL CMyOpenGLView::PreCreateWindow(CREA TESTRUCT& cs){// TODO: Modify the Window class or styles here by modifying// the CREATESTRUCT cscs.style |=WS_CLIPSIBLINGS | WS_CLIPCHILDREN;//设置窗口风格,使得支持openglreturn CView::PreCreateWindow(cs);}5定义绘图上下文成员变量与Windows的DC(Device Context)类似,OpenGL使用了一个叫RC(Rendering Context)的上下文来进行绘图,所以必须为CMyOpenGLView添加一个HGLRC类型的成员变量m_hGLRC:HGLRC m_hGLRC; //OpenGL的绘图上下文(Rendering Context)6创建OpenGL绘图环境定义了m_hGLRC,接下来的工作便是在CMyOpenGLView类中的OnCreate()成员函数中创建它。
MFC+OpenGL 编程入门

MFC+OpenGL 编程入门OpenGL 作图非常方便,故日益流行,但对许多人来说,是在微机上进行的,首先碰到的问题是,如何适应微机环境。
这往往是最关键的一步,虽然也是最初级的。
下面介绍如何在VC++ 上进行OpenGL 编程。
其实相当简单明快,只因国内缺少这方面的资料与例子,致使许多小细节要一个一个地试,耗去大量时间。
希望各位有什么心得体会,也公布出来,从而节省每个人都要试试的时间。
言归正传,下面以画一条Bezier 曲线为例,详细介绍VC++ 上OpenGL编程的方法。
这里实际上也给出了个C++ 良好封装性编程的范例。
文中给出了详细注释,以便给初学者明确的指引。
一步一步地按所述去做,你将顺利地画出第一个OpenGL 平台上的图形来。
(本文例子以VC++ 5.0 为背景)一、产生程序框架Test.dswNew Project | MFC Application Wizard (EXE) | "Test" | OK*注* : 加“”者指要手工敲入的字串二、导入Bezier 曲线类的文件。
用下面方法产生BezierCurve.hBezierCurve.cpp 两个文件:WorkSpace | ClassView | Test Classes| <右击弹出> New Class| Generic Class(不用MFC类) | "CBezierCurve" | OK三、编辑好Bezier 曲线类的定义与实现。
写好下面两个文件:BezierCurve.hBezierCurve.cpp四、设置编译环境:1. 在BezierCurve.h 和TestView.h 内各加上:#include <GL/gl.h>#include <GL/glu.h>#include <GL/glaux.h>2. 在集成环境中,Project | Settings | Link | Object/library module| "opengl32.lib glu32.lib glaux.lib" | OK五、设置OpenGL 工作环境:(下面各个操作,均针对TestView.cpp )1. 处理PreCreateWindow(): 设置OpenGL 绘图窗口的风格cs.style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN | CS_OWNDC;2. 处理OnCreate():创建OpenGL 的绘图设备。
MFC下基于OpenGL绘图程序的开发步骤和框架

。 能 体 整 和 识 意 任 责 员 高 提 范 规 描 位 岗 、 操 认 确 述 口 指 手 实 落 面 作 工 训 培 育 教 术 技 全 安 抓 狠 设 ”建 基 “双 化 深 断 不 , 织 组 合 理 管 学 科
int m_GLPixelIndex; 其它具体函数及其参数含义,大家可以通过 OpenGL 手册或者 MSDN 查询。这里不作累述。 (2)现在绘制窗口像素格式已经定义好,下一步工作是产生绘制上下文(RC)并使之成为当 前绘制上下文。在视类中加入一个私有型成员函数 BOOL CreateViewGLContext(HDC hDC)。 其中,m_hGLContext 为在视类中添加的一私有型的成员变量: HGLRC m_hGLContext;HGLRC 是一个指向 rendering context 的句柄。 (3)最后,在视类的 OnCreate 函数(OnCreate 函数相应 Window 消息 WM_CREATE,可以通 过 VC 的类向导 Class Wizard Ctrl+W 进行添加,如图)中实现上述两个函数的调用,实现 RC 的定义、产生以及和当前视区窗口 DC 的通讯。 6、添加绘图函数 视类函数 OnDraw 主要负责视区的绘图工作。为了在视区窗口利用 OpenGL 绘制图形,我 们自定义一个绘图函数 DrawScene(), 并 OnDraw 函数中调用该函数, 从而实现在视区窗口绘图。 7、修改视类 OnSize 函数 当视区绘图窗口大小变化时,应及时将新的窗口大小通知 OpenGL,才能在绘图窗口以正 确的比例显示图形。当视区窗口大小变化时,WM_SIZE 消息被触发,所以可以通过 VC 的类向 导 Class Wizard Ctrl+W 添加 WM_SIZE 的消息映射函数 OnSize。 然后对 OnSize 函数做修改。 8、修改视类 OnEraseBkgnd 函数 仿造第 7 步的方法通过类向导 Class Wizard 添加视类对消息 WM_ERASEBKGND 的映射函 数 OnEraseBkgnd,并对该函数进行修改。修改该函数的主要原因是:OpenGL 自身具有重绘能 力,通过修改该函数屏蔽 Window 的重绘操作,从而可以防止窗口频繁刷新时产生的闪烁现象。 9、回收 RC 所占用的资源 通过 VC 的类向导 Class Wizard Ctrl+W 添加 Window 消息 WM_DESTROY 的映射函数 OnDestroy 函数。在该函数中调用 OpenGL 函数 wglDeleteContext 对 RC 所占资源进行回收。注 意,回收之前需要先使用 OpenGL 函数 wglMakeCurrent 断开 RC 与 DC 的连接。 10、初始化绘图数据 编辑视类构造函数,初始化绘图数据。 至此,我们已构造好了框架,使该工程可以利用 OpenGL 进行绘图了。假设现在绘制一个 三角形,只需要在第 6 步添加的 DrawScene 函数中添加绘制三角形的函数, (二)生成三维物体 1) 首先,在 OnSize()中,把 gluOrtho2D(0.0, 500.0*aspect,0.0, 500.0)换成 gluPerspective(60, aspect, 1, 10.0);这样就实现了三维透视坐标系的设置。该语句说明了视点在原点,透视角是 60 度,近裁剪面在 z=1 处,远裁剪面在 z=10.0 处。 2) 在 DrawScene 函数中生成三维图形;
VC(MFC)开发OPENGL程序

VC(MFC)开发OPENGL程序作者:李英江日期: 2006-08-10 19:07:00网站:转载请保留作者内容!利用使用VC开发OPENGL程序,运用MFC库,做一个简单例子我简单介绍一下图形接口,现在流行的两大图形接口Direct3D 和OpenGL,Direct3D主要是针对游戏,像starcaft星际争霸,它支持DX5.0以上的版本,但是不少游戏同时支持两种图形加速,如CS,魔兽争霸。
OpenGL主要是针对专业的图形应用,在军事,医学,GIS地理信息系统,动画(3dsmax,maya...),电影,等应用广泛,并且可以在不同的平台上应用,DX相对来说就只能限于Windows操作系统了。
1.运用MFC向导,生成一个单文档应用程序,不做任何事的MFC 框架程序。
2.视图类中添加窗口样式。
/************************************************************** *******/BOOL CMfc_basicView::PreCreateWindow(CREATESTRUCT& cs){// Add Window styles required for OpenGL before window iscreatedcs.style |= (WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CS_OWNDC);return CView::PreCreateWindow(cs);}/************************************************************** *******/3.在afxcmn.h中包含OPENGL头文件。
/************************************************************** *******/#include <afxcmn.h>// MFC support for Windows Common Controls// Inserted these files for openGL#include <gl.h>#include <glut.h>#include <glu.h>#include <glaux.h>#endif // _AFX_NO_AFXCMN_SUPPORT/************************************************************** *******/4.视图类中 .h文件中加入四个public 成员变量/************************************************************** *******/HGLRC m_hRC; // Permanent Rendering ContextHDC m_myhDC; // Private GDI Device Contextint m_height; // Stores the height of the Viewint m_width; // Stores the width of the view/************************************************************** *******/5.视图类中右键添加一个BOOL成员函数SetupPixelFormat/************************************************************** *******/BOOL COglm_demoView::SetupPixelFormat(){GLuint PixelFormat;static PIXELFORMATDESCRIPTOR pfd= {sizeof(PIXELFORMATDESCRIPTOR),// Size Of This Pixel Format Descriptor1,// Version Number (?)PFD_DRAW_TO_WINDOW | // Format Must Support WindowPFD_SUPPORT_OPENGL | // Format Must Support OpenGL PFD_DOUBLEBUFFER, // Must Support Double Buffering PFD_TYPE_RGBA, // Request An RGBA Format24, // Select A 24Bit Color Depth0, 0, 0, 0, 0, 0, // Color Bits Ignored (?)0, // No Alpha Buffer0, // Shift Bit Ignored (?)0, // No Accumulation Buffer0, 0, 0, 0, // Accumulation Bits Ignored (?)16, // 16Bit Z-Buffer (Depth Buffer)0, // No Stencil Buffer0, // No Auxiliary Buffer (?)PFD_MAIN_PLANE, // Main Drawing Layer0, // Reserved (?)0, 0, 0 // Layer Masks Ignored (?)};m_myhDC = ::GetDC(m_hWnd); // Gets A Device Context For The WindowPixelFormat = ChoosePixelFormat(m_myhDC, &pfd); // Finds The Closest Match To The Pixel Format We Set Aboveif (!PixelFormat){::MessageBox(0,"Can't Find A Suitable PixelFormat.","Error",MB_OK|MB_ICONERROR);PostQuitMessage(0);// This Sends A 'Message' Telling The Program To Quitreturn false ; // Prevents The Rest Of The Code From Running}if(!SetPixelFormat(m_myhDC,PixelFormat,&pfd)){::MessageBox(0,"Can't Set The PixelFormat.","Error",MB_OK|MB_ICONERROR);PostQuitMessage(0);return false;}m_hRC = wglCreateContext(m_myhDC);if(!m_hRC){::MessageBox(0,"Can't Create A GL Rendering Context.","Error",MB_OK|MB_ICONERROR);PostQuitMessage(0);return false;}if(!wglMakeCurrent(m_myhDC, m_hRC)){::MessageBox(0,"Can't activate GLRC.","Error",MB_OK|MB_ICONERROR);PostQuitMessage(0);return false;}// Now that the screen is setup we can// initialize OpenGL();InitGL();return true;}/************************************************************** *******/6.关闭WM_ERASEBACKGROUND消息,不关闭的话,画图时会闪动.在视图类中选择“Add Windows Message Handler”加入消息处理函数./************************************************************** *******/BOOL CMfc_basicView::OnEraseBkgnd(CDC* pDC){return FALSE;}/************************************************************** *******/7.初始化OPENGL 添加InitGL()函数./************************************************************** *******/void CMfc_basicView::InitGL(){// Enables Depth TestingglEnable(GL_DEPTH_TEST);// Enable the point size for selected pointsglPointSize(5.0f);// This Will Clear The Background Color To BlackglClearColor(.4, 0.2, 0.0, 0.0f);// Reset the current projection matrixSetProjection();glMatrixMode(GL_MODELVIEW);glLoadIdentity();//Enable back face culling, defaults to Clock wise vertices.glEnable(GL_CULL_FACE);glEnable(GL_COLOR_MATERIAL);glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);glShadeModel(GL_SMOOTH);glPolygonMode(GL_FRONT, GL_FILL);}/************************************************************** *******/8. 在视图类中添加调窗口大小的处理函数OnSize() 消息句柄/************************************************************** *******/void CMfc_basicView::OnSize(UINT nType, int cx, int cy){CView::OnSize(nType, cx, cy);glMatrixMode(GL_MODELVIEW);glLoadIdentity();// Make the rendering context currentwglMakeCurrent(m_myhDC,m_hRC);// Reset The Current Viewport And Perspective TransformationglViewport(0, 0, cx, cy);m_height= cy;m_width = cx;// Calculate The Aspect Ratio Of The WindowgluPerspective(60.0f,(GLfloat)cx/(GLfloat)cy,0.1f,1000.0f);}9.添加SetPorjection()函数void CMfc_basicView::SetProjection(){glViewport(0, 0, m_width, m_height);// Reset The Projection MatrixglMatrixMode(GL_PROJECTION);glLoadIdentity();// It's a perspective projection// Calculate The Aspect Ratio Of The WindowgluPerspective(60.0f,(GLfloat)m_width/(GLfloat)m_height, 0.1f,3000.0f);}/************************************************************** *******/10.在Project 菜单选择Settings. 单击Link 选项页Object/library Module添加库文件.opengl32.lib glu32.lib glut.lib glaux.lib11.在视图类中加入OnCreate消息句柄/*********************************************************************/int CMfc_basicView::OnCreate(LPCREATESTRUCT lpCreateStruct){if (CView::OnCreate(lpCreateStruct) == -1)return -1;SetupPixelFormat();wglMakeCurrent(NULL,NULL);return 0;}/************************************************************** *******///现在编译程序的话,会看到一个无法刷新的应用程序了。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
基于MFC的OpenGL绘图本文更新版本请点击[置顶]《基于MFC的OpenGL编程》系列文章一、简介GDI是通过设备句柄(Device Context以下简称"DC")来绘图,而OpenGL则需要绘制环境(Rendering Context,以下简称"RC")。
每一个GDI命令需要传给它一个DC,但与GDI不同,OpenGL使用当前绘制环境(RC)。
一旦在一个线程中指定了一个当前RC,在此线程中其后所有的OpenGL命令都使用相同的当前RC。
虽然在单一窗口中可以使用多个RC,但在单一线程中只有一个当前RC。
下面我将首先产生一个OpenGL RC并使之成为当前RC,这将分为三个步骤:设置窗口像素格式;产生RC;设置为当前RC。
二、MFC中的OpenGL基本框架1、首先创建工程用AppWizard产生一个MFC EXE项目,其他默认即可。
2、将此工程所需的OpenGL文件和库加入到工程中在工程菜单中,选择"Build"下的"Settings"项。
单击"Link"标签,选择"General"目录,在Object/Library Modules的编辑框中输入"opengl32.lib glu32.lib glut.lib glaux.lib"(注意,输入双引号中的内容,各个库用空格分开;否则会出现链接错误),选择"OK"结束。
然后打开文件"stdafx.h",加入下列头文件:#include <gl\gl.h>#include <gl\glu.h>3、改写OnPreCreate函数并给视图类添加成员函数和成员变量OpenGL需要窗口加上WS_CLIPCHILDREN(创建父窗口使用的Windows风格,用于重绘时裁剪子窗口所覆盖的区域)和WS_CLIPSIBLINGS(创建子窗口使用的Windows风格,用于重绘时剪裁其他子窗口所覆盖的区域)风格。
把OnPreCreate改写成如下所示:BOOL COpenGLDemoView::PreCreateWindow(CREATESTRUCT& cs){// TODO: Modify the Window class or styles here by modifying// the CREATESTRUCT cscs.style |= (WS_CLIPCHILDREN | WS_CLIPSIBLINGS);return CView::PreCreateWindow(cs);}产生一个RC的第一步是定义窗口的像素格式。
像素格式决定窗口着所显示的图形在内存中是如何表示的。
由像素格式控制的参数包括:颜色深度、缓冲模式和所支持的绘画接口。
在下面将有对这些参数的设置。
我们先在COpenGLDemoView的类中添加一个保护型的成员函数BOOL SetWindowPixelFormat(HDC hDC)(用鼠标右键添加)和保护型的成员变量:int m_GLPixelIndex;并编辑其中的代码如下:BOOL COpenGLDemoView::SetWindowPixelFormat(HDC hDC){//定义窗口的像素格式PIXELFORMATDESCRIPTOR pixelDesc={sizeof(PIXELFORMATDESCRIPTOR),1,PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER|PFD_SUPPORT_GDI,PFD_TYPE_RGBA,24,0,0,0,0,0,0,0,0,0,0,0,0,0,32,0,0,PFD_MAIN_PLANE,0,0,0,0};this->m_GLPixelIndex = ChoosePixelFormat(hDC,&pixelDesc);if(this->m_GLPixelIndex==0){this->m_GLPixelIndex = 1;if(DescribePixelFormat(hDC,this->m_GLPixelIndex,sizeof(PIXELFORMATDES CRIPTOR),&pixelDesc)==0){return FALSE;}}if(SetPixelFormat(hDC,this->m_GLPixelIndex,&pixelDesc)==FALSE){return FALSE;}return TRUE;4、用ClassWizard添加WM_CREATE的消息处理函数OnCreate至此,OpenGL工程的基本框架就建好了。
但如果你现在运行此工程,则它与一般的MFC 程序看起来没有什么两样。
5、代码解释现在我们可以看一看Describe-PixelFormat提供有哪几种像素格式,并对代码进行一些解释:PIXELFORMATDESCRIPTOR包括了定义像素格式的全部信息。
DWFlags定义了与像素格式兼容的设备和接口。
通常的OpenGL发行版本并不包括所有的标志(flag)。
wFlags能接收以下标志:PFD_DRAW_TO_WINDOW 使之能在窗口或者其他设备窗口画图;PFD_DRAW_TO_BITMAP 使之能在内存中的位图画图;PFD_SUPPORT_GDI 使之能调用GDI函数(注:如果指定了PFD_DOUBLEBUFFER,这个选项将无效);PFD_SUPPORT_OpenGL 使之能调用OpenGL函数;PFD_GENERIC_FORMAT 假如这种象素格式由Windows GDI函数库或由第三方硬件设备驱动程序支持,则需指定这一项;PFD_NEED_PALETTE 告诉缓冲区是否需要调色板,本程序假设颜色是使用24或32位色,并且不会覆盖调色板;PFD_NEED_SYSTEM_PALETTE 这个标志指明缓冲区是否把系统调色板当作它自身调色板的一部分;PFD_DOUBLEBUFFER 指明使用了双缓冲区(注:GDI不能在使用了双缓冲区的窗口中画图);PFD_STEREO 指明左、右缓冲区是否按立体图像来组织。
PixelType定义显示颜色的方法。
PFD_TYPE_RGBA意味着每一位(bit)组代表着红、绿、蓝各分量的值。
PFD_TYPE_COLORINDEX 意味着每一位组代表着在彩色查找表中的索引值。
本例都是采用了PFD_TYPE_RGBA方式。
● cColorBits定义了指定一个颜色的位数。
对RGBA来说,位数是在颜色中红、绿、蓝各分量所占的位数。
对颜色的索引值来说,指的是表中的颜色数。
● cRedBits、cGreenBits、cBlue-Bits、cAlphaBits用来表明各相应分量所使用的位数。
● cRedShift、cGreenShift、cBlue-Shift、cAlphaShift用来表明各分量从颜色开始的偏移量所占的位数。
一旦初始化完我们的结构,我们就想知道与要求最相近的系统象素格式。
我们可以这样做:m_hGLPixelIndex = ChoosePixelFormat(hDC, &pixelDesc);ChoosePixelFormat接受两个参数:一个是hDc,另一个是一个指向PIXELFORMATDESCRIPTOR结构的指针& pixelDesc;该函数返回此像素格式的索引值。
如果返回0则表示失败。
假如函数失败,我们只是把索引值设为1并用DescribePixelFormat 得到像素格式描述。
假如你申请一个没得到支持的像素格式,则Choose-PixelFormat将会返回与你要求的像素格式最接近的一个值。
一旦我们得到一个像素格式的索引值和相应的描述,我们就可以调用SetPixelFormat设置像素格式,并且只需设置一次。
现在像素格式已经设定,我们下一步工作是产生绘制环境(RC)并使之成为当前绘制环境。
在COpenGLDemoView中加入一个保护型的成员函数BOOL CreateViewGLContext(HDC hDC),并加入一个保护型的成员变量HGLRC m_hGLContext;HGLRC是一个指向rendering context的句柄。
BOOL COpenGLDemoView::CreateViewGLContext(HDC hDC){this->m_hGLContext = wglCreateContext(hDC);if(this->m_hGLContext==NULL){//创建失败return FALSE;}if(wglMakeCurrent(hDC,this->m_hGLContext)==FALSE){//选为当前RC失败return FALSE;}return TRUE;}在OnCreate函数中调用此函数:int COpenGLDemoView::OnCreate(LPCREATESTRUCT lpCreateStruct) {if (CView::OnCreate(lpCreateStruct) == -1)return -1;// TODO: Add your specialized creation code hereHWND hWnd = this->GetSafeHwnd();HDC hDC = ::GetDC(hWnd);if(this->SetWindowPixelFormat(hDC)==FALSE){return 0;}if(this->CreateViewGLContext(hDC)==FALSE){return 0;}return 0;}添加WM_DESTROY的消息处理函数Ondestroy( ),使之如下所示:void COpenGLDemoView::OnDestroy(){CView::OnDestroy();// TODO: Add your message handler code hereif(wglGetCurrentContext()!=NULL){wglMakeCurrent(NULL,NULL);}if(this->m_hGLContext!=NULL){wglDeleteContext(this->m_hGLContext);this->m_hGLContext = NULL;}}最后,编辑COpenGLDemoView的构造函数,使之如下所示:COpenGLDemoView::COpenGLDemoView(){// TODO: add construction code herethis->m_GLPixelIndex = 0;this->m_hGLContext = NULL;}至此,我们已经构造好了框架,使程序可以利用OpenGL进行画图了。