当人们提到“状态机”时,并不清楚他们的意思是什么,因为他们从不解释相反的是什么。因此,我将从 OpenGL“状态机”与当前 D3D“非状态机”的角度来一般性和具体地讨论它。
OpenGL 和 Direct3D 都使用全局状态。每个渲染命令都需要您设置一堆状态。
为了在这两个 API 中进行渲染,您必须设置一堆全局状态。您必须设置要使用的着色器。您必须设置要使用这些制服的当前参数。如果您使用纹理,则需要对其进行设置。您需要设置当前视口参数。等等。
的原因this某种“状态机”很简单:这就是硬件通常的工作方式。
每个状态位代表 GPU 中的一些寄存器。那些寄存器是状态。需要加载着色器才能渲染。您需要设置视口寄存器。您需要设置您正在使用的纹理寻址寄存器。等等。因此,API 是状态机,因为GPU是一个状态机。
You could想象一下这将通过渲染命令来完成。但只要看看您需要传递多少个对象即可。你必须传递一堆着色器、一堆纹理、顶点数据、帧缓冲区、视口设置、混合设置等。
因此,API 让您执行 GPU 执行的操作。你事先设置好所有这些东西。
另外,这使得 APIfaster。为什么?因为现在 API 知道您正在使用什么状态。例如,如果您想使用不同的纹理渲染一个网格的不同部分,则可以保持帧缓冲区、视口、顶点数据等全部相同。它们之间唯一需要更改的是使用哪些纹理。
如果您使用某种带有数十个参数的大型绘制调用,那么现在 API 必须查看每个参数以查看它是否与您上次绘制调用相同。如果不是,则必须更新 GPU 寄存器。
现在来说说OpenGL和D3D的区别。在这种情况下,问题的区别在于他们如何对待对象。
D3D 是基于对象的,因为修改对象的函数将对象作为参数。此外,大多数 D3D 对象都是不可变的;一旦创建它们,您就无法更改它们的大部分设置。一旦创建了特定尺寸、格式等的纹理,就完成了。如果不删除对象并创建新对象,则无法使用不同的大小/格式/等重新分配它。
OpenGL 是基于状态的。这意味着(大多数情况下)修改对象的 OpenGL 函数不会将其操作的对象作为参数。
这与其说是一种“设计”,不如说是 OpenGL 严格遵守向后兼容性。 OpenGL 中的对象只是全局状态的片段;这就是它们的定义方式。为什么?
因为最初,早在 OpenGL 1.0 中,没有物体(除了显示列表)。是的,甚至没有纹理对象。当他们认为这是愚蠢的并且他们需要对象时,他们决定以向后兼容的方式实现它们。每个人都已经在使用在全局状态下运行的函数。所以他们只是说通过绑定一个对象,你可以覆盖全局状态。那些曾经改变全局状态的函数现在改变对象的状态。
通过这种方式,他们可以将对象引入 API,而无需引入一堆仅适用于对象的新函数。因此,以前工作的代码只需进行非常小的调整就可以处理对象,而不是强制对代码进行重要的重写。这也意味着,如果他们需要引入新的纹理功能,他们会使用and没有物体。因此,它既向后又向前兼容。
大多数 OpenGL 对象都是这样工作的 http://www.opengl.org/wiki/OpenGL_Object:如果你想改变它们,你必须绑定它们,然后修改“全局”状态。