glGetUniformLocation возвращает -1, хотя я использовал переменную в шейдере - PullRequest
2 голосов
/ 04 июля 2019

Похоже, что компилятор glsl оптимизирует неиспользуемую переменную (удалить).В моем случае я использовал переменную, но glGetUniformLocation возвращает -1

rgbScene.addRenderStage(
    [&obj = std::as_const(model)](Camera* cam) {

    auto& mesh = std::get<Mesh>(obj);
    auto& program = std::get<ShaderProgram>(obj);

    glUseProgram(program);

    glBindVertexArray(mesh.getData<VAO>());
    int loc;
    glUniformMatrix4fv(
        loc = glGetUniformLocation(program, "proj_matrix"),
        1, GL_FALSE,
        glm::value_ptr(cam->getProjectionMatrix())
    );

    glUniformMatrix4fv(
        loc = glGetUniformLocation(program, "view_matrix"),
        1, GL_FALSE,
        glm::value_ptr(cam->getViewMatrix())
    );

    glUniformMatrix4fv(
        loc = glGetUniformLocation(program, "model_matrix"),
        1, GL_FALSE,
        glm::value_ptr(mesh.getModelMatrix())
    );

    glUniform3fv(
        loc = glGetUniformLocation(program, "light_direction"),
        1, glm::value_ptr(-(cam->getForward()))
    );

    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, mesh.getData<VertexData>());
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);

    glEnableVertexAttribArray(1);
    glBindBuffer(GL_ARRAY_BUFFER, mesh.getData<NormalData>());
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, nullptr);

    glDrawArrays(GL_TRIANGLES, 0, mesh.getSize());

    glDisableVertexAttribArray(1);
    glDisableVertexAttribArray(0);
});

Я проверил переменную loc путем отладки построчно в Visual Studio 2019, а в последний раз glGetUniformLocation возвращает -1

вот мой код вершинного шейдера

#version 460 core

uniform mat4 proj_matrix;
uniform mat4 view_matrix;
uniform mat4 model_matrix;
uniform vec3 light_direction;

layout(location = 0) in vec3 pos;
layout(location = 1) in vec3 normal;

out VS_OUT
{
    vec3 N;
    vec3 L;
    vec3 V;
} vs_out;

void main(void)
{
    vec4 P = view_matrix * model_matrix * vec4(pos, 1.0);

    vs_out.N = mat3(view_matrix * model_matrix) * normal;
    vs_out.L = mat3(view_matrix) * (-light_direction);
    vs_out.V = -P.xyz;

    gl_Position = proj_matrix * P;
}

Я пытался изменить имя переменной, другой порядок ... но не могу решить эту проблему

Есть ли другие правила для единой переменнойв шейдере ??

- Правка - для фрагмента шейдера,

#version 460 core

layout (location = 0) out vec4 color;

in VS_OUT
{
    vec3 N;
    vec3 L;
    vec3 V;
} fs_in;

uniform vec3 diffuse_albedo = vec3(0.8, 0.3, 0.2);
uniform vec3 specular_albedo = vec3(0.7);
uniform float specular_power = 128.0;

void main(void)
{
    vec3 N = normalize(fs_in.N);
    vec3 L = normalize(fs_in.L);
    vec3 V = normalize(fs_in.V);

    vec3 R = reflect(-L, N);

    vec3 diffuse = max(dot(N, L), 0.0) * diffuse_albedo;
    vec3 specular = pow(max(dot(R, V), 0.0), specular_power) * specular_albedo;

    color = vec4(diffuse + specular, 1.0);

    // color = vec4(1.0,1.0, 1.0, 1.0);
}

1 Ответ

1 голос
/ 04 июля 2019

Фрагментные шейдерные входные данные N, L и V переменные должны быть "использованы" тоже.

Обратите внимание, что активные ресурсы определяются, когда программа связана. Если вход в фрагментный шейдер не используется, униформы, которые устанавливают соответствующую выходную переменную в вершинном шейдере, могут не активироваться.

См. Спецификация профиля ядра OpenGL 4.6 - 7.3.1 Программные интерфейсы , стр. 102:

7.3.1 Программные интерфейсы

Когда программный объект становится частью текущего состояния рендеринга, его исполняемый код может связываться с другими этапами конвейера GL или кодом приложения через множество интерфейсов. Когда программа связана, GL формирует список активных ресурсов для каждого интерфейса. Примеры активных ресурсов включают переменные, блоки интерфейса и подпрограммы, используемые кодом шейдера. Ресурсы, на которые имеются ссылки в шейдерном коде, считаются активными, если только компилятор и компоновщик не могут окончательно определить, что они не оказывают наблюдаемого влияния на результаты, полученные исполняемым кодом программы. Например, переменные могут считаться неактивными, если они объявлены, но не используются в исполняемом коде, используются только в предложении оператора if, который никогда не будет выполнен, используются только в функциях, которые никогда не вызываются, или используются только в вычислениях временных переменные, не влияющие на вывод любого шейдера. В случаях, когда компилятор или компоновщик не может сделать окончательное определение, любой ресурс, на который ссылается код шейдера, будет считаться активным. Набор активных ресурсов для любого интерфейса зависит от реализации, поскольку зависит от различных анализов и оптимизаций, выполняемых компилятором и компоновщиком

Если программа успешно связана, GL генерирует списки активных ресурсов на основе исполняемого кода, созданного ссылкой.

...