Reputation: 188
So say I have a Shader class and I want to have a Uniform function that sends the data I pass to the loaded Shader program
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[?]()
}
}
How would I write the Uniform function (using templates in C++) to accept any type (primitive OR object) and pass it to the Shader?
Examples:
GLSL: uniform float Amount;
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);
Upvotes: 0
Views: 1319
Reputation: 2516
First, C++ and GLSL are statically typed languages, not dynamically typed like JavaScript or Python. So there is no actual way to write a C++ function that accepts any type. What your C++ template function does is, essentially, a text substitution. Every time the C++ compiler sees the template used, eg "Vector", it takes the original template declaration and makes a new copy with "Type" and "Size" replaced by "float" and "3" respectively. And the compiler generates a unique mangled name to prevent linker errors something like __Vector_TypeFOO_SizeBAR...
(For sake of completeness, yes it's possible to implement your own dynamic typing in C/C++ with unions and/or pointer casts. But since you can't do either of those in GLSL, it doesn't help answer the question.)
So, since GLSL doesn't have templates to do the text replacement, you'll have to implement it yourself. Load the source of your shader from file or whatever. Before you pass it to glCompileShader, use your favourite string processing library to insert actual strings into placeholder text.
Eg in your shader you could write something like:
<TYPE><SIZE> position;
and your main program would do something like
src = loadShaderCode("example.template");
src.replace("<TYPE>", "vec");
src.replace("<SIZE>", "3");
shader = compileShader(src, ...);
Hope this helps.
Upvotes: 2