为什么这些不匹配的着色器变量不会产生链接器错误?

Bre*_*ent 3 opengl shader glsl

当着色器编译和链接期间出现故障时,我试图抛出异常并中止我的程序。我引入了一个错字:将顶点着色器的输出变量命名为与片段着色器中预期的输入变量不同的名称。我希望这会在链接上失败,但一切正常(片段着色器中变量的值最终为 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);
}
Run Code Online (Sandbox Code Playgroud)

片段着色器

#version 330 core
out vec4 FragColor;

in vec4 vertexColor;

void main()
{
    FragColor = vertexColor;
}

Run Code Online (Sandbox Code Playgroud)

测试代码:

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
Run Code Online (Sandbox Code Playgroud)

Rab*_*d76 5

该问题与 GLSL 版本有关。在OpenGL Shading Language 4.60 Specification (4.3.4 Input Variables) 中明确指出,如果输入变量是静态使用的,但在前一阶段没有声明相应的输出变量,这是链接时错误。

这部分规范在OpenGL 着色语言 3.30 规范中缺失。

将 GLSL 版本更改为(例如)4.60 ( #version 460 core),您将得到预期的错误。
例如

“错误:“vertexColor”未声明为上一阶段的输出”