OpenGL DC RC关系

转载 2015年11月19日 19:12:33

1.Windows操作系统对OpenGL的支持 

    具有Windows编程经验的人都知道,在Windows下用GDI作图必须通过设备上下文(DeviceContext简写DC)调用相应的函数;用OpenGL作图也是类似,OpenGL函数是通过"渲染上下文"(RenderingContext简写RC)完成三维图形的绘制。Windows下的窗口和设备上下文支持"位图格式"(PIXELFORMAT)属性,和RC有着位图结构上的一致。只要在创建RC时与一个DC建立联系(RC也只能通过已经建立了位图格式的DC来创建),OpenGL的函数就可以通过RC对应的DC画到相应的显示设备上。创建RC的过程如下:

  • 获取一个DC
  • 选择并且设置DC的像素格式
  • 通过API:wglCreateContext(DC)创建一个RC
  • 设置当前的RC,通过API:wglMakeCurrent(RC, DC)来设置.

实现释放或者选择其它RC:  

  • 调用API:wglMakeCurrent(NULL, NULL)使DC不再有RC。
  • 调用API:wglMakeCurrent(AnotherRC, DC)选择其他RC为当前RC,一般情况下,我们都是一个RC对应一个DC,当然,在某些场合里面是可以有多个RC。
  • 调用API:wglDeleteContent(RC) 直接删除,这个方法比较直截了当。

        这里还有以下需要注意的方面:


     1.一个线程只能拥有一个渲染上下文(RC),也就是说,用户如果在一个线程内对不同设备作图,只能通过更换与RC对应的DC来完成,而RC在线程中保持不变。(当然,删除旧的RC后再创建新的是可以的)与此对应,一个RC也只能属于一个线程,不能被不同线程同时共享。 

    2.设定DC位图格式等于设定了相应的窗口的位图格式,并且DC和窗口的位图格式一旦确定就不能再改变。这一点只能期望以后的Windows版本改进了。 

    3.一个RC虽然可以更换DC,在任何时刻只能利用一个DC(这个DC称为RC的当前DC),但由于一个窗口可以让多个DC作图从而可以让多个线程利用多个RC在该窗口上执行OpenGL操作。 

    4.现在的Windows下的OpenGL版本对OpenGL和GDI在同一个DC上作图有一定的限制。当使用双缓存用OpenGL产生动画时,不能使用GDI函数向该DC作图。 

    5.不建议用ANSIC在Windows下编写OpenGL程序。这样的程序虽然具有跨平台的可移植性(比如很多SGI的例子程序),但是它们不能利用 Windows操作系统的很多特性,实用价值不大。 

2.用VC来编写OpenGL程序 

经过上面的分析,用VC来调用OpenGL作图的方法就很显然了。步骤如下: 

   1.先设置显示设备DC的位图格式(PIXELFORMAT)属性。这通过填充一个PIXELFORMATDESCRIPTOR的结构来完成(关于PIXELFORMATDESCRIPTOR中 各项数据的意义,请参照VC的帮助信息),该结构决定了OpenGL作图的物理设备的属性,比如该结构中的数据项dwFlags中PFD_DOUBLEBUFFER位如果没有设置(置1),通过该设备的DC上作图的OpenGL命令就不可能使用双缓冲来做动画。有一些位图格式(PIXELFORMAT)是DC支持的,而有一些DC就不支持了。所以程序必须先用ChoosePixelFormat来选择DC所支持的与指定位图格式最接近的位图格式,然后用SetPixelFormat设置DC的位图格式。 

   2.利用刚才的设备DC建立渲染上下文RC(wglCreateContext),使得RC与DC建立联系(wglMakeCurrent)。 

   3.调用OpenGL函数作图。由于线程与RC一一对应,OpenGL函数的参数中都不指明本线程RC的句柄(handle) 

   4.作图完毕以后,先通过置当前线程的RC为NULL(::wglMakeCurrent(NULL,NULL);),断开当前线程和该渲染上下文的联系,由此断开与DC的联系。此时RC句柄的有效性在微软自己的文档中也没有讲清楚,所以在后面删除RC的时候要先判断以下RC句柄的有效性(f(m_hrc)::wglDeleteContext(m_hrc);)。再根据情况释放(ReleaseDC)或者删除(DeleteDC)DC 。

3.一些说明 

   1.一旦设定了一个DC的位图格式,该DC所联系的窗口的位图格式随之设定。该窗口若含有子窗口或者有兄弟窗口,这些兄弟/子窗口的位图格式没有设成与对应RC一致的格式,OpenGL在它们上面作图就容易出错。故而OpenGL作图的窗口必须具有WS_CLIPCHILDREN和WS_CLIPSIBLINGS风格,程序中在主框窗的构造函数中用LoadFrame(IDR_MAINFRAME,WS_OVERLAPPEDWINDOW|WS_CLIPCHILDREN|WS_CLIPSIBLINGS,NULL,NULL);指定了主窗口的风格。 

   2.在ANSIC的OpenGL编程中,由auxReshapeFunc定义设置OpenGL视口大小和作图尺寸的回调函数。在MFC中应该由WM_SIZ消息的处理函数来完成。在ANSIC的OpenGL编程中,由EauxMainLoop定义作图的回调函数。在MFC中应该由WM_PAINT消息的处理函数来处理。相应的,由OpenGL定义的键盘、鼠标处理函数都应该由相应的Windows处理函数来响应。 

   3.OpenGL自己有刷新背景的函数glClear,故而应禁止Windows刷新窗口背景。否则,当窗口需要重画时,Windows会自动先发送WM_ERASEBKGND ,而缺省的处理函数使用白色的背景刷。当OpenGL使用的背景颜色不是白色时,作图时有一帧白色的闪烁。这种现象在做动画时特别明显。程序中只需要在WM_ERASEBKGND的消息处理函数中禁止父窗口类的消息处理,简单的返回一个TRUE即可。 

   4.由于OpenGL的跨平台性,它必须用操作系统的调色板。所以如果GL_INDEX_MODE作图时,必须用VC自己定义调色板。不过一般情况下,用GL_RGBA_MODE模式比较方便,很少用到GL_INDEX_MODE模式。 

   5.在OpenGL作图期间,RC对应的DC不能删除或者释放。 

   6.由于OpenGL作图时需要长时间占用DC,所以最好把作图窗口类设成CS_OWNDC。MFC缺省的窗口类风格中没有设这一属性,程序中在主窗口C++ 类的PreCreateWindow方法中自己注册了一个窗口类,除了设定了CS_OWNDC属性以外,还设定了CS_HREDRAW、CS_VREDRAW和CS_SAVEBITS。设定CS_HREDRAW、CS_VREDRAW是为了让窗口缩放时产生WM_PAINT消息,修正OpenGL视口和作图尺寸;由于OpenGL作图需要很多计算,设定CS_SAVEBITS是为了在OpenGL窗口被遮盖后显现出来时,不产生WM_PAINT消息,用内存存储的图象来填充,从而用空间消耗换取计算时间。 

   7.本程序中没有对OpenGL函数的出错情况作出处理。OpenGL出错后返回错误码,不会抛出异常;而且在某一个函数出错以后,后继函数也一般不会出现异常,只是返回错误码,一不小心就可能忽略某些错误。而对每一个OpenGL函数都做出错与否的判断比较麻烦,所以编程序时对OpenGL的函数应当非常小心。

4.像素格式


  像素格式是OpenGL窗口的重要属性,它包括是否使用双缓冲,颜色位数和类型以及深度位数等。像素格式可由Windows系统定义的所谓像素格式描述子结构来定义(PIXELFORMATDESCRIPTOR),该结构定义在windows.h中。
  在该结构中包含有26个属性信息,其形式为:
  typedef struct tagPIXELFORMATDESCRIPTOR
  {
  WORD nSize;
  WORD nVersion;
  DWORD dwFlags;         //如果使用了双缓冲,则需要在绘制代码结束后使用SwapBuffers(HDC hDc)换页
  BYTE iPixelType;
  BYTE cColorBits;
  BYTE cRedBits;
  BYTE cRedShift;
  BYTE cGreenBits;
  BYTE cGreenShift;
  BYTE cBlueBits;
  BYTE cBlueShift;
  BYTE cAlphaBits;
  BYTE cAlphaShift;
  BYTE cAccumBits;
  BYTE cAccumRedBits;
  BYTE cAccumGreenBits;
  BYTE cAccumBlueBits;
  BYTE cAccumAlphaBits;
  BYTE cDepthBits;
  BYTE cStencilBits;
  BYTE cAuxBuffers;
  BYTE iLayerType;
  BYTE bReserved;
  DWORD dwLayerMask;
  DWORD dwVisibleMask;
  DWORD dwDamageMask;
  } PIXELFORMATDESCRIPTOR;
  各变量的含义如下:
  nSize:该结构所占内存空间。
  nVersion:版本号,当前为1。
  dwFlags:指定像素格式属性,可选参量如表1.1所示。

   像素格式属性
  标识符 解释
  PFD_DRAW_TO_BITMAP 支持内存中绘制位图
  PFD_DRAW_TO_WINDOW 支持屏幕绘图
  PFD_DOUBLEBUFFER 支持双缓冲
  PFD_CENERIC_FORMAT 指定选择GDI支持的像素格式
  PFD_NEED_PALETTE 指定需要逻辑调色板
  PFD_NEED_SYSTEM_PALETTE 指定需要硬件调色板
  PFD_STEREO NT不支持
  PFD_SUPPORT_OPENGL 支持OpenGL
  PFD_SUPPORT_GDI 支持GDI,此时不可使用PFD_DOUBLEBUFFER
  iPixelType:像素颜色模式,可选项为PFD_TYPE_RGBA或PFD_TYPE_INDEX,分别对应于RGBA模式和颜色索引模式。
  cColorBits:指定颜色的位数。
  cRedBits:采用RGBA模式时,红色组分占用位数。
  cRedShift:采用RGBA模式时,红色组分偏移量。
  cGreenBits:采用RGBA模式时,绿色组分占用位数。
  cGreenShift:采用RGBA模式时,绿色组分偏移量。
  cBlueBits:采用RGBA模式时,蓝色组分占用位数。
  cBlueShift: 采用RGBA模式时,蓝色组分偏移量。
  cAlphaBits:采用RGBA模式时,Alpha组分占用位数。
  cAlphaShift:采用RGBA模式时,Alpha组分偏移量。
  cAccumBits:指定累积缓冲区表示一个像素所用位数。
  cAccumRedBits:指定累积缓冲区表示红色组分占用位数。
  cAccumGreenBits:指定累积缓冲区表示绿色组分占用位数。
  cAccumBlueBits:指定累积缓冲区表示蓝色组分占用位数。
  cAccumAlphaBits:指定累积缓冲区表示Alpha组分占用位数。
  cDepthBits:指定深度缓冲区表示一个像素所用位数。
  cStencilBits:指定模板缓冲区表示一个像素所用位数。
  cAuxBuffers:指定辅助缓冲区,Windows9x、NT不支持。
  iLayerType:Windows9x、NT下只能是PFD_MAIN_PLANE。
  bReserved:=0。
  dwLayerMask:指定覆盖层的屏蔽,Windows9x、NT不支持。
  dwVisibleMask:Windows9x、NT不支持。
  dwDamageMask:Windows9x、NT不支持。
  Windows提供了四个像素格式管理函数,分别介绍如下:
  (1) int ChoosePixelFormat(HDC hdc,
  PIXELFORMATDESCRIPTOR *ppdf)
  该函数比较传过来的像素格式描述和OpenGL支持的像素格式,返回一个最佳匹配的像素格式索引。该索引值可传给SetPixelFormat为DC设置像素格式。返回值为0表示失败。
  在比较像素格式时,匹配优先级顺序为像素格式描述子结构中的下述各域:
  dwFlags->cColorBits->cAlphaBits->cAccumBits
  ->cDepthBits->cStencilBits->cAuxBuffers->iLayerType
  硬件支持的像素格式优先。
  (2) int DescribePixelFormat(HDC hdc, int iPixelFormat, UINT nBytes,
  LPPIXELFORMATDESCRIPTOR *ppfd)
  该函数用格式索引iPixelFormat说明的像素格式来填写由ppfd所指向的像素格式描述子结构,利用该函数可以枚举像素格式。
  (3) int GetPixelFormat(HDC hdc)
  该函数用于获取hdc的格式索引。
  (4) BOOL SetPixelFormat(HDC hdc, int iPixelFormat,
  LPPIXELFORMATDESCRIPTOR *ppfd)
  该函数用格式索引iPixelFormat来设置hdc的像素格式。在使用该函数之前应该调用ChoosePixelFormat来获取像素格式索引。另外,OpenGL窗口风格必须包含WS_CLIPCHILDREN和WS_CLIPSIBLINGS类型,否则设置失败。
  应该注意的是ChoosePixelFormat函数并不一定返回一个最佳的像素格式值,可以利用DescribePixelFormat来枚举系统所支持的所有像素格式。OpenGL的通常支持24种不同的像素格式,如果系统安装了OpenGL硬件加速器,它可能会支持其它的像素格式

0

相关文章推荐

基于OpenGL三维软件开发

实验原理: OpenGL在MFC下编程原理 ---- Windows操作系统对OpenGL的支持 在Windows下用GDI作图必须通过设备上下文(DeviceContext简写DC)调用相应的...

OpenGL系列教程之十二:OpenGL Windows图形界面应用程序

这篇文章是关于使用MVC(Model-View-Controller,模型-视图-控制)框架在windows平台下创建OpenGL图形界面应用程序。MVC框架在GUI(Graphic User Int...

Windows下DC、openGL、 RC关系

1.Windows操作系统对OpenGL的支持      具有Windows编程经验的人都知道,在Windows下用GDI作图必须通过设备上下文(DeviceContext简写DC)调用相应的函...

OpenGL DC RC关系

1.Windows操作系统对OpenGL的支持      具有Windows编程经验的人都知道,在Windows下用GDI作图必须通过设备上下文(DeviceContext简写DC)调用相应的函...
  • kkk328
  • kkk328
  • 2011年12月21日 19:39
  • 3503

RC与DC的介绍与使用

OpenGL的绘图方式与Windows一般的绘图方式是不同的,主要区别如下: 1、Windows采用的是GDI在设备描述表DC上进行绘图。 2、OpenGL采用的是OpenGL相关的函数在渲染描述...

Opengl RC(Render context,渲染下下文)与像素格式(转)

Opengl RC(Render context,渲染下下文)与像素格式(转)   2010-01-18 09:26:26|  分类: OpenGL |举报 |字号 订阅 ...
  • lcjwxd
  • lcjwxd
  • 2014年04月07日 15:44
  • 944

OpenGL(2)——像素格式和RC管理

1.写在前面 由于OpenGL被设计成独立于硬件,独立于窗口系统,因此OpenGL的用户不需要考虑如何对计算机图形设备中的显示面(display surfaces)进行初始化和管理,这些工作交由操作...
  • cuglxw
  • cuglxw
  • 2015年03月31日 08:45
  • 317

resource.h文件和项目的.rc资源的关系

resource.h文件和项目的.rc资源的关系 resource.h就是.rc文件的头文件 .rc文件里的常量全在resource.h定义 一般情况下不用你去写和修改 vc会帮你写和改 但是如果你想...

容器中rc.local,login shell, systemctl微妙关系

背景:假设有这么一个需求: - 容器中能使用systemctl操作和查看服务状态 - 容器启动时需获取运行容器时传入环境变量实践出真理我们先写一个获取环境变量的简单shell脚本# file na...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:OpenGL DC RC关系
举报原因:
原因补充:

(最多只允许输入30个字)