0
votes

I am trying to save the uniform locations of an array, to a std::map in my Shader class.

My vertex shader has an array uniforms to a mat4.

uniform mat4 bone_matrices[32];

In the following code the bone matrices name shows up as bone_matrices[0]. So I am only getting the location for the first array member. [I think the others are sequential.]

class Shader
{
...
private:
    GLuint mi_program;
    std::map<std::string, GLint> m_maplocations;
};


void Shader::mapLocations()
{
  GLint numUniforms = 0;
  const GLenum properties[5] = {GL_BLOCK_INDEX, GL_TYPE, GL_NAME_LENGTH, GL_LOCATION, GL_ARRAY_SIZE};
  glGetProgramInterfaceiv(mi_program, GL_UNIFORM, GL_ACTIVE_RESOURCES, &numUniforms);

  for(int unif = 0; unif < numUniforms; ++unif)
    {
      GLint values[5];
      glGetProgramResourceiv(mi_program, GL_UNIFORM, unif, 5, properties, 5, NULL, values);

      // Skip any uniforms that are in a block.
      if(values[0] != -1)
        continue;

      std::string nameData;
      nameData.resize(values[2]);

    if(values[4] > 1)
        {
         // **have an array here**
        }

      glGetProgramResourceName(mi_program, GL_UNIFORM, unif, nameData.size(), NULL, &nameData[0]);
      std::string name(nameData.begin(), nameData.end() - 1);
      m_maplocations.insert(std::pair<std::string, GLint>(name, values[3]));
    }
}

How can I iterate the bone_matrices array, get their names: bone_matrices[0], bone_matrices[1], ... and locations. Thanks..

1

1 Answers

0
votes

How can I iterate the bone_matrices array, get their names: bone_matrices[0], bone_matrices1, ... and locations.

There is one uniform: bone_matrices. This uniform is an array of basic types, so it is considered a single resource. Each array element has a location, but there is still only one uniform.

If you want to test if a uniform is arrayed, get the size of the uniform using the GL_ARRAY_SIZE property. If this value is greater than 1, then you can then query the location of each array element by a loop.

All that being said:

I am trying to save the uniform locations of an array, to a std::map in my Shader class.

Please don't do this. First, your std::map-based code will not be faster than glGetUniformLocation or glGetProgramResourceLocation. So if you're going to constantly query uniforms by string name, you may as well just use the existing API.

Second, since you're using program resources, a GL 4.3 feature, I have to assume you have access to explicit uniform locations. You should therefore assign uniforms to specific locations in your shader, then you don't have to query anything at all.

Even if you're writing a program that has to work with whatever the user gives you, it's still better for them to provide specific locations.

What I mean is this. Let's say you have an expectation that the user will provide an array of matrices called bone_matrices. So change your expectation to be that the user will provide an array of matrices at some particular uniform location X.

Yes, this means you have to partition out your uniform space. But it's a lot better than running through each shader to query its data. You don't have to have a map from a string to a location; you simply have the location where it expects it to be.