GLSL: How should i store and keep track of uniform/attribute locations?
At the moment i just do:
someuniform1 = glGetUniformLocation(MyShaderName, "someuniform1");
someattribute1 = glGetAttribLocation(MyShaderName, "someattribute1");
But this method seems annoyingly repetitive, so i thought of using std::map:
Shaders[MyShaderName].Uniforms["someuniform1"] = glGetUniformLocation(MyShaderName, "someuniform1");
Shaders[MyShaderName].Attributes["someattribute1"] = glGetAttribLocation(MyShaderName, "someattribute1");
// i could add a开发者_开发知识库 function to remove the repetition of the two strings at both sides.
Is there any smarter/faster way of doing this? (to reduce repetition as much as possible).
--
Edit: I was thinking more about this idea, and i thought, wouldnt it be great if i just read the glsl source files, parse the uniform/attributes and set to my map automatically, without me need to write anything else than the glsl source!? Is this how the big boys do it?
Edit2: I am now parsing the GLSL shader files successfully, and using the std::map
method, i use single function call with one string param to get the address for uniforms/attributes at current enabled shader. in case i need more performance, i will cache the std::map
calls to other variables. But i would like to know if i am on the right track here... so please, any comments appreciated.
Enumerate shader program's uniforms by GetActiveUniform
, then store them in your map.
Edit: The purpose.
- No repetition in code. Uniform names as constants appear only in places where you want to access them.
- Early-stage semantics mismatches checks. When you gather information from GL about uniforms you know exactly what type of values it expects. So when the actual value is passed, you can check whether the client supplied a correct type/size of the value. These checks may save you a lot of time of debugging in case of some edge scenario when OpenGL driver decides to be "smart".
glGetProgramiv
, glGetActiveUniform
and glGetActiveAttrib
can be used to get information about the used uniforms in a shader program. The information can be retrieved at any time after the program has been linked, glLinkProgram
:
glGetProgramiv( MyShaderName, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxUniformNameLen )
returns the length of the longest active uniform variable name (including the null termination character)glGetProgramiv( MyShaderName, GL_ACTIVE_UNIFORMS, &noOfUniforms )
returns the number of active uniform variables.glGetActiveUniform
returns information about an active uniform variable inclluding the name of the uniform.glGetProgramiv( MyShaderName, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxAttribNameLen )
returns the length of the longest vetex attribute name (including the null termination character)glGetProgramiv( MyShaderName, GL_ACTIVE_ATTRIBUTES, &noOfAttributes )
returns the number of the active attributes.glGetActiveAttrib
returns information about an active vetrtex attribute inclluding the name of the attribute.
Use the information from the functions above to find all uniform and attribute names within a program. Ask each uniform for its location and each attribute for its index, by their names. See the code snippet below:
GLint maxUniformNameLen, noOfUniforms;
glGetProgramiv( MyShaderName, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformNameLen );
glGetProgramiv( MyShaderName, GL_ACTIVE_UNIFORMS, &noOfUniforms );
GLint maxAttribNameLen, noOfAttributes;
glGetProgramiv( MyShaderName, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxAttribNameLen );
glGetProgramiv( MyShaderName, GL_ACTIVE_ATTRIBUTES, &noOfAttributes );
GLint read, size;
GLenum type;
std::vector< GLchar >unifN( maxUniformNameLen, 0 );
for ( GLint i = 0; i < noOfUniforms; ++ i )
{
glGetActiveUniform(Object(), i, maxUniformNameLen, &read, &size, &type, unifN.data());
Shaders[ MyShaderName ].Uniforms[ unifN.data() ] =
glGetUniformLocation( MyShaderName, unifN.data() );
}
std::vector< GLchar >attrN( maxAttribNameLen, 0 );
for ( GLint i = 0; i < noOfAttributes; ++ i )
{
glGetActiveAttrib(Object(), i, maxAttribNameLen, &read, &size, &type, attrN.data());
Shaders[ MyShaderName ].Attributes[ attrN.data() ] =
glGetAttribLocation( MyShaderName, attrN.data() );
}
精彩评论