创建OpenGL Context(WGL)

创建OpenGL Context是初始化OpenGL的一部分。只有在此之后才能使用OpenGL。

关于platform的注意事项

创建OpenGL context之后才会存在OpenGL。这个创建过程不归OpenGL Specification管,而是归各个platform的API管。本文讨论基于Windows的初始化过程。许多Windows上的初始化函数是以”wgl”开头的。

本文假设读者知道Win32 API的基础知识。读者应知道window handle(HWND)和device context(DC)是什么,以及如何创建他们。本文不是讲解如何创建窗口的教程。

创建一个简单的Context

这一节是创建Context的基础知识。

窗口

创建HWND时,要确保它有CS_OWNDC设置。

像素格式

MS Windows里,每个窗口都有一个Device Context(DC)与之关联。DC里存储有像素格式PixelFormat。你创建的OpenGL Context里有个默认的framebuffer,PixelFormat是描述此framebuffer的属性的数据结构。

设置PixelFormat的方式并不直观。首先你创建一个你想要的pixelFormat,然后交给ChoosePixelFormat函数,此函数会查找能够支持的PixelFormat列表,返回最接近pixelFormat的编号。然后你就可以用此编号指定DC的PixelFormat。

上面描述的数据结构就是PIXELFORMATDESCRIPTOR。

 1 PIXELFORMATDESCRIPTOR pfd =2 {3     sizeof(PIXELFORMATDESCRIPTOR),4     1,5     PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,    //Flags6     PFD_TYPE_RGBA,            //The kind of framebuffer. RGBA or palette.7     32,                        //Colordepth of the framebuffer.8     0, 0, 0, 0, 0, 0,9     0,
10     0,
11     0,
12     0, 0, 0, 0,
13     24,                        //Number of bits for the depthbuffer
14     8,                        //Number of bits for the stencilbuffer
15     0,                        //Number of Aux buffers in the framebuffer.
16     PFD_MAIN_PLANE,
17     0,
18     0, 0, 0
19 };

你看,很多field都是0。就这样,没问题。我们需要关心的field,你可能需要用的field,都用注释标记了。关于PixelFormat的更多flags,请查询Windows SDK文档。

上文说到ChoosePixelFormat函数,它接收一个DC和一个PFD,返回一个编号。如果返回的是0,那就意味着找不到匹配的PixelFormat,或者PDF内容错误。

有了PixelFormat编号,就可以用SetPixelFormat指定给DC。这个函数接收DC、编号和PFD的指针。别激动,这个函数没有读取PFD里的任何重要信息。

创建Context

接下来创建context就简单了。调用wglCreateContext。这个函数接收DC,返回OpenGL Context的句柄。

在使用OpenGL前,要用wglMakeCurrent 把context设置为current。如果已经有current context,这个函数会把旧context替换掉。后续的OpenGL函数调用会影响新context中的状态。如果你传入NULL,那么旧context会被移除,后续OpenGL函数调用会失败(崩溃)。

current context是线程专用的。每个线程可以将一个不同的context设置为current。将同一个context设置为多个线程的current是危险的。

删除Context

严格来说这不是创建Context的内容,但是你应当指定如何删除Context。

首先要确定你想删除的Context不是current。给wglMakeCurrent 传入NULL参数。

现在可以调用wglDeleteContext 来删除它了。

创建合适的Context

除非你只想做一个很简单的程序,否则你不应当使用上述的简单步骤创建的context。有一些功能强大的WGL扩展函数助你创建高级context,但是创建context 过程会复杂些。

创建一个傻帽Context

关键问题是这样的:你用来获取WGL扩展的函数,其本身就是一个OpenGL扩展。因此,首先要有一个OpenGL Context,然后才能使用WGL扩展。所以,为了能够使用那些“创建context的函数”,我们首先要“创建一个context”。幸运的是,这个context用不着是我们最后的context。我们只需创建一个傻帽context来获取函数指针,然后直接使用这些函数即可。

警告:不幸的是,Windows不允许用户改变一个窗口的PixelFormat。你只能设置一次。因此,如果你想通过傻帽Context使用一个不同的PixelFormat,你必须在用完傻帽Context后彻底销毁这个窗口并重建之。

对于傻帽Context,一个好的PixelFormat选择是32位RGBA颜色缓存+24位深度缓存+8位模版缓存。我们上面就是这样设置的PFD。这通常都能得到一个硬件加速的PixelFormat。

所以,这一步就是重复上文的代码,创建一个傻帽Context,设置为current。

获取WGL扩展

Main article: Load OpenGL Functions#Windows 2

如果你使用了加载扩展的库,现在就可以调用任何你需要的函数。如果没有,你就得自己手动加载。

有不少扩展可以实施高端的context创建工作。其中大多数是围绕PixelFormat的创建和一个Exception。

Pixel Format扩展

PFD是帮助创建Context的很好的方式,但是有个缺点:不可扩展。因此,产生了WGL_ARB_pixel_format扩展。这个扩展定义了一种新的获取PixelFormat编号的机制,此机制的核心是由一个’属性值’的数组。

只有在定义了此扩展的机器上才能使用它。这个扩展已经存在很长时间了,即使很老的显卡也支持它。所以你可以打赌认为你的机器环境是实现了WGL_ARB_pixel_format的。

此扩展提供了几个新的函数,我们感兴趣的是下面这个:

1 BOOL wglChoosePixelFormatARB(   HDC hdc,
2                                 const int *piAttribIList,
3                                 const FLOAT *pfAttribFList,
4                                 UINT nMaxFormats,
5                                 int *piFormats,
6                                 UINT *nNumFormats);

wglChoosePixelFormatARB 类似ChoosePixelFormat。他接收的不是固定的PFD结构体,而是一个’属性值’的数组。很多属性都直接对应PFD里的字段,但有些属性是新的。而且,此函数能够返回多个符合要求的PixelFormat,并按照从最符合到最不符合的顺序排序。“最符合”是由具体OpenGL实现来决定的。

总之,使用方法很简单。piAttribIList 是整数属性列表。每2个元素构成一个’属性值’对。属性’0’表示列表结束,并且其后不需要值。你可以传入NULL,此函数会当作你传入一个空列表。

类似的,pfAttribFList 是浮点属性列表。每2个元素构成一个’属性值’对。如何将整型的属性放到float类型里?非常小心地放。你需要用static-cast(C++里)或者用其它技巧让bit-pattern保持相同。

nMaxFormats 是将要保存到piFormats里的数量的最大值。因此piFormats 应当至少有那么多个元素。nNumFormats 是返回值,告诉你piFormats真正存储了多少个元素。

如果函数返回FALSE,就意味着没有找到合适的PixelFormat。此时piFormats 就是未定义的状态(OpenGL实现可以随意修改其内容)如果函数返回不是FALSE,那么就成功了,你得到了PixelFormat编号。

下面的示例代码演示了如何使用此函数产生和上文近似的PixelFormat:

 1 const int attribList[] =2 {3     WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,4     WGL_SUPPORT_OPENGL_ARB, GL_TRUE,5     WGL_DOUBLE_BUFFER_ARB, GL_TRUE,6     WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,7     WGL_COLOR_BITS_ARB, 32,8     WGL_DEPTH_BITS_ARB, 24,9     WGL_STENCIL_BITS_ARB, 8,
10     0,        //End
11 };
12
13 int pixelFormat;
14 UINT numFormats;
15
16 wglChoosePixelFormatARB(hdc, attribList, NULL, 1, &pixelFormat, &numFormats);

有一些扩展,给这个函数增加了新的属性。你可能想要用到的有:

  • WGL_ARB_pixel_format_float:支持浮点framebuffer。
  • WGL_ARB_framebuffer_sRGB: 支持sRGB格式的colorbuffer。
  • WGL_ARB_multisample: 支持多重采样的framebuffer。

得到了PixelFormat编号,你就可以用SetPixelFormat指定给DC。

Attributes创建Context

为了移除旧功能,OpenGL3.0及其以上版本创造了一个“不推荐可移除”的模型。但是这带来一点问题。在之前的OpenGL版本,新版OpenGL是旧版的超集(superset)。因此,如果你想要的是1.5版context,结果得到的是2.0版,那没问题。你只是得到了额外的你用不到的功能。一旦出现了移除旧功能的可能性,这种超集关系就没有了。

因此出现了WGL_ARB_create_context扩展。它提供了代替wglCreateContext的函数。类似wglChoosePixelFormatARB,它提供了一种扩展机制,使你能够增加新的创建context所用的选项。

如果傻帽context没有提供这个扩展,那么你就不能用它。你就只能用wglCreateContext 了。

如果它提供了这个扩展,那么会有一些平常得不到的选项供我们选用:

  • 保证获取OpenGL3.0或者更高版本的Context。
  • 创建OpenGL3.2或者更高班的core context,且没有兼容旧特性。
  • 不用窗口,创建context,用于离屏渲染。这可能会做不成。

遗留问题:(这里有一堆没什么用的话,略过不译)如果定义了WGL_ARB_create_context_profile,那就用上述方法。如果没有,那就只能用wglCreateContext 直接创建GL3.0或更高版本context。

wglCreateContextAttribsARB 签名如下:

1 HGLRC wglCreateContextAttribsARB(HDC hDC, HGLRC hshareContext, const int *attribList);

这里的attribList 与wglChoosePixelFormatARB里的类似。它是一系列’属性值’对,以单独的0作为最后一个元素结尾。

你可以用WGL_CONTEXT_MAJOR_VERSION_ARB 和WGL_CONTEXT_MINOR_VERSION_ARB这2个属性指定你想要哪个版本。

你请求一个版本,然后你得到哪个版本?这个规则比较复杂,简单来说有两条:

  1. 它总会返回一个等于或高于你要求的版本的OpenGL Context。
  2. 它永远不会返回一个没有实现你要求的版本里的core feature的OpenGL版本。

如果定义WGL_ARB_create_context_profile了,那么你可以用WGL_CONTEXT_PROFILE_MASK_ARB 属性来选择一个core配置(WGL_CONTEXT_CORE_PROFILE_BIT_ARB)或者一个兼容配置(WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB)。注意,这些都是bit组合,所以你可以同时要求他们俩(不过你只会得到兼容配置)。这里面的细节就值得深入讨论了。

你也可以用WGL_CONTEXT_FLAGS_ARB属性指定若干flag。你可以用它请求一个向前兼容的context(WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB)且(或)一个debug context(WGL_CONTEXT_DEBUG_BIT_ARB)。Debug context常常实现了ARB_debug_output,能够提供加强了的error输出。向前兼容的context必须彻底移除deprecated特性,实际上你永远都不应该用这个选项

hshareContext 是个特殊的参数。如果你有2个GL Context,且你想让他们共享对象,那你可以用wglShareLists函数。但是你必须在创建对象(在任意两个context里)之前使用。wglCreateContextAttribsARB 直接配合这个功能。

创建OpenGL Context(WGL)相关推荐

  1. C#中使用OpenGL(API)创建OpenGL渲染环境

    在C#中调用1.1版本的OpenGL函数,但是光有OpenGL函数还不能绘制图形,就像一个画家,他即使拥有绘画的技巧,还有画笔和颜料,如果没有画布,他也没有地方画画.有了画布,画家还需要画板把画布支起 ...

  2. 在Win32程序中创建OpenGL渲染环境

    在Win32程序中创建OpenGL渲染环境 创建opengl渲染环境步骤: 选定像素格式 //WinMain()HDC dc = GetDC(hwnd);PIXELFORMATDESCRIPTOR p ...

  3. NeHe OpenGL教程 01 创建OpenGL窗口

    本节详细剖析了一个基本的OpenGL程序框架,要点如下: 1.注册窗口类,创建窗口 RegisterClass ChangeDisplaySettings AdjustWindowRectEx Sho ...

  4. 如何在Python中创建OpenGL/Glut

    OpenGL(开放图形库)是一种跨语言.多平台的应用程序编程接口(API),用于绘制二维和三维计算机图形. API通常用于与图形处理单元(GPU)交互,以实现硬件加速渲染.OpenGL由Silicon ...

  5. linux qt “QXcbIntegration: Cannot create platform OpenGL context, neither GLX nor EGL are enable“

    需要将[/home/jakauser/Qt5.9.9/5.9.9/gcc_64/plugins/xcbglintegrations]文件夹也复制过去

  6. BIT祝威博客汇总(Blog Index)

    +BIT祝威+悄悄在此留下版了个权的信息说: 关于硬件(Hardware) <穿越计算机的迷雾>笔记 继电器是如何成为CPU的(1) 继电器是如何成为CPU的(2) 关于操作系统(Oper ...

  7. OpenGL的Context(Profile)

    OpenGL在渲染的时候需要一个Context,这个Context记录了OpenGL渲染需要的所有信息,可以把它理解成一个大的结构体,它里面记录了当前绘制使用的颜色.是否有光照计算以及开启的光源等非常 ...

  8. OpenGL笔记5 shader 调试信息获取 Debug

    我们今天来讲调试信息,这个东西讲起来会比较无聊,因为都是一些函数调用,没啥可讲的,函数就是那样用的,不过其效果挺好玩的,同时在程序设计中也是很必要的,所以还是来写一下,不过,就是因为知识比较固定且简单 ...

  9. OpenGL ES2.0 – Iphone开发指引

    原文链接地址:http://www.raywenderlich.com/3664/opengl-es-2-0-for-iphone-tutorial 免责申明(必读!):本博客提供的所有教程的翻译原稿 ...

  10. GPU随想——OpenGL函数加载流程

    导航: GLX基本流程 OpenGL函数的分发 到底什么是context? -----------------------------读前须知------------------------- 历代d ...

最新文章

  1. 如何具体学习计算机视觉
  2. orth--将矩阵正交规范化
  3. flash,flex,actionscript的关系
  4. 计算机网络英文面试题,计算机网络面试题整理
  5. 论文浅尝 - AAAI2020 | 多轮对话系统中的历史自适应知识融合机制
  6. json模拟数据怎么用_在使用axios获取自己模拟的json数据是踩到的坑
  7. keytool生成证书_基于 TrueLicense 的项目证书验证
  8. puppet连载15:搭建zabbix服务端、客户端
  9. Unity 获得某个物体的主贴图
  10. 2.同步(Synchronization)
  11. python2.7 UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-5
  12. mysql_use_result与mysql_store_result异同点
  13. groupdel: cannot remove the primary group of user 'lxh1'的解决办法
  14. 在Centos7中安装英伟达显卡驱动
  15. 如何在php中显示170cm,身高 158cm,怎么穿才能像 170cm?
  16. 电脑文件夹与手机同步办公?
  17. 在国企的 Java 程序员是一种什么样的体验?让我来告诉你吧!
  18. 学习记录596@CSS用svg做背景
  19. java实现仿qq界面及功能、网路编程、实现抽象工厂模式、线程池代码与测试
  20. 四、移动手机自动化测试

热门文章

  1. Matlab简单爬虫-寻宝天行诛仙在售角色信息
  2. 华为云上传docker镜像
  3. xp大容量u盘补丁_u盘128g 个性 大容量电脑系统修复
  4. Linux常用命令宝典(简单易懂)
  5. Canvas 烟花合集 -- 将粉丝头像做成烟花在天空绽放✨
  6. 计算机硬盘数据清零,彻底清除Windows电脑磁盘数据
  7. Sping Cloud专栏:路由Gateway有效避免 Only one connection receive subscriber allowed问题
  8. 苏宁API:item_get - 获得suning商品详情
  9. bzoj1698 / P1606 [USACO07FEB]白银莲花池Lilypad Pond
  10. [分享]一次中移物联网校园招聘javaweb的笔试题