是否可以在着色器类中使用"Key"设计模式?

Is using "Key" design pattern in shader class possible?

本文关键字:Key 设计模式 是否      更新时间:2023-10-16

首先,我不知道"键"模式是否被接受为一般模式,但最近SO上到处都出现了某种模式,所以......

我想做什么?

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

怎么了?

(快速解释,以便不习惯OpenGL的人也可以做出贡献)-统一变量是使用全局glUniform*函数设置的,将当前绑定着色器中均匀的位置作为第一个参数(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*)。由于其中一些将实时使用,这将导致不必要的性能开销。

第一个想法

我认为我可以为每个函数创建两个版本 - 一个采用std::string和值,第二个int和值,从而允许更快的访问。

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

第二个想法

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

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

我能够推断出,密钥类应该嵌套在CShader中,并且有CShader作为朋友。此外,它还应该声明简单的构造函数私有,并重载复制构造函数,以便复制的对象仍然是有效的键。

您只需要一个整数即可设置统一变量。事实上,与其调用一堆glGetUniformLocation,为什么不将这些值缓存在std::map<std::string, int>中呢?查询map会更快,不是吗?

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