Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
存储OpenGL状态 假设我正在尝试在C++上制作一个小型OpenGL图形引擎。我已经读到,通过glGet*函数访问opengl状态可能会非常昂贵(而访问opengl状态似乎是一项常见的操作),强烈建议将opengl状态的副本存储在具有快速读/写访问权限的某处_C++_Opengl - Fatal编程技术网

存储OpenGL状态 假设我正在尝试在C++上制作一个小型OpenGL图形引擎。我已经读到,通过glGet*函数访问opengl状态可能会非常昂贵(而访问opengl状态似乎是一项常见的操作),强烈建议将opengl状态的副本存储在具有快速读/写访问权限的某处

存储OpenGL状态 假设我正在尝试在C++上制作一个小型OpenGL图形引擎。我已经读到,通过glGet*函数访问opengl状态可能会非常昂贵(而访问opengl状态似乎是一项常见的操作),强烈建议将opengl状态的副本存储在具有快速读/写访问权限的某处,c++,opengl,C++,Opengl,我目前正在考虑将opengl状态存储为某种适当类型的全局线程\局部变量。那设计有多糟糕?有什么陷阱吗?如果你想坚持OpenGL的设计(你的上下文指针可以被认为是“线程本地的”),我想这是一个有效的选择。。。显然,为了使状态副本与当前上下文的状态保持同步,您需要完全控制所有OpenGL调用 我个人更喜欢使用一个“OpenGLState”类包装感兴趣的OpenGL状态,该类包含一组可设置/可获取的属性,每个属性映射到状态的某个部分。然后还可以避免两次设置相同的状态。您可以使它成为THEADLY本地,

我目前正在考虑将opengl状态存储为某种适当类型的全局线程\局部变量。那设计有多糟糕?有什么陷阱吗?

如果你想坚持OpenGL的设计(你的上下文指针可以被认为是“线程本地的”),我想这是一个有效的选择。。。显然,为了使状态副本与当前上下文的状态保持同步,您需要完全控制所有OpenGL调用

我个人更喜欢使用一个“OpenGLState”类包装感兴趣的OpenGL状态,该类包含一组可设置/可获取的属性,每个属性映射到状态的某个部分。然后还可以避免两次设置相同的状态。您可以使它成为THEADLY本地,但我不能(VisualC++只支持TyRead本地POD类型)。 您需要非常小心,因为某些OpenGL调用会间接更改上下文状态中看似不相关的部分。例如,glDeleteTextures会将已删除纹理的任何绑定重置为0。此外,一些工具包在更改背后的OpenGL状态方面非常“有用”(例如,OSX上的QtOpenGLContext在成为当前视口时会为您更改视口)。

既然您只能(合理地)使用带有一个线程的GL上下文,为什么需要线程本地?是的,您可以在不同的时间在不同的线程中设置当前上下文,但这不是一个明智的设计


通常会有一个上下文和一个线程访问它。在极少数情况下,您将有两个上下文(通常是共享的)和两个线程。在这种情况下,您可以简单地将希望保存的任何附加状态放入上下文类中,其中每个实例仅由一个线程拥有

但大多数情况下,您不需要明确地“记住”状态。所有状态都有详细记录的初始状态,只有在您更改它们时才会更改(例外情况是“超级智能”工具包所做的更改,但在这种情况下存储错误的状态也没有帮助)

您通常会尝试将状态批处理在一起,并使用一组状态执行许多“类似”的绘制调用,原因是状态更改会使管道暂停,需要在下一次绘制调用之前进行昂贵的验证。
所以,从默认值开始,在绘制批处理之前,设置所有需要非默认值的内容。然后更改下一批需要不同的内容


如果您不必费心去挖掘规格中的默认值并保持跟踪,那么您可以随时冗余地设置所有内容。然后在GDebugger中运行您的应用程序,它将告诉您哪些状态更改是多余的,这样您就可以消除它们。

我知道opengl状态更改不太明显,我必须非常仔细地阅读文档:)几乎让您想要创建阴影层“每个实例都由一个线程拥有。”这就是为什么它应该是线程本地的,不是吗?我没有使用“真正的”3D引擎的经验,但这似乎有点乐观……或者在使用它后将每个状态重新设置为默认状态(浪费时间,而且可能会加倍,因为您可能会在下一次图形调用中重新应用相同的状态)或者您假设知道代码中任何一点的OpenGL状态。如果您不想要一个巨大的“渲染”函数,您该怎么办?@lisyarus:上下文是“神奇的线程本地”上下文"单独。创建上下文的线程拥有它,除非另一个线程调用
MakeCurrent
。来自另一个线程的任何其他调用都将失败。但是,将上下文设置为另一个线程的当前值是一个非常慢的函数。因此,尽管可能,实际上,您只能对一个线程使用一个上下文。如果只有一个线程访问不管怎么说,让每一点信息都成为线程本地是没有什么好处的。@Damon:我知道opengl上下文本身就是线程本地的。我说的是让存储的opengl状态线程成为本地的,这样真正的存储状态只能由拥有上下文的线程访问。经过一些考虑,我意识到这样,每个线程都会有一个opengl状态的副本,而只有一个线程会使用opengl,因此将其设为本地线程可能是一个糟糕的设计。@heinrichj:这取决于,但通常你不会一直更改那么多状态。在“真实”的情况下正如您所说的3D引擎,人们通常将所有内容与一个“关键点”一起放入一个容器中,该“关键点”根据渲染过程和状态更改的重要性进行区分,排序,并按顺序绘制排序后的命令。其他人只需手工操作,例如绘制地形,然后绘制所有房屋,然后绘制所有树木(实例),然后是动画角色。您绘制的对象组在状态上仍然非常相似(可能纹理不同,但基本上就是这样)。您不希望为此使用线程本地存储。状态机是每个渲染上下文的,因此请为渲染上下文编写一个精简包装,并在一天内结束。您可以根据需要在包装中为状态操作添加尽可能多或尽可能少的复杂度。您可能需要的唯一线程本地存储是一个变量,用于跟踪所创建的上下文它在当前线程中处于活动状态,即使这样也太过分了,因为所有的窗口系统API都有一个可以为此调用的函数。