我正在编写一个OpenGL C ++包装器。这个包装器旨在减少复杂和易错的使用。
例如,我目前希望用户只需关注OpenGL Context
。为此,我写了一个课程gl_texture_2d
。众所周知,OpenGL texture
基本上有以下操作:
repeat
/ mirror
,依此类推min
/ mag
filter
设为linear
基于此,我们有:
class gl_texture_2d
{
public:
void mirror_u(); // set u parameter as mirror model
void mirror_v(); // set v parameter as mirror model
void linear_min_filter(); // ...
void linear_mag_filter(); // ...
};
嗯,我们知道,只有当the handle of OpenGL texture object
当前绑定到OpenGL context
时,我们才能执行这些操作。
假设我们有一个函数执行此操作:
void bind(GLuint htex); //实际上是相关GL函数的别名
好的,我们现在可以将gl_texture_2d
用法设计为:
gl_texture_2d tex;
bind(tex.handle());
tex.mirror_u();
tex.linear_min_filter();
unbind(tex.handle());
它确认了GL的逻辑,但它失去了包装的重要性,对吗?作为用户,我希望像以下一样操作:
gl_texture_2d tex;
tex.mirror_u();
tex.linear_min_filter();
为实现这一目标,我们必须实现以下功能:
void gl_texture_2d::mirror_u()
{
glBindTexture(GL_TEXTURE_2D, handle());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glBindTexture(GL_TEXTURE_2D, 0);
}
始终在内部执行绑定操作,确保操作有效。但是成本很高!
代码:
tex.mirror_u();
tex.mirror_v();
将扩展为一对无意义的绑定/解除绑定操作。
有没有任何机制可以让编译器知道:
bind(b)
紧跟bind(a)
后,bind(a)
可以删除; bind(a)
在一个区块中出现两次,则最后一个没有效果。答案 0 :(得分:1)
如果您正在使用pre-DSA OpenGL,并且您绝对必须使用自己的API直接将OpenGL调用,那么用户可能必须知道整个绑定到编辑的事情。毕竟,如果他们为了渲染目的绑定了一个纹理,那么他们会尝试修改一个,它可能会损坏当前的绑定。
因此,您应该将绑定到编辑的概念直接构建到API中。
也就是说,纹理对象(BTW, 仅限于2D纹理)实际上不应该具有修改它的功能,因为你不能修改OpenGL纹理而不绑定它(或者没有DSA,你真的应该学习)。它不应该有mirror_u
等等;这些函数应该是binder对象的一部分:
bound_texture bind(some_texture, tex_unit);
bind.mirror_u();
...
bound_texture
的构造函数将some_texture
绑定到tex_unit
。它的成员函数将修改该纹理(注意:他们需要调用glActiveTexture
以确保没有人更改活动纹理单元。)
bound_texture
的析构函数应该自动解除绑定纹理。但是你应该有一个release
成员函数来手动取消绑定它。
答案 1 :(得分:0)
您无法在编译级别执行此操作。相反,如果你真的担心这些错误的时间成本,那么管理者对象可能就是这样:
class state_manager {
GLuint current_texture;
/*Maybe other stuff?*/
public:
void bind_texture(gl_texture_2d const& tex) {
if(tex.handle() != current_texture) {
current_texture = tex.handle();
glBindTexture(/*...*/, current_texture);
}
}
};
int main() {
state_manager manager;
/*...*/
gl_texture_2d tex;
manager.bind(tex);
manager.bind(tex); //Won't execute the bind twice in a row!
/*Do Stuff with tex bound*/
}