GLSL: Как я должен хранить и отслеживать расположение униформ / атрибутов? - PullRequest
10 голосов
/ 06 апреля 2011

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

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

Ответы [ 2 ]

6 голосов
/ 06 апреля 2011

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

Редактировать: Цель.

  1. Нет повторений в коде. Унифицированные имена в виде констант появляются только в местах, где вы хотите получить к ним доступ.
  2. Семантика ранней стадии не соответствует проверкам. Когда вы собираете информацию от GL об униформе, вы точно знаете, какой тип ценностей он ожидает. Поэтому, когда передается фактическое значение, вы можете проверить, правильно ли клиент указал правильный тип / размер значения. Эти проверки могут сэкономить вам много времени на отладку в случае некоторого граничного сценария, когда драйвер OpenGL решает быть «умным».
1 голос
/ 03 июля 2017

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