现在,我正在对某种小OpenGL库进行建模,以愚弄图形编程等。因此,我正在使用类来包装特定的OpenGL函数调用,例如纹理创建,着色器创建等,到目前为止,效果很好。
我的问题:
所有OpenGL调用必须由拥有已创建的OpenGL上下文的线程完成(至少在Windows下,每个其他线程将不执行任何操作并产生OpenGL错误)。因此,为了获得OpenGL上下文,我首先创建一个窗口类的实例(只是Win API调用的另一个包装器),最后为该窗口创建OpenGL上下文。这对我来说听起来很合乎逻辑。 (如果我的设计中已经存在一个让您尖叫的缺陷,请告诉我...)
如果要创建纹理或需要OpenGL调用的任何其他对象来进行创建,则基本上可以这样做(例如,称为OpenGL对象的构造函数):
opengl_object()
{
//do necessary stuff for object initialisation
//pass object to the OpenGL thread for final contruction
//wait until object is constructed by the OpenGL thread
}
因此,换句话说,我使用
opengl_object obj;
然后,它在其构造器中将自己放入要由OpenGL上下文线程创建的OpenGL对象队列。 OpenGL上下文线程然后调用一个在所有OpenGL对象中实现的虚函数,该虚函数包含最终创建该对象所需的OpenGL调用。
我真的认为,以这种方式处理该问题会很好。但是,现在,我认为我错了。
情况是,即使到目前为止上述方法都可以很好地工作,但随着类层次结构的深入,我会遇到麻烦。例如(这不是很完美,但它显示了我的问题):
假设,我有一个名为sprite的类,显然,它代表一个Sprite。它具有OpenGL线程自己的创建功能,其中顶点和纹理坐标被加载到图形卡的内存中,依此类推。到目前为止没有问题。
进一步说,我想有两种渲染 Sprite 的方法。一个实例,一个实例。因此,我将得到2个类,sprite_instanced和sprite_not_instanced。两者都是从sprite类派生的,因为它们都是仅以不同方式呈现的sprite。但是,sprite_instanced和sprite_not_instanced在其create函数中需要进一步的OpenGL调用。
到目前为止,我的解决方案(我对此感到非常恐惧!)
我对C++中的对象生成如何工作以及它如何影响虚函数有某种理解。因此,我决定仅使用类Sprite的虚拟创建功能将顶点数据等加载到图形内存中。然后,sprite_instanced的虚拟创建方法将进行准备以渲染该实例实例。
所以,如果我想写
sprite_instanced s;
首先,调用sprite构造函数,并在进行一些初始化之后,构造线程将对象传递给OpenGL线程。此时,传递的对象仅仅是普通的 Sprite ,因此将调用sprite::create,而OpenGL线程将创建普通的 Sprite 。之后,构造线程将调用sprite_instanced的构造函数,再次进行一些初始化,然后将该对象传递给OpenGL线程。但是这次是sprite_instanced,因此将调用sprite_instanced::create。
因此,如果我对上述假设是正确的,那么至少在我的情况下,一切都会按预期进行。我花了最后一个小时来阅读有关从构造函数调用虚拟函数以及v表如何构建等的信息。我已经进行了一些测试来检验我的假设,但这可能是特定于编译器的,因此我不完全依赖它们。此外,它感觉就像可怕的骇客一样可怕。
另一个解决方案
另一种可能性是在OpenGL线程类中实现工厂方法来解决这一问题。因此,我可以在这些对象的构造函数中进行所有OpenGL调用。但是,在那种情况下,我将需要很多功能(或一种基于模板的方法),并且当OpenGL线程要做的事情比需要做的更多时,感觉就像是潜在的渲染时间损失。
我的问题
可以按照我上面描述的方式来处理吗?还是我应该扔掉那些东西然后做其他事情?
最佳答案
确实,无论何时您开始写“Objectname::Create”,都停下来思考:“我真的应该使用Factory对象。”
关于c++ - OpenGL对象创建,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7590646/