将 glUniform 函数作为参数传递 (C++)

Passing glUniform functions as parameter (C++)

我目前正在编写一个 openGL 着色器 class。我没有使用函数来设置每个统一类型,而是尝试将统一函数(例如 glUniform1f)作为参数传递。

我目前的尝试看起来像这样:

template <typename T1> 
void Shader::setUniform(void (* fnc)(GLint, T1), const GLchar *name, const T1 value1)
{
    fnc(getUniformLocation(name), value1);
}

调用

shader.setUniform<GLfloat>(*glUniform1f, "test", 5);

但是,我经常遇到转换错误,例如:

cannot convert argument 1 from 'void (__stdcall *)(GLint,GLfloat)' to 'void (__cdecl *)(GLint,GLfloat)'

是否有可能使它按预期工作?

谢谢

注意:如果这很重要,我正在使用 GLEW 和 glfw

来自 OpenGL 加载库的函数指针(特别是那些 return 直接从 DLL 加载的函数)有时会使用与常规函数指针不同的调用约定进行注释。

此类函数指针不可相互转换。

有两种方法可以处理这个问题。您可以使用不同的 OpenGL 加载库,它处理使用标准调用约定的函数指针(本质上,隐藏它加载的实际指针)。例如,在 my glLoadGen loader, if you use the func_cpp 生成器样式中,所有函数都是常规 C++ 函数。

否则,您将不得不更改函数指针在接口中的声明方式,以匹配加载程序的工作方式。例如,如果您使用 GLEW,则必须执行如下操作:

void Shader::setUniform(void (GLAPIENTRY* fnc)(GLint, T1), const GLchar *name, const T1 value1)

你也可以在仿函数的类型上模板化函数,让你自己不用处理函数指针语法、调用约定等。这个版本将接受所有可以用记录的参数调用的东西(函数、函数对象、lambda 等) .).它同时是主要的优势和劣势。通过概念进行类型限制有望在下一版本的 C++ 标准中引入。

template <typename F, typename T1>
// requires: F callable with parameter types GLint, T1
void Shader::setUniform(F fnc, const GLchar* name, const T1 value1) {
    fnc(getUniformLocation(name), value1);
}

int main() {
    ...
    shader.setUniform(glUniform1f, "foo", 3.14f);
}

我同意评论,这并没有太大变化,因为用户仍然键入函数名称和所有参数。 更多 "object oriented" 方法可能是为制服引入模板化 class 并根据参数类型对其进行专门化(数量不多)。