将 glUniform 函数作为参数传递 (C++)
Posted
技术标签:
【中文标题】将 glUniform 函数作为参数传递 (C++)【英文标题】:Passing glUniform functions as parameter (C++) 【发布时间】:2016-10-11 17:14:18 【问题描述】:我目前正在编写一个 openGL 着色器类。我没有尝试设置每个统一类型的函数,而是尝试将统一函数(例如 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 不熟悉,但您是否尝试过通过std::function
而不是函数指针来传递函数?
还没有,等一下。
一个更好的问题是......你为什么要这样做?您的目标似乎是为glUniform
系列函数提供模板包装器。但是你这样做的方式需要用户同时传递类型(GLfloat
)和函数指针,它......已经具有类型。必须有更好的方法来做你似乎想做的事情。
基本思想是拥有一个单一的功能,而不是太多,例如void setUniform1f(const GLchar *name, float value); void setUniform1i(const GLchar *name, int value);
@LevyEhrstein:但你没有实现这一目标。您仍然需要输入您要调用的函数的名称。用户仍然必须记住他们真正想要调用的函数。您并没有隐瞒用户提供“太多”功能的事实。那么 API 有什么好处呢?
【参考方案1】:
来自 OpenGL 加载库的函数指针(尤其是那些返回直接从 DLL 加载的函数)有时会使用与常规函数指针不同的调用约定进行注释。
这样的函数指针不能相互转换。
有两种方法可以处理这个问题。您可以使用不同的 OpenGL 加载库,它处理使用标准调用约定的函数指针(本质上,隐藏它加载的实际指针)。例如,在my glLoadGen loader 中,如果您使用func_cpp
生成器样式,则所有函数都将是常规C++ 函数。
否则,您将不得不更改函数指针在接口中的声明方式以匹配加载程序的工作方式。例如,如果您使用 GLEW,则必须执行以下操作:
void Shader::setUniform(void (GLAPIENTRY* fnc)(GLint, T1), const GLchar *name, const T1 value1)
【讨论】:
【参考方案2】:您也可以在仿函数的类型上模板化函数,让自己免于处理函数指针语法、调用约定等。这个版本将接受可以使用文档化参数调用的所有内容(无论是函数、函数对象、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);
我同意 cmets 的观点,这并没有太大的变化,因为用户仍然键入函数名称和所有参数。 更“面向对象”的方法可能是为制服引入一个模板类,并根据参数类型对其进行专门化(数量不多)。
【讨论】:
以上是关于将 glUniform 函数作为参数传递 (C++)的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 swig 将 python 类实例作为 c++ 函数的参数传递?