Почему эти несовпадающие шейдерные переменные не вызывают ошибку компоновщика? - PullRequest
3 голосов
/ 23 мая 2019

Я пытаюсь вызвать исключение и прервать свою программу, если что-то не получается во время компиляции и компоновки шейдера. Я ввел опечатку: присвоение имени выходной переменной моего вершинного шейдера чем-то отличным от ожидаемой входной переменной в моем фрагментном шейдере. Я ожидал бы, что это потерпит неудачу на ссылке, но все работает нормально (и значение переменной в фрагментном шейдере просто заканчивается 0). В частности, glGetProgramiv(id, GL_LINK_STATUS, &success); устанавливает успех на true. Что происходит?

Вершинный шейдер :

#version 330 core
layout (location = 0) in vec3 aPos;
out vec4 vertexColo; // NOTE THE MISSPELLING HERE

void main()
{
    gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
    vertexColo = vec4(1.0 - aPos.y, 0.8 - aPos.y, aPos.x, 1.0);
}

Фрагмент шейдера :

#version 330 core
out vec4 FragColor;

in vec4 vertexColor;

void main()
{
    FragColor = vertexColor;
}

Код теста:

namespace btv {

namespace {
static void test_compile(unsigned id, const char* path)
{
    int success;
    glGetShaderiv(id, GL_COMPILE_STATUS, &success);
    if (!success) {
        constexpr size_t BUF_SIZE = 1024;
        char buf[BUF_SIZE];
        glGetShaderInfoLog(id, BUF_SIZE, NULL, buf);
        std::stringstream ss;
        ss << "Shader at path: " << path << " failed with message: "
            << buf;
        throw std::runtime_error(ss.str());
    }
}

static void test_link(unsigned id, const char* v_path, const char* f_path)
{
    int success;
    glGetProgramiv(id, GL_LINK_STATUS, &success);
    if (!success) {
        constexpr size_t BUF_SIZE = 1024;
        char buf[BUF_SIZE];
        glGetProgramInfoLog(id, BUF_SIZE, NULL, buf);
        std::stringstream ss;
        ss << "Program with v shader: " << v_path << ", f shader: " << f_path
           <<  " failed with message: " << buf;
        throw std::runtime_error(ss.str());
    }
}
}

Program::Program(const char* v_path, const char* f_path)
{
    std::string v_src = slurp(v_path);
    std::string f_src = slurp(f_path);

    const char *v_c = v_src.data();
    const char *f_c = f_src.data();


    unsigned v_shdr = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(v_shdr, 1, &v_c, nullptr);
    glCompileShader(v_shdr);
    test_compile(v_shdr, v_path);


    unsigned f_shdr = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(f_shdr, 1, &f_c, nullptr);
    glCompileShader(f_shdr);
    test_compile(f_shdr, f_path);

    id = glCreateProgram();
    glAttachShader(id, v_shdr);
    glAttachShader(id, f_shdr);
    glLinkProgram(id);
    test_link(id, v_path, f_path);
}
} // namespace btv

1 Ответ

4 голосов
/ 23 мая 2019

Проблема связана с версией GLSL. В спецификации OpenGL Shading Language 4.60 (4.3.4 Входные переменные) четко указано, что это ошибка времени соединения, если входная переменная используется статически, но соответствующая выходная переменная не объявлена ​​в предыдущий этап.

Эта часть спецификации отсутствует в спецификации OpenGL Shading Language 3.30 .

Измените версию GLSL на (например, 4,60 (#version 460 core)), и вы получите ожидаемую ошибку.
например

"ошибка:" vertexColor "не объявлен как выход из предыдущего этапа"

...