opengl像素格式和RC管理

2024-05-02 22:38
文章标签 管理 格式 像素 opengl rc

本文主要是介绍opengl像素格式和RC管理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

http://hi.baidu.com/dem_simulation/item/7e45bc4086bb59a461d7b9c6

1.写在前面

由于OpenGL被设计成独立于硬件,独立于窗口系统,因此OpenGL的用户不需要考虑如何对计算机图形设备中的显示面(display surfaces)进行初始化和管理,这些工作交由操作系统帮助完成。虽然如此,任何想要使用好OpenGL的开发人员,都应该理解在Windows平台下(如果你的程序运行于Windows平台下的话),一副三维图形在显示面上呈现的具体原理。正所谓“连路都不会走,跑是必然要摔跟头的”,所以沉下心来,一一搬开你路上的石头。

这里主要讨论像素格式和渲染设备描述表(RC)的管理原理。能成功管理这些对象,就建立了硬件与图形接口之间的桥梁。在Windows平台下提供有两种机制来完成硬件与OpenGL之间的接连——像素格式操作API和WGL API。其中后者用于管理RC。好,下面一一介绍。

2.软件渲染模式与硬件加速模式

在Windows平台上,OpenGL驱动可能有三种模式:纯软件、MCD和ICD。

   ***   纯软件模式是由微软提供一个OpenGL的软件实现,所有渲染操作均由CPU完成,速度很慢。如果安装系统时使用Windows自带的显卡驱动程序,那么OpenGL程序就会运行在软件模式下。而且由于微软有自己的Direct3D,所以对OpenGL的支持很消极,它的OpenGL纯软件实现只支持OpenGL1.1,而目前OpenGL的最新版本为 1.4。

   ***   MCD(Mini Client Driver)是早期微软在Windows NT上支持OpenGL时,为了简化驱动开发时使用的一个模型。MCD虽然可以简化驱动开发,但是功能限制太大,现在市面上的3D加速卡均支持硬件变换和光照,MCD却不能利用这一特性,看上去MCD已经没有存在的价值。

   ***   ICD(Installable Client Driver)是一个完整的OpenGL驱动模型,比MCD复杂得多。硬件厂商要实现完整的OpenGL渲染管线,如变换、光照、光栅化等,因此只要硬件支持,ICD可以硬件加速整个OpenGL渲染管线。我们通常说的OpenGL硬件加速就是指的通过ICD模型获得的硬件加速,而现在硬件厂商提供的OpenGL驱动程序也都是依照ICD模型开发的。(主要硬件厂商的ICD已经可以支持OpenGL的最新版1.4)

Windows怎么实现OpenGL硬件加速呢?OpenGL32.dll是微软的OpenGL 1.1纯软件实现,我们的程序都要动态链接到这个dll。如果安装3D芯片厂商的驱动程序,会将一个不同名字的dll放到Windows系统目录下,比如在Windows 2000下安装nVIDIA GeForce2 MX的驱动程序,会在系统目录下放置一个nvoglnt.dll(这就是nVIDIA的OpenGL驱动),并在注册表中登记nvoglnt.dll,让 Windows知道硬件加速OpenGL驱动的名字,以后运行OpenGL程序,OpenGL32.dll就会把OpenGL调用直接转到 nvoglnt.dll进行处理。nvoglnt.dll则将OpenGL和 WGL指令打包发送给3D芯片厂商的驱动程序,这些驱动程序与支持绘图渲染的基础函数库联接,这样以来,OpenGL程序可以最大限度地利用显卡对OpenGL渲染的支持,从而极大地提高渲染速度。

在Windows平台上,一个OpenGL程序是否使用硬件加速由三个因素决定,这三个因素缺一不可,否则程序都会运行于纯软件模式: 
   ***   是否有一块3D加速卡 
   ***   是否安装了显卡厂商提供的最新的驱动程序,Windows自带的显卡驱动程序并不会提供OpenGL硬件加速能力 
‍ ***   指定的像素格式是否被显卡硬件所支持

3.像素格式管理

图形的整体显示由单个的像素点所组成。每个像素在内存中都分配了一定字节数的内存空间。用于保存所有像素信息的内存就是缓存。缓存可以有多种形式,分别用于保存不同的信息,比如深度缓存保存每个像素的深度值等。计算机屏幕上所有像素的字节的某一位组成的矩阵是一个位面(bitplane),系统中所有的缓存统称为帧缓存。

帧缓存有四种,一种是颜色缓存,其内包含了该像素的颜色信息,数据可以是颜色索引值(color index),也可以是颜色的RGBA值;一种是深度缓存,其内包含了每个像素的深度信息,如果两个像素占用同一个位置,那么较低深度值的像素用覆盖较高深度值的像素;一种是模板缓存,利用它可以限制屏幕上绘图的区域;最后一种是累积缓存,它主要用于保存各像素的RGBA值,用于反走样等复杂的效果。

在Windows对OpenGL的软件实现中,包含了这些缓存区的设置。软件实现支持单缓存和双缓存模式,支持深度缓存、模板缓存和积累缓存,但层级缓存还不支持。为了有效地利用这些缓存,必须设置好像素格式。每个OpenGL程序窗口都有一套像素格式,下面讨论结构、功能和使用方法。

3.1像素格式结构体

PIXELFORMATDESCRIPTOR是像素格式结构体,用以描述Windows平台下的像素格式的各类属性。某些硬件厂商可能会为加强OpenGL的渲染能力而支持某此软件加速并不支持的像素格式属性。结构体定义如下:

typedef struct tagPIXELFORMATDESCRIPTOR
{
WORD nSize;           //定义数据结构体的大小,可以这样给值:pfd.nsize = sizeof(PIXELFORMATDESCRIPTOR)
WORD nVersion;                            //直接设置为1
DWORD dwFlags;                            //一系列位标识符,可以相互取或联接,具体有哪些功能标识符,查看MSDN
BYTE iPixelType;      //定义像素数据的类型,是索引值(‍PFD_TYPE_COLORINDEX)还是RGBA值(PFD_TYPE_RGBA)
BYTE cColorBits;      //每个颜色缓存中的位面数,如果是RGBA模式,除去alpha位面后的位面数就是该值
BYTE cRedBits;        //颜色缓存中,红色信息所占用的位面数
BYTE cRedShift;       //红色位面数在缓存区中的移位数,即移多少位可以找到红色的RGB信息   
BYTE cGreenBits;      //颜色缓存中,绿色信息所占用的位面数
BYTE cGreenShift;     //绿色位面数在缓存区中的移位数,即移多少位可以找到绿色的RGB信息
BYTE cBlueBits;       //颜色缓存中,蓝色信息所占用的位面数
BYTE cBlueShift;      //蓝色位面数在缓存区中的移位数,即移多少位可以找到蓝色的RGB信息
BYTE cAlphaBits;      //软件加速不支持, 颜色缓存中,alpha信息的位面数
BYTE cAlphaShift;     //软件加速不支持, 颜色缓存中,alpha信息移位数
BYTE cAccumBits;       //积累缓存中的总位面数
BYTE cAccumRedBits;    //积累缓存中的红色信息位面数
BYTE cAccumGreenBits;    //积累缓存中的绿色信息位面数
BYTE cAccumBlueBits;     //积累缓存中的蓝色信息位面数
BYTE cAccumAlphaBits;      //积累缓存中的alpha信息的位面数
BYTE cDepthBits;          //深度缓存保存的深度值
BYTE cStencilBits;        //模板缓存中保存的深度值   
BYTE cAuxBuffers;          //软件加速并不使用该项,辅助缓存区的数目
BYTE iLayerType;          //1.0版本的OpenGL只能置为PFD_MAIN_PLANE
BYTE bReserved;            //必须置为0
DWORD dwLayerMask;
DDWOR dwVisibleMask;
DWORD dwDamageMask;
} PIXELFORMATDESCRIPTOR;
;

其中以每一个像素的颜色缓存区为例子说明一下各参数的意义,如下图所示。


图:像素格式结构体中每一像素的颜色缓存区(RGBA模式)

3.2像素格式的种类

Windows对OpenGL的软件实现中支持24种不同的像素格式,虽然每一种都由唯一的标识(1-24)所区别,但并非这么简单。某一种像素格式,主要还是由其内所具有的属性来归类,如下图:



图:像素格式的主要属性

由上面的图中可以看出,对一个像素格式进行归类,主要看它的BPP,即每个像素的字节位数。这里支持5种位面组成:32BPP、24BPP、16BPP、8BPP和4BPP。如果按照这种分类方法,24种定义的像素格式中,有8种是专门为显示硬件所设计的,显示硬件驱动程序定义了每个像素应该具有的字节位数,这些像素格式被称为是与硬件相匹配的“本地像素格式”(native format),余下的16种像素格式叫作“非本地像素格式”,这些像素格式支持对位图的操作。

还可以按照像素数据类型来分,RGBA和颜色索引值。然后可以按单缓存或是双缓存分类,最后可以按照深度缓存的深度分类(32或者16)。这样算起来,像素格式的各类不下40种,但是16种非本地像素格式被限制使用,因为它们对位图的双缓存区不起作用。各种像素格式的各类,具体可以参见MSDN。

3.3列举像素格式

像素格式各类比较多,开发者应该为自己的应用程序精心挑选一款适合自己具体情况的像素格式。可以写一个程序来列举所有的像素格式。代码如下:

void CPixForm::OnClickedLastPfd()
{
COpenGL gl;
PIXELFORMATDESCRIPTOR pfd;
//
//得到视类窗口的句柄.
//
HWND hwndview = GetViewHwnd();
//
//得到与视类窗口相关联的DC句柄
//
HDC   hdc   = ::GetDC(hwndview);
int nID = (m_nNextID > 1) ? m_nNextID-- : 1;
//
//得到像素格式的具体内容,如果不可用,那么查看下一个,并更新对话框内容,否则什么都不做
//
if (gl.DescribePixelFormat(hdc, nID, sizeof(PIXELFORMATDESCRIPTOR), &pfd))
    UpdateDlg(&pfd);
//
//释放DC
//
::ReleaseDC(hwndview, hdc);
}

3.4管理像素格式的函数

有4个函数用于像素格式的管理。它们都是Win32函数。它们分别是:

ChoosePixelFormat
SetPixelFormat
GetPixelFormat
‍DescribePixelFormat

使用这些函数的一般方法由下图给出:



图:像素格式管理函数的使用

一个应用程序可以从上图中的最上面的方块(也就是PIXELFORMATDESCRIPTOR结构体中)知道一些基本的信息,比如说程序应用使用双缓存、应该对窗口进行OpenGL渲染、可以支持GDI等等。应用程序要么调用ChoosePixelFormat函数,要么调用它自定义的像素格式匹配函数。其中前者将开发者要求的像素格式与软件或者硬件支持的像素格式进行比较,并返回最匹配的某一款像素格式,下面的步骤具体描述了这种匹配的过程:

   ***   首先,ChoosePixelFormat( )函数查找那些满足开发者定义的像素格式的属性,如:
            ***   PFD_DRAW_TO_WINDOW
            *** PFD_DRAW_TO_BITMAP
            *** PFD_SUPPORT_GDI
            *** PFD_SUPPORT_OPENGL
            *** PFD_TYPE_RGBA
            *** PFD_TYPE_COLORINDEX
            *** PFD_DOUBLEBUFFER
            *** PFD_STEREO
   ***   然后,函数尝试与下面的属性值进行匹配:
            ***   cColorBits
            *** cAlphaBits
            *** cAccumBits
            *** cDepthBits
            *** cStencilBits
            *** cAuxBuffers
            *** iLayerType
   ***   最后,在返回的可匹配的像素格式中,如果既有硬件支持的又有软件支持的,函数会优先选择前者作为最佳结果返回给开发者。

一旦你有了一款合适的像素格式,就调用SetPixelFormat( )函数,将窗口的像素格式设为选择结果。一旦窗口的像素格式设置成功,它就不能再被修改了。

3.5硬件支持的像素格式识别

要识别一款像素格式是否被硬件支持,可以通过下面的代码实现,它主要是利用像素格式结构体中的dwFlags域来查看像素格式的相关信息。

BOOL COpenGL::IsDeviceIndex(HDC hdc, int idx)
{
ASSERT (hdc);
ASSERT (idx > 0);
BOOL bRet = FALSE;
PIXELFORMATDESCRIPTOR pfd;
int ipfdmax = DescribePixelFormat(hdc, idx, sizeof(PIXELFORMATDESCRIPTOR), 
                &pfd);
if (!(pfd.dwFlags & PFD_GENERIC_FORMAT))
    bRet = TRUE;
return (bRet);
}

如果‍PFD_GENERIC_FORMAT位被置1,那么像素格式是软件支持。否则为硬件支持的。那么查看一款像素格式是否为本地像素格式,也可以用类似的方法完成:

BOOL COpenGL::IsNativeIndex(HDC hdc, int idx)
{
ASSERT (hdc);
ASSERT (idx > 0);

BOOL bRet = FALSE;
PIXELFORMATDESCRIPTOR pfd;
int ipfdmax = DescribePixelFormat(hdc, idx, sizeof(PIXELFORMATDESCRIPTOR), 
                &pfd);

if (pfd.dwFlags & PFD_DRAW_TO_WINDOW)
    bRet = TRUE;
return (bRet);
}

如果PFD_DRAW_TO_WINDOW被置1,那么像素格式就是本地像素格式。否则,它是非本地像素格式,于是可用以支持位图操作。

4.RC管理

4.1OpenGL与DC

在使用OpenGL与DC之前,有以下注意事项:

   ***   窗口的像素格式被设置后,就不能再修改;
   ***   DC可用以创建RC,它可以被释放或者删除,所有的DC依次被收回或者创建的时候,必须有正确的像素格式索引号与之对应。

为了取得当前使用的像素格式的索引号,可以使用GetPixelFormat( )函数,下面的代码显示了如何应用这个函数:

int COpenGL::GetCurPFDIndex()
{
int icuridx = GetPixelFormat(wglGetCurrentDC());
return (icuridx);
}

得到的icuridx可以再传入DescribePixelFormat( )函数,以便取得更多的信息。

4.2 OpenGL的RC

在使用RC之前,也有几点注意事项:

   ***   在创建RC之前,必须设置好像素格式
   ***   在调用任何OpenGL命令之前,RC必须与DC相关联
   ***   RC与DC相关联期间,DC不得被释放或者删除(除非与该DC对应的窗口类的风格为CS_OWNDC)

有5个函数用以管理RC:

wglCreateContext
wglMakeCurrent
wglGetCurrentContext
wglGetCurrentDC
wglDeleteContext

这些函数都很重要,但是你格外注意一下wglMakeCurrent( )函数,该函数能让所有的绘图在DC上完成。通常,应用程序调用wglCreateContext(),然后将调用wglMakeCurrent()将RC与绘图面相关联,然后OpenGL可以绘图,然后仍然用‍wglMakeCurrent()将RC与绘图面分离,最后RC由wglDeleteContext()删除。

4.3两种RC的管理机制

既然DC(包括像素格式)与RC如此紧密地联系,那么如何将它们合理地利用并管理呢?首先,用DC创建一个RC,OpenGL利用这个RC在DC上,最终在绘图面上进行绘制。有两种方法利用DC。如下图所示,DC在程序初始化时创建,在程序关闭时释放。这种方法有些让人不安,因为我们并没有在同一个作用域内完成DC的创建和释放。其实这种作法是可行的,没有错误。


图:RC的管理机制一

另一种方法则比较传统,如下图所示。这种方法里面,RC与两个DC进行了关联,同时要调用两次wglMakeCurrent( )函数,这个函数是相当耗时的,所以这种方法在实时渲染和动画设计中,不推崇使用。


图:RC管理机制二

5.总结

Windows平台为OpenGL提供了软件实现,如果没有硬件驱动支持,所有的像素格式和RC的管理都交由GDI处理。如果有硬件驱动支持,那么硬件设备会分担很多管理任务,从而使OpenGL渲染运行地更快。在OpenGL可以绘图之前,窗口、位图或者硬件的像素格式必须初始化。然后创建RC,最后由程序开发人员在此基础上尽情展示自己精彩的程序

参考文献

[1] 刘梢月 图形处理OpenGL硬件加速 ‍http://blog.csdn.net/liusaoyue/archive/2009/12/29/5093949.aspx
[2] Dennis Crain Windows NT OpenGL: Getting Started   Microsoft Developer NetWork Technology Group MSDN-2001

这篇关于opengl像素格式和RC管理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/955291

相关文章

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

软考系统规划与管理师考试证书含金量高吗?

2024年软考系统规划与管理师考试报名时间节点: 报名时间:2024年上半年软考将于3月中旬陆续开始报名 考试时间:上半年5月25日到28日,下半年11月9日到12日 分数线:所有科目成绩均须达到45分以上(包括45分)方可通过考试 成绩查询:可在“中国计算机技术职业资格网”上查询软考成绩 出成绩时间:预计在11月左右 证书领取时间:一般在考试成绩公布后3~4个月,各地领取时间有所不同

安全管理体系化的智慧油站开源了。

AI视频监控平台简介 AI视频监控平台是一款功能强大且简单易用的实时算法视频监控系统。它的愿景是最底层打通各大芯片厂商相互间的壁垒,省去繁琐重复的适配流程,实现芯片、算法、应用的全流程组合,从而大大减少企业级应用约95%的开发成本。用户只需在界面上进行简单的操作,就可以实现全视频的接入及布控。摄像头管理模块用于多种终端设备、智能设备的接入及管理。平台支持包括摄像头等终端感知设备接入,为整个平台提

从状态管理到性能优化:全面解析 Android Compose

文章目录 引言一、Android Compose基本概念1.1 什么是Android Compose?1.2 Compose的优势1.3 如何在项目中使用Compose 二、Compose中的状态管理2.1 状态管理的重要性2.2 Compose中的状态和数据流2.3 使用State和MutableState处理状态2.4 通过ViewModel进行状态管理 三、Compose中的列表和滚动

easyui同时验证账户格式和ajax是否存在

accountName: {validator: function (value, param) {if (!/^[a-zA-Z][a-zA-Z0-9_]{3,15}$/i.test(value)) {$.fn.validatebox.defaults.rules.accountName.message = '账户名称不合法(字母开头,允许4-16字节,允许字母数字下划线)';return fal

Sentinel 高可用流量管理框架

Sentinel 是面向分布式服务架构的高可用流量防护组件,主要以流量为切入点,从限流、流量整形、熔断降级、系统负载保护、热点防护等多个维度来帮助开发者保障微服务的稳定性。 Sentinel 具有以下特性: 丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应

NGINX轻松管理10万长连接 --- 基于2GB内存的CentOS 6.5 x86-64

转自:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=190176&id=4234854 一 前言 当管理大量连接时,特别是只有少量活跃连接,NGINX有比较好的CPU和RAM利用率,如今是多终端保持在线的时代,更能让NGINX发挥这个优点。本文做一个简单测试,NGINX在一个普通PC虚拟机上维护100k的HTTP

PMBOK® 第六版 规划进度管理

目录 读后感—PMBOK第六版 目录 规划进度管理主要关注为整个项目期间的进度管理提供指南和方向。以下是两个案例,展示了进度管理中的复杂性和潜在的冲突: 案例一:近期,一个长期合作的客户因政策要求,急需我们为多家医院升级一个小功能。在这个过程中出现了三个主要问题: 在双方确认接口协议后,客户私自修改接口并未通知我们,直到催进度时才发现这个问题关于UI设计的部分,后台开发人员未将其传递给

PHP原理之内存管理中难懂的几个点

PHP的内存管理, 分为俩大部分, 第一部分是PHP自身的内存管理, 这部分主要的内容就是引用计数, 写时复制, 等等面向应用的层面的管理. 而第二部分就是今天我要介绍的, zend_alloc中描写的关于PHP自身的内存管理, 包括它是如何管理可用内存, 如何分配内存等. 另外, 为什么要写这个呢, 因为之前并没有任何资料来介绍PHP内存管理中使用的策略, 数据结构, 或者算法. 而在我们

[数据集][目标检测]血细胞检测数据集VOC+YOLO格式2757张4类别

数据集格式:Pascal VOC格式+YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):2757 标注数量(xml文件个数):2757 标注数量(txt文件个数):2757 标注类别数:4 标注类别名称:["Platelets","RBC","WBC","sickle cell"] 每个类别标注的框数: