2

首先,我不知道“关键”模式是否被接受为一般模式,但最近它已经出现在 SO 各处,所以......

我想做的事?

在 C++ 中创建着色器操作类。我在这里的问题特别关注设置统一值(从 C++“直接”发送到 GLSL 的值)。

有什么问题?

(快速解释,让不习惯OpenGL的人也可以贡献) - 使用全局glUniform*函数设置uniform变量,第一个参数是uniform在当前绑定着色器中的位置(int);

所以常见的用法是:

glBindProgram(myProgramNum);
int Location = glGetUniformLocation(myProgramNum, "myUniformParameterName");
float myValue = 42.f; // arbitrary data
glUniform1f (Location, myValue);

我已经创建了一些我需要封装上述内容的方法,例如

void SetUniform1f (std::string const& name, float a);
void SetUniformVector3 (std::string const& name, CVector3 const& vec);
void SetUniformMatrix4 (std::string const& name, CMatrix4 const& mat);

但是,我注意到所有这些都使用glGetUniformLocation(int, const char*). 由于其中一些将实时使用,这将导致不必要的性能开销。

第一个想法

我认为我可以为每个函数创建两个版本——一个是 takestd::string和 value,第二个是intvalue,从而可以更快地访问。

但是,这不会比纯粹的 OpenGL 访问更好,因为用户仍然可以向它们发送恶意参数。

第二个想法

因此,正确的做法是从着色器类生成某种“Key”对象,其中包含给定制服的位置。然而,它需要链接到特定的 CShader 类实例,因为可能会在一个对象中生成密钥并将其传递给另一个对象,从而导致不需要的行为。

我的问题是——在 C++ 中这样的事情可能吗?我是否必须在关键对象中保留指向“父”对象的指针并测试它是否每次都是有效参数,或者是否有任何语言/Boost 功能允许围绕它使用某种语法糖?

我自己能够推断出,关键类应该嵌套在 CShader 中,并且有 CShader 作为朋友。它还应该将普通构造函数声明为私有,并重载复制构造函数,以便复制的对象仍然是有效的键。

4

1 回答 1

2

您只需要一个整数来设置一个统一变量。确实,与其调用一堆glGetUniformLocation,不如将这些值缓存在 a 中std::map<std::string, int>?查询map会更快,不是吗?

您的问题并非一切都清楚(父指针?,恶意值?),但最后一个假设的CShader类用户想要一个设置统一值的快捷方式。实际上,您可以在着色器链接后查询统一(使用glGetActiveUniform),或者您可以在必要时查询统一和缓存统一位置。

于 2012-06-10T22:42:53.890 回答