OpenGL 工作原理

OpenGL 工作原理

OpenGL 图形接口的设计 The Design of the OpenGL Graphics Interface

Mark Segal Kurt Akeley Silicon Graphics Computer Systems 2011 N. Shoreline Blvd., Mountain View, CA 94039

Abstract

OpenGL 是一种新兴的图形标准,它提供高级渲染功能,同时 保持简单的编程模型。因为 OpenGL 是仅渲染的,它可以被合 并到任何窗口系统中(并且已经被合并到 X 窗口系统和即将发 布的 Windows 版本中)或者可以在没有窗口系统的情况下使 用。OpenGL 实现可以有效地适应几乎任何级别的图形硬件, 从基本的帧缓冲区到最复杂的图形子系统。因此,在交互式 3 D 和 2D 图形应用程序中使用它是一个不错的选择。

我们描述了这些和其他考虑因素如何控制 OpenGL 中图形运算 符的选择和表示。复杂的操作已被避开,取而代之的是对 3D 和 2D 图形的基本操作进行简单、直接的控制。然而,更高级 别的图形函数可以从 OpenGL 的低级运算符构建,因为这些运 算符在设计时就考虑到了这种分层。

CR 类别和主题描述符:I.3.3[计算机图形学]:图片图像生成;I.3.7【计算机图形学】:三维图形与写实

1 Introduction

计算机图形(尤其是 3D 图形,尤其是交互式 3D 图形)正在寻 找越来越多的应用程序,从用于个人计算机的简单图形程序到用于工作站和超级计算机的复杂建模和可视化软件。随着对计算机图形学的兴趣不断增长,人们希望能够编写在具有 一系列图形功能的各种平台上运行的应用程序。图形标准消 除了为运行应用程序的每个平台编写不同的图形驱动程序的 需要,从而简化了这项任务。

为了可行,用于交互式 3D 应用程序的图形标准必须满足几个 标准。它必须能够在具有不同图形功能的平台上实现,而不会影响底层硬件的图形性能,也不会牺牲对硬件操作的控制 。它必须提供一个自然接口,允许程序员简洁地描述渲染操作。最后,界面必须足够灵活适应扩展,以便当新的图形操作变得重要或在新的图形子系 统中可用时,可以在不破坏原始界面的情况下提供这些操作 。

OpenGL 通过为 3D 图形渲染的基本操作提供简单、直接的接口来满足这些标准。它支持点、线段、多边形和图像等基本图形基元,以及仿射和投影变换和光照计算等基本渲染操作 。它还支持高级渲染功能,例如纹理映射和抗锯齿。

还有其他几个提供 API 的系统(Application Programmer's Interface) 用于影响图形渲染。在 2D 图形的情 况下,PostScript 页面描述语言 [5] 已被广泛接受,使得电子交换相对容易,并且在一定程度上可以操作包含文本和 2D 图 形的静态文档。除了提供图形渲染操作符之外,PostScript 还是一种基于堆栈的编程语言。

X 窗口系统 [9] 已成为 UNIX 工作站的标准。程序员使用 X 在图形显示上获得一个窗口,可以在其中绘制文本或 2D 图形;X 还提供了一种从键盘和鼠标等设备获取用户输入的方法。大 多数工作站制造商采用 X 意味着单个程序可以通过简单地重新编译程序来生成 2D 图形或在各种工作站上获取用户输入。这 种集成甚至可以跨网络工作:程序可以在一个工作站上运行 ,但在另一个工作站上显示并从另一个工作站上获取用户输入,即使网络两端的工作站是由不同的公司制造的。

对于 3D 图形,有几个系统正在使用中。一个相对知名的系统 是 PHIGS(程序员的分层交互式图形系统)。PHIGS 基于 GK S[6](图形内核系统),是一个 ANSI(美国国家标准协会) 标准。PHIGS(及其后代 PHIGS+[11])提供了一种操作和绘制 3D 对象的方法,方法是将对象描述和属性封装到显示列表中,然后在显示或操作对象时引用该列表。显示列表的一个优点是即使要显示多次,复杂对象也只需要描述一次。如果要显示的对象必须通过低带宽通道(例如网络)传输,这一点尤其重要。显示列表的一个缺点是,如果由于用户交互而不断修改对象,则可能需要相当大的努力来重新指定对象。P HIGS 和 PHIGS+(以及 GKS)的另一个困难是缺乏对高级渲染功能(如纹理映射)的支持。PEX[10] 扩展了 X 以包含操纵和绘制 3D 对象的能力。

(PEXlib[7] 是一个使用 PEX 协议的 API。)最初基于 PHIGS,PEX 允许立即模式渲染,这意味着对象可以按描述的方式显示,而不必先完成显示列表。PEX 目前缺乏高级渲染功能(尽管提供此类功能的兼容版本尚未设计),并且仅适用于 X 的用户。然而,从广义上讲,描述图形对象以使用 PEX(或者更确切地说,PEXlib)进行渲染的方法类似于 OpenGL 提供的那些。

与 OpenGL 和 PEXlib 一样,Renderman[16] 是一种 API,它提供了一种渲染几何对象的方法。然而,与这些界面不同的是 ,Renderman 提供了一种编程语言(称为着色语言)来描述这些对象在绘制时如何出现。这种可编程性允许生成看起来非常逼真的图像,但在大多数图形加速器上实现是不切实际的,这使得 Renderman 成为交互式 3D 图形的糟糕选择。

最后,作为描述高级图形对象的方法的结果,有一些 API 提供对 3D 渲染的访问。其中最主要的是 HOOPS[17] 和 IRISInvent or[15]。这些接口提供的对象通常比使用 PEXlib 或 OpenGL 等 API 描述的简单几何图形更复杂;它们可能不仅包括几何图形 ,还包括有关它们如何绘制以及它们如何对用户输入作出反应的信息。

HOOPS 和 Inventor 将程序员从单个绘图操作的繁琐描述中解 放出来,但对复杂对象的简单访问通常意味着失去对渲染的精细控制(或至少使这种控制变得困难)。在任何情况下,OpenGL 都可以为构建此类更高级别的 API 提供良好的基础。

2 OpenGL

在本节中,我们将简要介绍 OpenGL。更全面的描述,请读者参考 [8] 或 [13]。

OpenGL 将图元绘制到帧缓冲区中,并受多种可选模式的影响 。每个图元都是一个点、线段、多边形、像素矩形或位图。 每种模式都可以独立改变;一个模式的设置不会影响其他的设置 (尽管许多模式可能会相互作用以确定最终在帧缓冲区中结束的内容)。通过以函数或过程调用的形式发出命令来设置模式、指定图元和其他 OpenGL 操作。

alt

图 1 显示了 OpenGL 的示意图。命令在左侧输入 OpenGL。大多数命令可以累积在显示列表中以供以后处理。否则,命令将通过处理管道有效发送。

第一阶段提供了一种通过评估输入值的多项式函数来逼近曲线和曲面几何形状的有效方法。下一阶段对顶点描述的几何图元进行操作:点、线段和多边形。在这个阶段,顶点被变换和点亮,图元被裁剪到一个视锥体中,为下一个阶段光栅化做准备。光栅器使用点、线段或多边形的二维描述生成一系列帧缓冲区地址和值。这样产生的每个片段都被馈送到下一个阶段,在它们最终改变帧缓冲区之前对各个片段执行操作。这些操作包括基于传入和先前存储的深度值(以实现深度缓冲)对帧缓冲区进行条件更新,将传入的片段颜色与存储的颜色混合,以及对片段值进行屏蔽和其他逻辑操作。

最后,像素矩形和位图绕过管道的顶点处理部分,通过光栅化直接将一个片段块发送到各个片段操作,最终导致一个像素块被写入帧缓冲区。值也可以从帧缓冲区读回或从帧缓冲区的一部分复制到另一部分。这些传输可能包括某种类型的解码或编码。

3 设计注意事项

设计任何 API 都需要在许多一般因素之间进行权衡,例如完成常见操作的简单性与通用性,或者带有少量参数的许多命令与带有许多参数的少量命令。在本节中,我们将描述影响 OpenGL 开发的 3DAPI 设计所特有的考虑因素。

3.1 性能 Performance

交互式 3D 图形的一个基本考虑因素是性能。渲染一个复杂度不高的 3D 场景需要进行大量计算,并且在交互式应用程序中 ,通常每秒必须重绘几次场景。因此,用于交互式 3D 应用程序的 API 必须提供对其使用的图形硬件功能的有效访问。但是不同的图形子系统提供不同的能力,所以必须找到一个通用的接口

该界面还必须提供一种打开和关闭各种渲染功能的方法。这 是必需的,因为某些硬件可能不支持某些功能,因此无法为这些功能提供可接受的性能,还因为即使有硬件支持,启用某些功能或功能组合可能会显着降低性能。例如,在生成场景的最终图像时,慢速渲染可能是可以接受的,但在处理场景中的对象或调整视点时,通常需要交互速率。在这种情况 下,性能下降的特征可能对最终图像是可取的,但在场景操作期间是不可取的。

3.2 正交性 Orthogonality

由于希望能够打开和关闭功能,因此这样做应该对其他功能几乎没有副作用。例如,如果希望使用单一颜色绘制每个多边形,而不是在其面上插入颜色,则这样做不应影响如何应用光照或纹理。类似地,启用或禁用任何单个功能不应导致渲染结果未定义的不一致状态。这些类型的特征独立性是必要的,它允许程序员轻松地操作特征,而不必为特定的非法或不希望的特征组合生成测试,这可能需要改变貌似不相关的特征的状态。功能独立性的另一个好处是可以以设计界面时未预见到 的有用方式组合功能。

3.3 完备性 Completeness

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
OpenGL Compute Shader是OpenGL 4.3引入的一种新型Shader,它主要用于通用计算(GPGPU)任务而不是图形渲染。它可以在GPU上执行高度并行的计算任务,例如物理模拟、图像处理和机器学习等。Compute Shader与其他Shader不同之处在于它没有渲染管道的输入和输出,并且可以从CPU上下文中直接调用。它还可以读写各种类型的缓冲区和纹理,使其非常灵活和强大。 Compute Shader的使用步骤如下: 1.创建Compute Shader对象:使用glCreateShader函数创建Compute Shader对象。 2.编译Compute Shader代码:使用glShaderSource和glCompileShader函数将Compute Shader代码编译为OpenGL可识别的二进制格式。 3.创建Compute Program对象:使用glCreateProgram函数创建Compute Program对象。 4.将Compute Shader附加到Compute Program对象上:使用glAttachShader函数将Compute Shader附加到Compute Program对象上。 5.链接Compute Program对象:使用glLinkProgram函数将Compute Program对象链接到OpenGL渲染管道。 6.使用Compute Shader:使用glUseProgram函数激活Compute Program对象,并通过glDispatchCompute函数调用Compute Shader。 7.清理资源:使用glDeleteShader和glDeleteProgram函数删除Compute Shader和Compute Program对象。 下面是一个简单的Compute Shader示例代码: ```glsl #version 430 layout(local_size_x = 16, local_size_y = 16) in; layout(std430, binding = 0) buffer InputBuffer { float data[]; }; layout(std430, binding = 1) buffer OutputBuffer { float result[]; }; void main() { uint idx = gl_GlobalInvocationID.x + gl_GlobalInvocationID.y * gl_NumWorkGroups.x * gl_WorkGroupSize.x; result[idx] = data[idx] * data[idx]; } ``` 这个Compute Shader使用输入缓冲区和输出缓冲区,对输入缓冲区的每个元素进行平方运算,并将结果存储在输出缓冲区中。在主函数中,使用gl_GlobalInvocationID获取全局线程ID,计算出要处理的输入元素的索引,并在输出缓冲区中存储计算结果。 最后,通过调用glDispatchCompute函数启动Compute Shader。该函数需要指定调度的工作组数量,以及每个工作组中线程的数量。在这个示例中,我们使用16x16的工作组,并将其应用于输入缓冲区的所有元素。 ```c++ glDispatchCompute(numGroupsX, numGroupsY, numGroupsZ); ``` 以上就是OpenGL Compute Shader的原理与使用方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值