`
icheng
  • 浏览: 829887 次
  • 性别: Icon_minigender_1
  • 来自: 珠海
文章分类
社区版块
存档分类
最新评论

Win32 OpenGL 编程(1)Win32下的OpenGL编程必须步骤

 
阅读更多

Win32 OpenGL 编程( 1 Win32 下的 OpenGL 编程必须步骤

write by 九天雁翎 (JTianLing) -- blog.csdn.net/vagrxie

讨论新闻组及文件

一、 前言

人生在于折腾,继续折腾吧。 OpenGL 编程的红宝书《 OpenGL Programming Guide 》在举例子的时候为了平台无关,使用的都是 GLUT 来管理窗口,个人感觉不爽 -_-! 要是针对 Windows 平台,个人倾向使用 Win32(MFC 也行 ) ,要是跨平台,我还会 Qt 嘛, Qt OpenGL 也有很好的支持的,为啥还折腾个新的窗口管理组件?虽然说 GLUT 比较简单,但是还是不喜欢扭曲的适应之,何况我去看了下 GLUT 这个东西,最新的版本都是 2001 年发布的了,什么古董级的家伙啊,更加不想用了,还是在 Windows 平台上学习 OpenGL 吧。刚开始这样想的就这样做了,结果比我想象的稍微复杂一些,原来不光是熟悉 Win32 API 就能随便搞掂的,当时还看到有人专门为此写了篇论文 -_-!( 不知道学历 ) 吓到我了,没有那么高的学术研究价值吧?后来又看到 3 个研究生都开始为此写论文了(这还真是研究院中的人写的),感叹不已。。。。。。。。。。

二、 提要

本文主要介绍 Win32 下的 OpenGL 编程需要的一些操作,以 Andre LaMothe T3D Game Console Win32 框架实现一个 Win32 下的 OpenGL 游戏编程框架, 以参考资料 2 为蓝本,实现一些 OpenGL 示例。以后的讲解围绕此框架展开。本文假设读者已经具备基本的 Win32 编程知识,不讲解 Win32 编程中固有的要素,需要了解 Win32 编程的,建议学习 Charles Petzold 的《 Programming Windows 》。

三、 Win32 OpenGL 编程需要的操作步骤

全部源代码见我的放在 Google Code 上的 blog-sample-code 2009-9-27/Win32OpenGLTemplate 目录。取回方式见本文最后的说明。

下面会用到的全局变量:

// GLOBALS ////////////////////////////////////////////////

HWND ghWnd ; // 窗口句柄

HINSTANCE ghInstance ; // 程序实例句柄

HDC ghDC ; // GDI 设备环境句柄

HGLRC ghRC ; // 渲染环境句柄

1. 头文件

#include <windows.h>

// OpenGL 需要的头文件

#include <GL/gl.h>

#include <GL/glu.h>

需要注意的就是,必须先包含 Windows.h ,然后才能包含 gl.h glu.h 。因为 gl.h glu.h 中可能包含 Windows.h 中定义的宏。

2. 链接库

此步完全可以通过功能配置来完成,需要包含的库 opengl32.lib glu32.lib ,事实上,为了方便,可以通过如下语句来完成( VC++ 特有特性),但是我们讨论的是 Win32 下的 OpenGL ,这样也能接受了。

// 定义程序链接时所需要调用的OpenGL 程序库, 简化工程配置

#pragma comment ( lib , "opengl32.lib" )

#pragma comment ( lib , "glu32.lib" )

3. 像素格式 (Pixel Format) 设置

需要用到的函数的原型:

int ChoosePixelFormat(


 
HDC 

hdc





, 
// device context to search for a best pixel format 



// match


 
CONST PIXELFORMATDESCRIPTOR * 

ppfd





 



// pixel format for which a best match is sought


);

BOOL SetPixelFormat(


 
HDC 

hdc





, 
// device context whose pixel format the function 



// attempts to set


 
int 

iPixelFormat





,


 
// pixel format index (one-based)


 
CONST PIXELFORMATDESCRIPTOR * 

ppfd





 



// pointer to logical pixel format specification


);


这是 Win32 下的 OpenGL 编程必做的事情之一,为 DC 设置像素的格式。

// 设置像素格式

PIXELFORMATDESCRIPTOR pfd ;

int iFormat ;

ghDC = GetDC ( ghWnd );

ZeroMemory ( & pfd , sizeof ( pfd ) );

pfd . nSize = sizeof ( pfd );

pfd . nVersion = 1; // 版本,一般设为

pfd . dwFlags = PFD_DRAW_TO_WINDOW | // 一组表明象素缓冲特性的标志位

PFD_SUPPORT_OPENGL ;

pfd . iPixelType = PFD_TYPE_RGBA ; // 明象素数据类型是RGBA 还是颜色索引;

pfd . cColorBits = 32; // 每个颜色缓冲区中颜色位平面的数目,对颜色索引方式是缓冲区大小

pfd . iLayerType = PFD_MAIN_PLANE ; // 被忽略,为了一致性而包含的

iFormat = ChoosePixelFormat ( ghDC , & pfd ); // 选择一个像素格式

SetPixelFormat ( ghDC , iFormat , & pfd ); // 设置到DC

这样的函数完成了像素格式的设置,事实上还可以进行更多的操作,比如设置缓冲区等,下面的代码就是一个设置双重缓冲区的代码。

PIXELFORMATDESCRIPTOR pfd;

ZeroMemory( &pfd, sizeof( pfd ) );

pfd.nSize = sizeof( pfd );

pfd.nVersion = 1;

pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL |

PFD_DOUBLEBUFFER;

pfd.iPixelType = PFD_TYPE_RGBA;

pfd.cColorBits = 32;

pfd.cDepthBits = 32;

pfd.iLayerType = PFD_MAIN_PLANE;

int iFormat = ChoosePixelFormat( hDC, &pfd );

SetPixelFormat( hDC, iFormat, &pfd );

具体的每个参数的意义,最好还是去查查 MSDN 啦,查看 PIXELFORMATDESCRIPTOR 结构的解释就行。

4. 渲染器环境 (Render Context) 创建

调用 wglCreateContext wglMakeCurrent 函数 ,这两个函数都是 Windows 下为了兼容 OpenGL 而特别提供的接口,以 wgl 开头。

函数原型:

HGLRC wglCreateContext(


 
HDC 

hdc





 
// device context of device that the rendering context 



// will be suitable for


);


BOOL wglMakeCurrent(


 
HDC 

hdc





, 
// device context of device that OpenGL calls are 



// to be drawn on


 
HGLRC 

hglrc





 
// OpenGL rendering context to be made the calling 




// thread's current rendering context


);

调用方式如下:

ghRC = wglCreateContext ( ghDC ); // 创建渲染环境

wglMakeCurrent ( ghDC , ghRC ); // 使之成为当前渲染环境

5. 实际绘制

这个部分就与一般的 OpenGL 一致,在后面慢慢展开讲述。

6. 释放资源

首先取消当前的渲染环境选中,然后依次删除渲染环境与设备环境。

需要调用的函数原型:

BOOL wglDeleteContext(


 
HGLRC 

hglrc





 
// handle to the OpenGL rendering context to delete


);

// 取消OpenGL ,在程序结束前调用,释放渲染环境,设备环境以及最终窗口句柄。

void DisableOpenGL ()

{

wglMakeCurrent ( NULL , NULL );

wglDeleteContext ( ghRC );

ReleaseDC ( ghWnd , ghDC );

}

上述流程基本就是一个完整的 Win32 OpenGL 程序所需要的了。。。。。。实际上在参考 5 中,有较为详细的论述,但是事实上,你也可以作为论文发表,见参考 3.

四、 真正的 OpenGL 相关内容

1. 静态图形显示演示:一个矩形

见参考 2 中(即所谓的 OpenGL 红宝书 The Red Book )中的例子

基本流程分两部分,初始化和实际绘制:

//OpenGL 初始化开始

void SceneInit ( int w , int h )

{

glClearColor (0.0f, 0.0f, 0.0f, 0.0f); // 黑色背景

glMatrixMode ( GL_PROJECTION );

glLoadIdentity ();

glOrtho (0.0, 1.0, 0.0, 1.0, -1.0, 1.0);

}

// 这里进行所有的绘图工作

void SceneShow ( GLvoid )

{

glClear ( GL_COLOR_BUFFER_BIT );

glColor3f (1.0, 1.0, 1.0);

glBegin ( GL_POLYGON );

glVertex3f (0.25, 0.25, 0.0);

glVertex3f (0.75, 0.25, 0.0);

glVertex3f (0.75, 0.75, 0.0);

glVertex3f (0.25, 0.75, 0.0);

glEnd ();

glFlush ();

}

显示效果非常简陋,就是黑色背景窗口中一个白色的矩形。 OpenGLGL 的每个函数意义不在此文中描述,本文的主要目的是讲述 win32 OpenGL 编程需要的操作。

然后就是将所有的部分串起来了,上述都是代码的片段。 全部源代码见我的放在 Google Code 上的 blog-sample-code 2009-9-27/Win32OpenGLTemplate 目录。取回方式见本文最后的说明。

2. 动画演示:一个旋转的矩形

因为整体的框架使用了 Andre LaMothe T3D Game Console ,所以显示动画非常简单。只不过需要注意的是,这里为了显示效果更好利用了双缓冲,那么上面的设置像素格式一步需要用第二种设置方式。

全部的改动如下:

// 激活创建OpenGL 窗口

void EnableOpenGL ()

{

PIXELFORMATDESCRIPTOR pfd ;

int iFormat ;

ghDC = GetDC ( ghWnd );

ZeroMemory ( & pfd , sizeof ( pfd ) );

pfd . nSize = sizeof ( pfd );

pfd . nVersion = 1; // 版本,一般设为

// 一组表明象素缓冲特性的标志位

pfd . dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER ;

pfd . iPixelType = PFD_TYPE_RGBA ; // 明象素数据类型是RGBA 还是颜色索引;

pfd . cColorBits = 32; // 每个颜色缓冲区中颜色位平面的数目,对颜色索引方式是缓冲区大小

pfd . cDepthBits = 16;

pfd . iLayerType = PFD_MAIN_PLANE ; // 被忽略,为了一致性而包含的

iFormat = ChoosePixelFormat ( ghDC , & pfd ); // 选择一个像素格式

SetPixelFormat ( ghDC , iFormat , & pfd ); // 设置到DC

ghRC = wglCreateContext ( ghDC ); // 创建绘图描述表

wglMakeCurrent ( ghDC , ghRC ); // 使之成为当前绘图描述表

}

//OpenGL 初始化开始

void SceneInit ( int w , int h )

{

glClearColor (0.0f, 0.0f, 0.0f, 0.0f); // 黑色背景

glColor3f (1.0f, 1.0f, 1.0f);

glShadeModel ( GL_FLAT );

glMatrixMode ( GL_PROJECTION );

glLoadIdentity ();

glOrtho (-50.0f, 50.0f, -50.0f, 50.0f, -1.0f, 1.0f);

}

// 这里进行所有的绘图工作

void SceneShow ( GLvoid )

{

// 旋转角度

static float fSpin = 0.0f;

fSpin += 2.0f;

if ( fSpin > 360.0f)

{

fSpin -= 360.0f;

}

glClear ( GL_COLOR_BUFFER_BIT );

glPushMatrix ();

// 旋转矩形的主要函数

glRotatef ( fSpin , 0.0f, 0.0f, 1.0f);

glRectf (-25.0, -25.0, 25.0, 25.0);

glPopMatrix ();

// 交换缓冲区

SwapBuffers ( ghDC );

}

全部源代码见我的放在 Google Code 上的 blog-sample-code 2009-9-28/RotateRect / 目录。取回方式见本文最后的说明。

五、 参考资料

1. OpenGL Reference Manual 》, OpenGL 参考手册

2. OpenGL 编程指南》(《 OpenGL Programming Guide 》), Dave Shreiner Mason Woo Jackie Neider Tom Davis 著,徐波译,机械工业出版社

3. Win32 环境下的 OpenGL 编程 》,郑竞华,《现代电子技术》,空军雷达学院

4. Win32 下使用 OpenGL

5. OpenGL Win32 Tutorial 》,(讲解比较透彻)

6. MSDN ,让人惊讶的是 MSDN 中有比较完整的 OpenGL 参考资料,并且还有很多是讲 X Window OpenGL -_-!

六、 最后说明

本文中所有代码(如果有的话)都能用 Mercurial Google Code 中下载。

文章以博文发表的日期分目录存放,下载地址为:

http://code.google.com/p/jtianling/source/checkout?repo=blog-sample-code

Mercurial 使用方法见《 分布式的,新一代版本控制系统 Mercurial的介绍及简要入门

write by 九天雁翎 (JTianLing) -- blog.csdn.net/vagrxie

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics