OpenGL版本和GPU - 有什么兼容性?

6
我正在尝试理解显卡版本、OpenGL版本和API头文件如何协同工作。我已经在OpenGL论坛和其他地方阅读了关于OpenGL 2.0/3.0/3.1的争议,但对于我这样一个新手开发人员来说,这仍然不太清楚(顺便说一句,我在这个问题中使用nVidia作为例子,因为我要购买他们的显卡,但显然我希望我的软件能够跨平台)。
首先,需要支持OpenGL版本的GPU。但是例如nVidia为旧视频卡提供驱动程序以支持OpenGL 3。这是否意味着这些驱动程序通过软件实现某些功能以模拟硬件中没有的新功能?
然后是API头文件。如果我决定编写支持OpenGL 3的应用程序,我应该等到微软发布更新的平台SDK并具有支持此版本的头文件吗?如何选择要使用的API版本-通过代码中的预处理器定义,还是只需更新到最新的平台SDK即可升级到最新版本(无法想象这是最后一种选择,但你永远不知道……)。
关于向后兼容性怎么样?如果我编写一个针对OpenGL 1.2的应用程序,安装了支持OpenGL 3的驱动程序的用户是否仍然能够运行它,或者我应该在我的应用程序中测试卡的功能/支持的版本?阅读http://developer.nvidia.com/object/opengl_3_driver.html似乎确认至少对于nVidia卡,针对1.2编写的应用程序将继续工作,但这也意味着其他供应商可能会停止支持1.2 API。基本上,这可能会使我在未来处于这样的位置,即软件不会与最新的卡一起工作,因为它们不再支持1.2。但是,如果我今天开发OpenGL 3甚至2,我可能会排除那些只支持1.2的gpu的用户。
我不需要OpenGL中的花哨功能-我几乎根本不使用任何着色,固定管道对我很有效(我的应用程序类似于CAD)。基于哪个版本是基于预期成为长期应用程序的最佳选择,并且在未来几年内进行增量更新?
我可能忘记了其他相关问题,在这种情况下,任何见解都非常感谢。
3个回答

8
根据我的OpenGL经验,似乎“针对”特定版本只是访问为该版本添加的各种扩展。因此,您之所以要“针对”OpenGL版本3,就是因为您想使用某些新版本3中新增的扩展。如果您不真正使用版本3扩展(如果您只是进行基本的OpenGL操作),那么您自然不会“针对”版本3。
在Visual Studio中,您将始终链接您的应用程序与opengl32.lib,并且opengl32.lib在不同的OpenGL版本之间不会发生变化。相反,OpenGL使用wglGetProcAddress()来动态访问运行时的OpenGL扩展/版本,而不是编译时。也就是说,如果给定的驱动程序不支持扩展,则当请求该扩展的过程时,wglGetProcAddress()将在运行时返回NULL。因此,在您的代码中,您需要实现处理NULL返回情况的逻辑。在最简单的情况下,您可以打印错误并说“此功能不可用,因此此程序将表现为...”。或者您可以找到其他替代方法来执行不使用扩展的相同操作。在大多数情况下,您只会从wglGetProcAddress获取NULL返回,如果您的应用程序正在运行旧硬件/驱动程序上,这些硬件/驱动程序不支持添加扩展的OpenGL版本。但是,在未来几年中,您将希望了解那些新的OpenGL版本决定废弃的事物。我没有仔细阅读3.1规范,但显然他们正在引入一个废弃模型,其中旧技术/扩展可能会被废弃,这将为新硬件/驱动程序不再支持废弃扩展打开大门,在这种情况下,wglGetProcAddress将再次返回NULL。因此,如果您在处理wglGetProcAddress()的NULL返回时放置了逻辑,则即使对于废弃的扩展,您也应该没问题。只是您可能需要实现更好的替代方案或使新的扩展成为默认值。
就版本化API头而言,对头文件的更改主要只是更改以允许访问由wglGetProcAddress()返回的新函数。因此,如果您包括版本2的API头,则只要您只需要OpenGL 2的扩展,您就可以使用。如果您需要访问在版本3中添加的函数/扩展,则只需用版本3的头文件替换版本2的头文件,后者只添加了一些与新扩展相关的附加函数指针typedef,以便在调用wglGetProcAddress()时,您可以将返回值转换为正确的函数指针。例如:
PFNGLGENQUERIESARBPROC glGenQueriesARB = NULL;

...

glGenQueriesARB = (PFNGLGENQUERIESARBPROC)wglGetProcAddress("glGenQueriesARB");

在上面的例子中,PFNGLGENQUERIESARBPROC的typedef在API头文件中定义。我相信glGenQueriesARB是在1.2版本中添加的,所以我需要至少1.2 API头文件才能得到PFNGLGENQUERIESARBPROC的定义。这就是头文件的全部作用。
还有一件事情我想提一下关于3.1版本。显然,在3.1版本中,他们正在废弃我们公司广泛使用的许多OpenGL功能,包括显示列表、glBegin/glEnd机制和GL_SELECT渲染模式。我不太了解细节,但我不知道他们如何能够这样做而不必创建一个新的opengl32.lib来链接,因为似乎大部分该功能都嵌入到opengl32.lib中,并且不能通过wglGetProcAddress访问。此外,Microsoft是否会将新的opengl32.lib包含在他们的Visual Studio版本中?我没有这些问题的答案,但我认为,即使3.1版本废弃了它,这个功能也将存在很长时间。如果您继续链接您当前的opengl32.lib,它应该会持续工作几乎无限期,尽管您可能会在某个时候失去硬件加速。网络上绝大多数OpenGL教程都使用glBegin/glEnd方法来绘制基本形状。对于GL_SELECT也是如此,虽然很多硬件不再加速GL_SELECT渲染模式。即使是opengl.org的教程也使用了被认为过时的glBegin/glEnd方法。而且我还没有找到一个只使用3.1功能、避免使用废弃功能的“入门”教程(当然,如果有人知道这样的教程,请给我链接)。无论如何,虽然3.1版本似乎抛弃了很多旧的东西来迎接全新的东西,但我认为这些旧的东西仍将存在相当长的一段时间。
长话短说,这是我的建议。如果您的OpenGL需求很简单,只需使用基本的OpenGL功能。顶点数组在1.1-3.1版本中都受支持,因此如果您想要最大寿命并且从头开始,那么这可能是您应该使用的内容。然而,我的意见是,即使在第3版中它们被废弃了,glBegin/glEnd和显示列表仍将存在一段时间,所以如果您想使用它们,我不会太担心。我会避免使用GL_SELECT模式进行选择,而选择其他方法。许多硬件供应商多年来一直认为GL_SELECT已经过时了,即使它刚刚在第3版中被废弃。在我们的应用程序中,我们遇到了很多在ATI卡和集成的GMA卡上无法工作的问题。因此,我们只是实现了一个使用遮挡查询的选择方法,这似乎解决了问题。因此,为了第一次做对,避免使用GL_SELECT。
祝你好运。

2
就驱动程序而言,在某些情况下缺少的功能是通过软件编写的。使用OpenGL的整个重点(除了加速)是编写API而不关心它是如何实现的。
根据我的经验,您不需要声明OpenGL版本。 API版本之间的函数调用不重叠。请注意规范,如果例如调用2.0方法,则应用程序的最小版本就变成了2.0。我编写了显示应用程序以针对OpenGL(愚蠢的旧Sun视频卡),并且在全新的nvidia 200系列卡上运行得很好。
我认为没有任何方式可以保证API在将来不会更改,特别是如果您无法控制它。当我们使用OpenGL 6.4时,您的应用程序可能会在10年后停止工作。希望您编写了足够好的应用程序,客户愿意为升级付费。

0
这位名叫MarK J. Kilgard的人自90年代以来一直在发布nVidia的OpenGL源代码和文档,并代表着游戏硬件中最大的两个品牌之一。
//------------------------------------------------------------------------------------- ...认为OpenGL应用程序永远不应该使用即时模式是过于狂热的观点。OpenGL 3.0规范甚至已经将OpenGL中的即时模式标记为“弃用”(不管那意味着什么!);这种极端主义是适得其反且愚蠢的。鼓励良好API使用的正确方法不是试图废除或禁止API使用,而是教育开发人员在特定情况下选择正确的API使用方式。


为了教育开发人员在特定情况下正确使用API,我想补充一点:立即模式 = 在提交的“几何体”数量和具有非零开销的API调用数量之间存在线性相关关系。 - Gigi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接