假设我有一个 Shader 类,我想要一个 Uniform 函数将我传递的数据发送到加载的 Shader 程序
class Shader{
unsigned int programid;
template<typename Type>
void Uniform(unsigned int location, Type object){
//Some logic that passes the type data to the uniform using glUniform[?]()
}
}
我将如何编写 Uniform 函数(使用 C++ 中的模板)来接受任何类型(原始或对象)并将其传递给着色器?
例子:
GLSL:统一 float ;
C++:shader.Uniform(somefloat);
GLSL:uniform vec3 Position;
C++:
template<typename Type, size_t Size>
Vector{ Type data[Size]; }
Vector<float, 3> position = {0.0f, 1.0f, 1.0f}
shader.Uniform(position);
GLSL:
struct Light
{
vec3 position;
vec4 rotation;
float luminosity;
bool status;
};
uniform Light object;
C++:
struct Light {
Vector<float, 3> position;
Vector<float, 4> rotation;
float luminosity;
bool status;
}
Light object = {{1.0f,0.0f,0.0f},{0.0f,0.0f,0.0f},0.75f,true};
shader.Uniform(object);
最佳答案
首先,C++ 和 GLSL 是静态类型的语言,而不是像 JavaScript 或 Python 那样的动态类型。所以没有实际的方法来编写接受任何类型的 C++ 函数。您的 C++ 模板函数的作用实质上是文本替换。每次 C++ 编译器看到使用的模板(例如“Vector”)时,它都会采用原始模板声明并制作一个新拷贝,其中“Type”和“Size”分别替换为“float”和“3”。并且编译器生成一个唯一的错位名称以防止链接器错误,例如 __Vector_TypeFOO_SizeBAR...
(为了完整起见,是的,可以使用 union 和/或指针转换在 C/C++ 中实现您自己的动态类型化。但是由于您不能在 GLSL 中执行其中任何一项,因此它无助于回答问题。)
因此,由于 GLSL 没有模板来进行文本替换,您必须自己实现它。从文件或其他任何地方加载着色器的源代码。在将其传递给 glCompileShader 之前,使用您最喜欢的字符串处理库将实际字符串插入到占位符文本中。
例如,在你的着色器中你可以这样写:
<TYPE><SIZE> position;
你的主程序会做类似的事情
src = loadShaderCode("example.template");
src.replace("<TYPE>", "vec");
src.replace("<SIZE>", "3");
shader = compileShader(src, ...);
希望这对您有所帮助。
关于c++ - 对于 OpenGL 着色器,您将如何在 C++ 中编写接受所有类型的统一函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58864129/