GLSL: Как я должен хранить и отслеживать местоположения единообразных/атрибутов?

В данный момент я просто делаю:

someuniform1 = glGetUniformLocation(MyShaderName, "someuniform1");
someattribute1 = glGetAttribLocation(MyShaderName, "someattribute1");

Но этот метод кажется раздражающе повторяющимся, поэтому я подумал об использовании 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.

Есть ли более умный/быстрый способ сделать это? (чтобы максимально сократить повторение).

-

Изменить: Я думал больше об этой идее, и я подумал, не было бы здорово, если бы я просто прочитал исходные файлы glsl, проанализировал унифицированные/атрибуты и автоматически установил на свою карту, без мне нужно написать что-нибудь еще, кроме источника glsl!? Как это делают большие мальчики?

Edit2: Теперь я разбираю файлы шейдера GLSL успешно и используя метод std::map, я использую один вызов функции с одним параметром строки, чтобы получить адрес для униформ/атрибутов при включенном текущем шейдер. в случае, если мне нужно больше производительности, я буду кэшировать вызовы std::map для других переменных. Но я хотел бы знать, если я на правильном пути здесь... так что, пожалуйста, любые комментарии оценили.

Ответ 1

Перечислить унифицированную форму шейдерной программы на GetActiveUniform, а затем сохранить их на карте.

Изменить: Цель.

  • Повторение кода отсутствует. Унифицированные имена как константы отображаются только в тех местах, где вы хотите получить к ним доступ.
  • Ранняя сценическая семантика не учитывает проверки. Когда вы собираете информацию из GL об униформах, вы точно знаете, какой тип ценностей он ожидает. Поэтому, когда фактическое значение передается, вы можете проверить, предоставил ли клиент правильный тип/размер значения. Эти проверки могут сэкономить вам много времени на отладку в случае какого-то крайнего сценария, когда драйвер OpenGL решит быть "умным".

Ответ 2

glGetProgramiv, glGetActiveUniform и glGetActiveAttrib можно использовать для получения информации об используемых формах в программе шейдеров. Информация может быть восстановлена ​​в любое время после того, как программа была связана, glLinkProgram:

  • glGetProgramiv( MyShaderName, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxUniformNameLen ) возвращает длину самого длинного активное равномерное имя переменной (включая символ нулевой остановки)

  • glGetProgramiv( MyShaderName, GL_ACTIVE_UNIFORMS, &noOfUniforms ) возвращает число активных равномерных переменных.

  • glGetActiveUniform возвращает информацию об активной однородной переменной, включающей имя униформы.

  • glGetProgramiv( MyShaderName, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxAttribNameLen ) возвращает длину самого длинного имени атрибута vetex (включая символ нулевого завершения)

  • glGetProgramiv( MyShaderName, GL_ACTIVE_ATTRIBUTES, &noOfAttributes ) возвращает количество активных атрибутов.

  • glGetActiveAttrib возвращает информацию об активном атрибуте vetrtex, включающем имя атрибута.

Используйте информацию из приведенных выше функций, чтобы найти все единообразные имена атрибутов в программе. Спросите каждую униформу для ее местоположения и каждого атрибута для своего индекса, по их именам. См. Фрагмент кода ниже:

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