为什么OpenGL有全局函数?

5
为什么OpenGL不是面向对象的?每个人都教授面向对象编程和设计模式,但OpenGL有许多全局函数。这不是一种糟糕的风格吗?

2
如果你想要一个更干净、面向对象的OpenGL接口,可以考虑使用像开源的OpenSceneGraph这样的中间件包。 - James McNellis
3
@James,实际上你的评论很好地说明了原因--我认为OSG很丑,不想采用那种设计...但由于OpenGL具有低级别的特性,我可以自己编写代码。 - Kornel Kisielewicz
5个回答

19
低级API的整个意义在于使其尽可能精简和易于移植。如果给它一个面向对象的架构,这将不可行:
- 多态性会增加不必要的函数调用开销。 - 它会强制您使用一些相对困难的调用约定,从而降低可移植性。 - 您无法将面向对象的架构包装成过程化的架构,但可以反之;因此,尽可能灵活是有意义的。如果需要,可以轻松编写OpenGL的面向对象包装器。
最后,你应该真正质疑你所学到的关于OOP的东西。尽管你的大学或学院告诉你OOP是程序设计的万灵药,但实际上并非如此。C ++ STL(以及大多数Boost)中绝对没有面向对象,这是有很好的原因的。
面向对象在某些情况下很有用,但你应该学会什么时候有用,什么时候不用,并且绝不能相信任何不是OOP的东西都是“坏风格”。

11

OpenGL

  • OpenGL 应该支持所有平台 -- 在这方面没有任何接近 C 语言的东西 - 感谢它几乎每个设备都可以使用相同的 API
  • OpenGL 应该支持所有语言 -- 在这方面也没有任何接近 C 语言的东西 - 感谢它,支持调用 C 库的每种语言(几乎所有语言)都可以使用 OpenGL
  • OpenGL 是一个 API,而不是引擎 -- 旨在为图形硬件提供 低级别 接口,并足够高级以成为不同硬件的抽象 -- C 比 C++ 更低级别,OOP 不是低级别
  • OpenGL 是一个可构建的框架,而不是完整的解决方案 -- 没有一种正确的方法来编写图形代码,OpenGL 不应强制我们做任何事情 - 如果采用 OOP,它将强制我们使用他们的“解决方案”
  • OpenGL 与任何特定的编程范型 无关 -- 因此,我们可以将 OpenGL 包装到函数式、逻辑或 OOP 语言中 -- 或者以过程化方式使用它
  • OpenGL 关注效率 -- 而直接函数调用是最有效率的。OOP 的效率与它适用于特定任务的程度一样高。

总的来说 -- OpenGL 的设计允许我们拥有完全自由,而不为我们做任何选择。而自由意味着选择平台、语言、编程范型、引擎设计、方法论和效率与可读性之间的水平。

因此,我称赞OpenGL,也因此我厌恶Direct X。

附注: 每个人都教授面向对象编程,因为它是最容易理解的。这不是唯一的真实范式。还有函数式编程、逻辑编程、契约编程,甚至是在 C 中编写面向对象的方式。计算机科学中没有唯一的真理。至于设计模式,我可以列出更多在OpenGL架构中使用的模式。坏的风格?我看过很多漂亮的C程序,里面有aaaaallll全局函数...


1
我喜欢你的回答,它更详细地阐述了我想说的内容。 :) 此外,我同意GL与DX之间的选择。我曾经一直信奉DX,但最终尝试了OpenGL,尽管我认为它可以大大改进,但它提供的灵活性和控制量非常棒,更不用说整个扩展系统了。我实际上可以利用非常特定的功能并逐渐回退,直到找到一个可行的方案,甚至可以使用一个供应商特定的助手,或者我的自己的通用实现。在DX中,你永远无法尝试设计这样的系统。 - GManNickG
@GMan,除此之外,说实话--如果想看一些不同于Windows和XBox的东西,除了OpenGL之外就没有其他API了... - Kornel Kisielewicz
完全正确。更多的人不利用OpenGL的力量是一件遗憾的事情。诚然,你需要知道更多才能开始使用它,但这没关系。 - GManNickG
2
我同意这个观点,刚开始使用OpenTK框架在C#中编写OpenGL程序,我非常喜欢它。我发现XNA很痛苦,而这个却真的很有趣! - Skurmedel

8
一般来说,OpenGL是面向对象的。它只是使用不直接支持面向对象编程的语言实现的。但是API是面向对象的:它由许多不同的对象类型和在每个对象上定义的一组操作组成。每个对象类型的内部都对用户隐藏。它满足所有面向对象编程的要求。只是它恰好是用C语言实现的,没有方便的类或成员方法语法。
除此之外,全局函数也没有任何问题。在C++中,一个常见的建议是尽可能优先使用全局函数而不是成员方法。在函数式编程中,全局函数是默认的。

3
OpenGL并不是面向对象的。OpenGL中没有类,只有原始数据类型。由于没有类,也就没有对象,也显然没有可以在对象上调用的方法。再一次强调,所有内容都只是改变OpenGL FSM状态的原始数据。这里没有消息传递(因为没有对象);没有继承(没有类);没有多态性(没有类)。 OpenGL API与面向对象编程唯一相似的地方就是它是一个抽象层,但是它使用过程进行内部抽象,而不是对象和类层次结构。 - Peter Alexander
1
+1:面向对象编程。Poita_,你曾经写过FBO或VBO吗? - Kornel Kisielewicz
1
@GMan,我理解了你的意思,但我认为你并不理解面向对象编程是什么。面向对象编程不仅仅是使用对象进行编程,那只是面向对象编程的一部分。面向对象编程具体指的是我上面提到的内容(例如多态性、继承、类层次结构、消息传递等)。如果一个对象只是数据和对数据的操作,那么这是否意味着所有的C编程都属于面向对象编程?我不这样认为。最后,我从来没有说过你不能在C中以面向对象的方式编程。 - Peter Alexander
2
@Poita_:重点是你通过一组相关的过程来操作数据,而不是像在纯C中经常出现的任意过程直接操作数据。但是另一方面,关于OOP有一些不同的解释。 - Georg Fritzsche
不,其实并不是面向对象编程(OOP),要成为OOP至少需要封装,但这里没有封装,你没有通过对象传递消息,操作和数据完全分离,这根本不是OOP。你可以在脑海中将其建模为OOP,但它并不是真正的OOP。 - user90843
显示剩余18条评论

4
OpenGL最初是在C语言中创建的,那时候还没有任何其他东西。即使现在,他们仍然希望保留C接口,因为C仍然是一种广泛使用的语言。
他们应该维护C接口和C++包装器吗?放弃C只使用C++?还是保留C接口?我认为后者是最好的解决方案:对他们来说容易,对我们来说也不太难。
话虽如此,OpenGL接口确实很丑陋。许多东西本应被“废弃”,但遗憾的是这些被推迟到了以后。

你认为什么是恶心的?此外,我在你的帖子中没有看到一个真正好的理由。即使OpenGL今天被设计,它仍然会是C语言。 - Kornel Kisielewicz
@Kornel:因此保留C接口。这对每个人来说都很容易使用。也许我应该更明确地表达:我的意思是几乎每种语言都可以与C库进行接口。至于那些丑陋的东西,如果你将OpenGL 3.0应该做什么与它实际做了什么进行比较,就会发现有大量无用和已弃用的函数挂在那里。对我来说,这使它变得丑陋。如果我想执行一个任务,一个干净的接口给我提供了一种好的灵活方式来完成;而不是一堆不同的方式,其中只有一种被认为是正确的方式。 - GManNickG
@Kornel:我从来没有想过这样做,我倾向于避免修改第三方头文件。话虽如此,我将OpenGL封装起来,所以我不再需要去碰它了。:)编写包装器很有趣。 - GManNickG
@GMan,我目前也在为GL编写一个类似于Boost的模板化包装器...这既有趣又疯狂 D: - Kornel Kisielewicz
@GMan - 例如,顶点是模板化的,因此对于任何类型的顶点编码(3v3n3c、2v2t等),都有单一的代码,网格的类型通过顶点定义进行模板化,并且处理它们的代码在运行时确定。还有一些更多的技巧 :> - Kornel Kisielewicz
显示剩余4条评论

4

有几个原因:

  • 你应该把OpenGL上下文视为一个状态机,任何时候只会有一个活动的上下文。在所有操作前面加上Opengl.whatever并没有什么区别。
  • 速度很快,OpenGL被设计为最小API。
  • 如果它是面向对象的,那么你会用哪种语言编写它?C ++?然后每个人都必须编写复杂的绑定。C更容易包装。

2
amen. C很容易理解,也很容易编写。面向对象绝对不应该成为默认选项。 - Matt Joiner
这是来自一位C++狂热者的话;) - Chris H
在任何时间只能有一个活动上下文的事实,是否会使同时进行两个线程的OpenGL调用变得困难/不可能,因为它们会互相干扰彼此的上下文?鉴于现在多核CPU的普及,这似乎可能是一个问题... - Jeremy Friesner
是的。同一时间只有一个线程可以访问上下文,并且在程序中任何给定时间只能有一个上下文处于活动状态。你想要表达什么意思?它与所提出的问题有什么关系? - Chris H
@Kornel Kisielewicz:当然他们可以编写绑定。这些绑定很可能涉及将c++ api封装到extern c过程中(也就是我们现在拥有的api类型),但这是可能的。 - Grizzly
1
我希望OpenGL更像OpenCV,OpenCV是一块美玉,它使用最少的面向对象特性和极简接口。 - user90843

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