三秦IT网在线论坛's Archiver

蓝冰 发表于 2005-12-8 17:44

OpenGL简介

<P><STRONG><FONT face=Tahoma>1</FONT>、OpenGL简介</STRONG><BR>  OpenGL是近几年发展起来的一个性能卓越的三维图形标准,它是在SGI等多家世界闻名的计算机公司的倡导下,以SGI的GL三维图形库为基础制定的一个通用共享的开放式三维图形标准。目前,包括Microsoft、SGI、IBM、DEC、SUN、HP等大公司都采用了OpenGL做为三维图形标准,许多软件厂商也纷纷以OpenGL为基础开发出自己的产品,其中比较著名的产品包括动画制作软件Soft Image和3D Studio MAX、仿真软件Open Inventor、VR软件World Tool Kit、CAM软件ProEngineer、GIS软ARC/INFO等等。值得一提的是,随着Microsoft公司在Windows NT和最新的Windows 95中提供了OpenGL标准及OpenGL三维图形加速卡的推出,OpenGL将在微机中有广泛地应用,同时也为广大用户提供了在微机上使用以前只能在高性能图形工作站上运行的各种软件的机会。<BR><BR><B>2</B><B>、</B><B>OpenGL</B><B>特点及功能</B><BR>  OpenGL实际上是一个开放的三维图形软件包,它独立于窗口系统和操作系统,以它为基础开发的应用程序可以十分方便地在各种平台间移植;OpenGL可以与Visual C++紧密接口,便于实现机械手的有关计算和图形算法,可保证算法的正确性和可靠性;OpenGL使用简便,效率高。它具有七大功能:
<UL type=disc>
<LI class=MsoNormal style="MARGIN-BOTTOM: 12pt; TEXT-ALIGN: left"><B>建模</B><BR>OpenGL图形库除了提供基本的点、线、多边形的绘制函数外,还提供了复杂的三维物体(球、锥、多面体、茶壶等)以及复杂曲线和曲面(例如Bezier、Nurbs等曲线或曲面)绘制函数。
<LI class=MsoNormal style="MARGIN-BOTTOM: 12pt; TEXT-ALIGN: left"><B>变换</B><B><BR></B>OpenGL图形库的变换包括基本变换和投影变换。基本变换有平移、旋转、变比镜像四种变换,投影变换有平行投影(又称正射投影)和透视投影两种变换。其变换方法与机器人运动学中的坐标变换方法完全一致,有利于减少算法的运行时间,提高三维图形的显示速度。
<LI class=MsoNormal style="MARGIN-BOTTOM: 12pt; TEXT-ALIGN: left"><B>颜色模式设置</B><BR>OpenGL颜色模式有两种,即RGBA模式和颜色索引(Color Index)。
<LI class=MsoNormal style="MARGIN-BOTTOM: 12pt; TEXT-ALIGN: left"><B>光照和材质设置</B><BR>OpenGL光有辐射光(Emitted Light)、环境光(Ambient Light)、漫反射光(Diffuse Light)和镜面光(Specular Light)。材质是用光反射率来表示。场景(Scene)中物体最终反映到人眼的颜色是光的红绿蓝分量与材质红绿蓝分量的反射率相乘后形成的颜色。
<LI class=MsoNormal style="MARGIN-BOTTOM: 12pt; TEXT-ALIGN: left"><B>纹理映射</B>(Texture Mapping)<BR>利用OpenGL纹理映射功能可以十分逼真地表达物体表面细节。
<LI class=MsoNormal style="MARGIN-BOTTOM: 12pt; TEXT-ALIGN: left"><B>位图显示和图象增强</B><BR>图象功能除了基本的拷贝和像素读写外,还提供融合(Blending)、反走样(Antialiasing)和雾(fog)的特殊图象效果处理。以上三条可是被仿真物更具真实感,增强图形显示的效果。
<LI class=MsoNormal style="TEXT-ALIGN: left"><B>双缓存动画</B>(Double Buffering)<BR>双缓存即前台缓存和后台缓存,简而言之,后台缓存计算场景、生成画面,前台缓存显示后台缓存已画好的画面。此外,利用OpenGL还能实现深度暗示(Depth Cue)、运动模糊(Motion Blur)等特殊效果。从而实现了消隐算法。 </LI></UL>
<P><B>3</B><B>、</B><B>OpenGL for Windows 95</B><B>图形库</B><BR>  OpenGL图形库一共有100多个函数。其中核心函数有115个,它们是最基本的函数,其前缀是gl,OpenGL实用库(OpenGL utility library,GLU)的函数功能更高一些,如绘制复杂的曲线曲面、高级坐标变换、多边形分割等,共有43个,前缀为glu;OpenGL辅助库(OpenGL auxiliarylibrary,GLAUX)的函数是一些特殊的函数,包括简单的窗口管理、输入事件处理、某些复杂三维物体绘制等函数,共有31个,前缀为aux。<BR>  此外,还有六个WGL函数非常重要,专门用于OpenGL和Windows 95窗口系统的联接,其前缀为wgl,主要用于创建和选择图形操作描述表(renderingcontexts)以及在窗口内任一位置显示字符位图。这些功能是Windows 95对OpenGL的唯一补充。另外,还有五个Win32函数用来处理像素格式(pixel formats)和双缓存。由于它们是对Win32系统的扩展,因此不能应用在其它OpenGL平台上。<BR><BR><B>4</B><B>、</B><B>OpenGL for Windows 95</B><B>程序设计</B><BR>  OpenGL for Windows 95的设计与OpenGL for UNIX的程序设计有一点小区别,关键就在于如何将OpenGL与不同的操作系统下的窗口系统联系起来。如果调用OpenGL辅助库窗口管理函数,则不用考虑这些问题。下面简要介绍在Windows 95下OpenGL的程序设计关键。<BR><BR>  <B>4.1 </B><B>图形操作描述</B><BR>  在Windows 95下窗口程序必须首先处理设备描述表(Device Contexts,DC),DC包括许多如何在窗口上显示图形的信息,既指定画笔和刷子的颜色,设置绘图模式、调色板、映射模式以及其它图形属性。同样,OpenGL for Windows95的程序也必须使用DC,这与其它Windows 95程序类似。但是,OpenGL for Windows 95必须处理特殊的DC图形操作描述表,这是DC中专为OpenGL使用的一种。一个OpenGL应用图形操作描述表内有OpenGL与Windows 95窗口系统相关的各种信息。一个OpenGL应用首先必须创建一个图形操作描述表,然后再启动它,最后在所定义的窗口内按常规方式调用OpenGL函数绘制图形。<BR>  一个图形操作描述表不同于其它DC,它们调用每个GDI函数都需要一个句柄,而图形操作描述表方式下只需一个句柄就可以任意调用OpenGL函数。也就是说,只要当前启用了某个图形操作描述表,那么在未删除图形操作描述表之前可以调用任何OpenGL函数,进行各种操作。<BR><BR>  <B>4.2 </B><B>像素格式</B><BR>  在创建一个图形操作表之前,首先必须设置像素格式。像素格式含有设备绘图界面的属性,这些属性包括绘图界面是用RGBA模式还是颜色表模式,像素缓存是用单缓存还是双缓存,以及颜色位数、深度缓存和模板缓存所用的位数,还有其它一些属性信息。<BR><BR>  <B>4.3 </B><B>像素格式结构</B><BR>  每个OpenGL显示设备都支持一种指定的像素格式。一般用一个名为PIXELFORMATDESCRIPTOR的结构来表示某个特殊的像素格式,这个结构包含26个属性信息。Win32定义PIXELFORMATDESCRIPTOR如下所示:<BR><BR>  typedef struct tagPIXELFORMATDESCRIPTOR<BR>  {<BR>    WORD nSize;<BR>    WORD nVersion;<BR>    DWORD dwFlags;<BR>    BYTE iPixelType;<BR>    BYTE cColorBits;<BR>    BYTE cRedBits;<BR>    BYTE cRedShift;<BR>    BYTE cGreenBits;<BR>    BYTE cGreenShift;<BR>    BYTE cBlueBits;<BR>    BYTE cBlueShift;<BR>    BYTE cAlphaBits;<BR>    BYTE cAlphaShift;<BR>    BYTE cAccumBits;<BR>    BYTE cAccumRedBits;<BR>    BYTE cAccumGreenBits;<BR>    BYTE cAccumBlueBits;<BR>    BYTE cAccumAlphaBits;<BR>    BYTE cDepthBits;<BR>    BYTE cStencilBits;<BR>    BYTE cAuxBuffers;<BR>    BYTE iLayerType;<BR>    BYTE bReserved;<BR>    DWORD dwLayerMask;<BR>    DWORD dwVisibleMask;<BR>    DWORD dwDamageMask;<BR>  } PIXELFORMATDESCRIPTOR;<BR><BR>  <B>4.4 </B><B>初始化</B><B>PIXELFORMATDESCRIPTOR</B><B>结构</B><BR>  PIXELFORMATDESCRIPTOR中每个变量值的具体含义和设置可以参考有关资料,下面举出一个PIXELFORMATDESCRIPTOR初始化例子来简要说明相关变量的意义。定义PIXELFORMATDESCRIPTOR结构的pfd如下:<BR><BR>  PIXELFORMATDESCRIPTOR pfd = {<BR>    sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd<BR>    1,<BR>    PFD_DRAW_TO_WINDOW |      // support window<BR>    PFD_SUPPORT_OPENGL |      // support OpenGL<BR>    PFD_DOUBLEBUFFER,        // double buffered<BR>    PFD_TYPE_RGBA,         // RGBA type<BR>    24,               // 24-bit color depth<BR>    0, 0, 0, 0, 0, 0,        // color bits ignored<BR>    0,               // no alpha buffer<BR>    0,               // shift bit ignored<BR>    0,               // no accumulation buff<BR>    0, 0, 0, 0,           // accum bits ignored<BR>    32,               // 32-bit z-buffer<BR>    0,               // no stencil buffer<BR>    0,               // no auxiliary buffer<BR>    PFD_MAIN_PLANE,         // main layer<BR>    0,               // reserved<BR>    0, 0, 0             // layer masks ignored<BR>  };<BR><BR>  在这个结构里,前两个变量的含义十分明显。第三个变量dwFlags的值是PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER,表明应用程序使用OpenGL函数来绘制窗口,第四个表明当前采用RGBA颜色模式,第五个采用24位真彩色,既1.67千万种颜色,如果是256色系统则自动实现颜色抖动;因为没有使用alpha缓存和累计缓存,所以从变量cAlphaBits到cAccumAlphaBits都设置为0;深度缓存设置为32位,这个缓存能解决三维场景的消隐问题;变量cAuxBuffers设置为0,在Windows 95下不支持辅助缓存;Windows 95下针对OpenGL变量ilayerType只能设置为PFD_MAIN_PLANE,但在其它平台也许支持PFD_MAIN_PLANE或PFD_MAIN_UNDERLAYPLANE;接下来bReserved变量只能设为0,而最后三个变量Windows 95都不支持,故全设置为0。<BR><BR>  <B>4.5 </B><B>设置像素结构</B><BR>  当初始化PIXELFORMATDESCRIPTOR结构后,就要设置像素格式。下面举例说明如何设置像素格式。<BR><BR>  CClientDC clientDC(this);<BR>  int PixelFormat = ChoosePixelFormat(clientDC.m_hDC,&amp;pfd);<BR>  BOOL result=SetPixelFormat(clientDC.m_hDC,PixelFormat,&amp;pfd);<BR><BR>  第一行语句说明得到一个应用窗口客户区的设置描述表。第一行调用ChoosePixelFormat()选择一个像素格式,并将像素格式索引号返回给pixelFormat变量;函数中第一个参数是选择像素格式的设备描述表的句柄,第二个参数是PIXELFORMATDESCRIPTOR结构的地址。如果调用失败则返回0;否则返回像素格式索引号。第三行调用SetPixelFormat()设置像素格式,三个参数分别是设备描述表的句柄、像素格式索引号和PIXELFORMATDESCRIPTOR结构的地址。如果调用成功则返回TRUE,否则返回FALSE。<BR><BR>  <B>4.6 </B><B>创建图形操作描述表</B><BR>  正如前所述,必须创建图形操作描述表并启用它后,才能调用OpenGL函数在窗口内进行各种图形操作。一般来说,利用MFC中增补的管理图形操作描述表方法来编程比较方便。即在视类(CView)的消息OnCreat()中创建图形操作描述表。</P>
<P>/**************************<BR> * Includes<BR> *<BR> **************************/</P>
<P>#include &lt;windows.h&gt;<BR>#include &lt;gl/gl.h&gt;</P>
<P><BR>/**************************<BR> * Function Declarations<BR> *<BR> **************************/</P>
<P>LRESULT CALLBACK WndProc (HWND hWnd, UINT message,<BR>WPARAM wParam, LPARAM lParam);<BR>void EnableOpenGL (HWND hWnd, HDC *hDC, HGLRC *hRC);<BR>void DisableOpenGL (HWND hWnd, HDC hDC, HGLRC hRC);</P>
<P><BR>/**************************<BR> * WinMain<BR> *<BR> **************************/</P>
<P>int WINAPI <BR>WinMain (HINSTANCE hInstance,<BR>         HINSTANCE hPrevInstance,<BR>         LPSTR lpCmdLine,<BR>         int iCmdShow)<BR>{<BR>    WNDCLASS wc;<BR>    HWND hWnd;<BR>    HDC hDC;<BR>    HGLRC hRC;        <BR>    MSG msg;<BR>    BOOL bQuit = FALSE;<BR>    float theta = 0.0f;</P>
<P>    /* register window class */<BR>    wc.style = CS_OWNDC;<BR>    wc.lpfnWndProc = WndProc;<BR>    wc.cbClsExtra = 0;<BR>    wc.cbWndExtra = 0;<BR>    wc.hInstance = hInstance;<BR>    wc.hIcon = LoadIcon (NULL, IDI_APPLICATION);<BR>    wc.hCursor = LoadCursor (NULL, IDC_ARROW);<BR>    wc.hbrBackground = (HBRUSH) GetStockObject (BLACK_BRUSH);<BR>    wc.lpszMenuName = NULL;<BR>    wc.lpszClassName = "GLSample";<BR>    RegisterClass (&amp;wc);</P>
<P>    /* create main window */<BR>    hWnd = CreateWindow (<BR>      "GLSample", "OpenGL Sample", <BR>      WS_CAPTION | WS_POPUPWINDOW | WS_VISIBLE,<BR>      0, 0, 256, 256,<BR>      NULL, NULL, hInstance, NULL);</P>
<P>    /* enable OpenGL for the window */<BR>    EnableOpenGL (hWnd, &amp;hDC, &amp;hRC);</P>
<P>    /* program main loop */<BR>    while (!bQuit)<BR>    {<BR>        /* check for messages */<BR>        if (PeekMessage (&amp;msg, NULL, 0, 0, PM_REMOVE))<BR>        {<BR>            /* handle or dispatch messages */<BR>            if (msg.message == WM_QUIT)<BR>            {<BR>                bQuit = TRUE;<BR>            }<BR>            else<BR>            {<BR>                TranslateMessage (&amp;msg);<BR>                DispatchMessage (&amp;msg);<BR>            }<BR>        }<BR>        else<BR>        {<BR>            /* OpenGL animation code goes here */</P>
<P>            glClearColor (0.0f, 0.0f, 0.0f, 0.0f);<BR>            glClear (GL_COLOR_BUFFER_BIT);</P>
<P>            glPushMatrix ();<BR>            glRotatef (theta, 0.0f, 0.0f, 1.0f);<BR>            glBegin (GL_TRIANGLES);<BR>            glColor3f (1.0f, 0.0f, 0.0f);   glVertex2f (0.0f, 1.0f);<BR>            glColor3f (0.0f, 1.0f, 0.0f);   glVertex2f (0.87f, -0.5f);<BR>            glColor3f (0.0f, 0.0f, 1.0f);   glVertex2f (-0.87f, -0.5f);<BR>            glEnd ();<BR>            glPopMatrix ();</P>
<P>            SwapBuffers (hDC);</P>
<P>            theta += 1.0f;<BR>            Sleep (1);<BR>        }<BR>    }</P>
<P>    /* shutdown OpenGL */<BR>    DisableOpenGL (hWnd, hDC, hRC);</P>
<P>    /* destroy the window explicitly */<BR>    DestroyWindow (hWnd);</P>
<P>    return msg.wParam;<BR>}</P>
<P><BR>/********************<BR> * Window Procedure<BR> *<BR> ********************/</P>
<P>LRESULT CALLBACK <BR>WndProc (HWND hWnd, UINT message,<BR>         WPARAM wParam, LPARAM lParam)<BR>{</P>
<P>    switch (message)<BR>    {<BR>    case WM_CREATE:<BR>        return 0;<BR>    case WM_CLOSE:<BR>        PostQuitMessage (0);<BR>        return 0;</P>
<P>    case WM_DESTROY:<BR>        return 0;</P>
<P>    case WM_KEYDOWN:<BR>        switch (wParam)<BR>        {<BR>        case VK_ESCAPE:<BR>            PostQuitMessage(0);<BR>            return 0;<BR>        }<BR>        return 0;</P>
<P>    default:<BR>        return DefWindowProc (hWnd, message, wParam, lParam);<BR>    }<BR>}</P>
<P><BR>/*******************<BR> * Enable OpenGL<BR> *<BR> *******************/</P>
<P>void<BR>EnableOpenGL (HWND hWnd, HDC *hDC, HGLRC *hRC)<BR>{<BR>    PIXELFORMATDESCRIPTOR pfd;<BR>    int iFormat;</P>
<P>    /* get the device context (DC) */<BR>    *hDC = GetDC (hWnd);</P>
<P>    /* set the pixel format for the DC */<BR>    ZeroMemory (&amp;pfd, sizeof (pfd));<BR>    pfd.nSize = sizeof (pfd);<BR>    pfd.nVersion = 1;<BR>    pfd.dwFlags = PFD_DRAW_TO_WINDOW | <BR>      PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;<BR>    pfd.iPixelType = PFD_TYPE_RGBA;<BR>    pfd.cColorBits = 24;<BR>    pfd.cDepthBits = 16;<BR>    pfd.iLayerType = PFD_MAIN_PLANE;<BR>    iFormat = ChoosePixelFormat (*hDC, &amp;pfd);<BR>    SetPixelFormat (*hDC, iFormat, &amp;pfd);</P>
<P>    /* create and enable the render context (RC) */<BR>    *hRC = wglCreateContext( *hDC );<BR>    wglMakeCurrent( *hDC, *hRC );</P>
<P>}</P>
<P><BR>/******************<BR> * Disable OpenGL<BR> *<BR> ******************/</P>
<P>void<BR>DisableOpenGL (HWND hWnd, HDC hDC, HGLRC hRC)<BR>{<BR>    wglMakeCurrent (NULL, NULL);<BR>    wglDeleteContext (hRC);<BR>    ReleaseDC (hWnd, hDC);<BR>}</P>

页: [1]



Powered by Discuz! Archiver 7.0.0  © 2001-2009 Comsenz Inc.