Bartek Banachewicz
Bartek Banachewicz

Reputation: 39380

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

First of all, i don't know if the "key" pattern is accepted as general patter, but some sorts of it have been appearing all over SO recently, so...

What I want to do?

Create shader manipulation class in C++. My issue here particularly focuses on setting uniform values (values sent from C++ to GLSL "directly").

What's the problem?

(Quick explanation, so that people not accustomed to OpenGL can contribute too) - Uniform variables are set by using global glUniform* functions, taking as first parameter the location of the uniform in currently bound shader (int);

So the common usage is:

glBindProgram(myProgramNum);
int Location = glGetUniformLocation(myProgramNum, "myUniformParameterName");
float myValue = 42.f; // arbitrary data
glUniform1f (Location, myValue);

I've created some of the methods I need to encapsulate the above, such as

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);

I've noticed, however, that all these use the glGetUniformLocation(int, const char*). As some of them will be used in realtime, this would cause unnecessary performance overhead.

The first idea

I've thought that I could create two versions of each function - one taking std::string and value, and second int and value, thus allowing faster access.

However, it would make them no better than the pure OpenGL access, since user would still be able to send malicious parameter to them.

The second idea

So, the proper way do to it would be to generate some sort of "Key" object from shader class, containing location of given uniform. It would however need to be linked to specific CShader class instance, because one could generate key in one object and pass it to another, causing unwanted behavior.

And my question is - is something like this possible in C++? Do I have to keep pointer to "parent" object in the key object and test if it's valid parameter every time, or are there any language/Boost features that will allow some sort of syntaxic sugar around it?

What I was able to deduce myself, the key class should be nested in CShader, and had CShader as friend. Also it should declare trivial constructor private, and overload copy-constructor so that copied objects will still be valid keys.

Upvotes: 2

Views: 529

Answers (1)

Luca
Luca

Reputation: 11961

You need only an integer to set an uniform variable. Indeed, instead of calling a bunch of glGetUniformLocation, why don't you cache those values in a std::map<std::string, int>? Querying the map would be faster, isn't it?

Not everything is clear in you question (parent pointer?, malicious values?), but at the end an hypothetical user of a CShader class wants a shortcut for setting up uniform values. Indeed you can query uniforms after shader linkage (using glGetActiveUniform) or you can query uniform and cache uniform location when necessary.

Upvotes: 2

Related Questions