OpenGL State Sets
OpenGL State Sets
这与其说是一个OpenGL问题,不如说是一个c++组织问题。
我将有一个简单的场景图(一个n-tree),其中的节点(为了这个问题的缘故)都将渲染一些几何形状。更具体地说,它们在draw()
方法中都有一些OpenGL绘制命令。
出于优化的原因,我想将相似的对象批处理在一起并一次绘制它们。出于这个原因,我想用一种方式来表达我称之为OpenGL的"状态集"。状态集只是一堆OpenGL绑定,或者在调用X对象上的draw之前设置的命令,然后取消设置。
因此一个状态集至少有set()
和unset()
,在使用该状态集的节点绘制命令之前和之后,渲染系统将调用该状态集。
我的问题是如何表达这些状态集?当然,一堆函数可以做到这一点,但我宁愿能够命名一组并回忆起它。如节点A的状态集为LIGHTING_AND_SHADOW
,节点B的状态集为CEL_SHADING
。
因此,创建一个称为stateSet
的抽象类,它本质上是set()
和unset()
方法的接口,并从它继承每个状态集似乎是一个好主意。但是,它需要创建一堆对象来获得一个名称。似乎有更好的办法。
理想情况下,我还希望有一个可以轻松召回的所有stateSets
的列表。例如,在渲染开始之前,能够按stateSet
对场景图中的所有节点进行排序是很好的。
任何想法?
您可以使用单例模式实现您的状态。然后,另一个单例状态跟踪器类管理这些状态类的实例,并仅在状态尚未设置时设置状态。下面是一个粗略的实现。这应该会给你一个关于如何去做的想法:
class SingletonStateClass1 {
public:
static SingletonStateClass1* getInstance() {
if(! instanceFlag) {
single = new SingletonStateClass1();
instanceFlag = true;
return single;
}
else {
return single;
}
}
void set() {
// Do setting stuff
}
void unset() {
// Do unsetting stuff
}
~SingletonStateClass1() {
instanceFlag = false;
}
private:
static bool instanceFlag;
static SingletonStateClass1 *single;
SingletonStateClass1() {} //private constructor
};
bool SingletonStateClass1::instanceFlag = false; //needs to be set so that the first call to getInstance() works ok.
//ASSUME THERE IS ANOTHER CLASS WITH SIMILAR DESIGN, NAMED: SingletonStateClass2
class SingletonStateTracker {
public:
static SingletonStateTracker* getInstance() {
if(! instanceFlag) {
single = new SingletonStateTracker();
state1 = SingletonStateClass1::getInstance();
state2 = SingletonStateClass2::getInstance();
instanceFlag = true;
isSetState1 = false;
isSetState2 = false;
return single;
}
else {
return single;
}
}
// Only setting a state unsets the other states
void set1() {
if (!isSetState1) {
if (isSetState2) {
state2->unset();
isSetState2 = false;
}
state1->set();
isSetState1 = true;
}
}
void set2() {
if (!isSetState2) {
if (isSetState1) {
state1->unset();
isSetState1 = false;
}
state2->set();
isSetState2 = true;
}
}
private:
static bool instanceFlag;
static bool isSetState1;
static bool isSetState2;
static SingletonStateTracker *single;
static SingletonStateClass1 *state1;
static SingletonStateClass2 *state2;
SingletonStateTracker() {} //private constructor
};
bool SingletonStateTracker::instanceFlag = false; //needs to be set so that the first call to getInstance() works ok.
class DrawableObject1 {
public:
DrawableObject1() {
tracker = SingletonStateTracker::getInstance();
}
void draw() const
{
tracker->set1();
//DO YOUR OBJECT SPECIFIC OPENGL DRAW STUFF HERE
}
private:
SingletonStateTracker* tracker;
};
class DrawableObject2 {
public:
DrawableObject2() {
tracker = SingletonStateTracker::getInstance();
}
void draw() const
{
tracker->set2();
//DO YOUR OBJECT SPECIFIC OPENGL DRAW STUFF HERE
}
private:
SingletonStateTracker* tracker;
};
/* Below two classes show a crude usage of the above design */
class Scene {
// ... other stuff ...
public:
DrawableObject1 obj1a;
DrawableObject1 obj1b;
DrawableObject2 obj2;
// ... other stuff ...
};
class Viewer {
// ... other stuff ...
public:
void draw() {
scene->obj1a.draw(); //This call unsets state2, sets state1
scene->obj1b.draw(); //This call does not set any state since state1 is already set
scene->obj2.draw(); //This call unsets state1, sets state2
}
private:
Scene* scene;
// ... other stuff ...
};
注意上面的设计是非常简单的。正如您在问题中提到的,您可以有多个状态类来继承一个公共接口。关键是要有一个追踪者(又名追踪者)。(Manager)类,对象通过它来设置状态。Tracker类的工作是消除对一个状态的不必要设置,如果它已经设置,并且取消当前设置的其他状态。
因此,创建一个名为
stateSet
的抽象类本质上是set()
和unset()
方法的接口从它继承每个状态集似乎是一个好主意。但是,它需要创建一堆对象来获得一个名称本质上。
假设的抽象类实现通过虚函数表工作,虚函数表通常作为函数指针数组实现。在这种情况下,您将实例化的显然毫无意义的对象确实持有有意义的状态-那些函数指针。
作为创建两个函数指针的多个数组的替代方法,也许您应该创建两个函数指针数组,在数组中命名索引,保留最后使用的索引,并在间接通过数组之前让stateSet(uint state_name)
检查state_name
是否不同。我建议通过static
关键字对其他编译单元隐藏全局状态。
这种方法提供了更少的自动安全性——从语义上讲,没有什么可以阻止你将任何整数传递给stateSet(uint)
,并且没有对原始数组的范围检查,除非你自己把它放在那里。
这两个选项在其他方面基本上非常相似;
- 递归模板化函数不能分配给具有常量限定类型"const tt &"的变量"state"
- 如何修复" State Error (active) E0513 a value of type "const wchar_t *" cannot be assigned to an entity o
- C 是否具有对两个STD :: sets,vectors等进行三角比较的标准方法
- 为什么SADWinowSize_slider的跟踪栏的值在分配给 sbm->state 时变为 0。SADWindowSize,在我的代码中
- C++为所有 std::sets 编写泛型函数
- "State pattern" vs "one member function per state" ?
- ODBC 错误"String data, right truncation State code: 22001"与 SQL Server 数据库
- 为什么要iStream ::获得sets failbit和eofbit在一起
- Qt state machine
- 如何确定State模式的状态
- 将openMP与SETS结合使用
- C++ 中的'retain state'是什么意思?
- 如何在Flash Player中触发"running state"?
- State of a QTcpSocket
- GCC"__attribute__((纯))"关于"input state"吸气剂方法的建议 - 正确吗?
- 如何使用boost::graph算法与listS,setS作为顶点/边缘容器
- sets and xmemory in C++
- 对State::State(State)没有匹配的函数调用
- 使用分隔符通过'Street; City; State; Country'将每个区域存储到不同的变量中来解析地址
- OpenGL State Sets