为啥片段着色器没有附加?

Posted

技术标签:

【中文标题】为啥片段着色器没有附加?【英文标题】:Why fragment shader didn't attach?为什么片段着色器没有附加? 【发布时间】:2014-03-24 13:27:03 【问题描述】:

我对现代 OpenGL (3.0+) 很陌生,现在我正在尝试在黑色背景上创建一个基本的白色三角形。我在 Mac OS X Mavericks 10.9.2 上,使用 GLFW 3.0.4 创建窗口,使用 GLEW 1.10.0 加载扩展。你可以找到full source code here.

我的问题是,我的片段着色器不想附加到我的程序中。我检查了程序(glIsProgram())和着色器(glIsShader),它们都通过了。着色器正在编译,程序正在链接..

但是我的代码编译、运行并且没有抛出任何错误,我只有一个黑色背景但没有白色三角形的运行窗口。这是部分,我认为它以某种方式损坏(或者至少这是我可以找到错误的地方):

const char* opengl_get_error(void)

    switch (glGetError())
    
        case 0x0500: return "GL_INVALID_ENUM​";
        case 0x0501: return "GL_INVALID_VALUE​";
        case 0x0502: return "GL_INVALID_OPERATION​";
        case 0x0503: return "GL_STACK_OVERFLOW​";
        case 0x0504: return "GL_STACK_UNDERFLOW​";
        case 0x0505: return "GL_OUT_OF_MEMORY​";
        case 0x0506: return "GL_INVALID_FRAMEBUFFER_OPERATION​";
        case 0x8031: return "GL_TABLE_TOO_LARGE​";
            default: return "GL_NO_ERROR";
    


void check_attached_shaders(GLuint program)

    GLsizei count = 0;
    GLuint shaders[] = 0, 0, 0, 0;
    glGetAttachedShaders(program, 4, &count, shaders);
    printf(">>> ERROR: %s\n", opengl_get_error());
    printf("\tnumber of shaders: %d\n", count);
    for (int i=0; i < 4; i++) printf("\tshader_id: %d\n", shaders[i]);


...

    // Get program ID
    GLuint programID = glCreateProgram();

    // Attach shaders
/* CHECKING: */ check_attached_shaders(programID);
    glAttachShader(programID, vert_shader);
/* CHECKING: */ check_attached_shaders(programID);
    glAttachShader(programID, frag_shader);
/* CHECKING: */ check_attached_shaders(programID);

    // Link shader program
    glLinkProgram(programID);

...

我有这个输出:

/*
>>> ERROR: GL_NO_ERROR
    number of shaders: 0
    shader_id: 0
    shader_id: 0
    shader_id: 0
    shader_id: 0
>>> ERROR: GL_NO_ERROR
    number of shaders: 1
    shader_id: 1
    shader_id: 0
    shader_id: 0
    shader_id: 0
>>> ERROR: GL_INVALID_OPERATION
    number of shaders: 1
    shader_id: 1
    shader_id: 0
    shader_id: 0
    shader_id: 0
*/

这是我的顶点着色器的样子:

// OpenGL Shading Language Version 1.5.0
#version 150 core

in vec2 input_position;

void main()

    gl_Position = vec4(input_position, 0.f, 1);

这是我的片段着色器的样子:

// OpenGL Shading Language Version 1.5.0
#version 150 core

out vec4 output_fragment;

void main()

    output_fragment = vec4(1.f, 1.f, 1.f, 1.f);

欢迎任何反馈,

提前致谢!

【问题讨论】:

是不是因为在create_program_from_shaders中,你在链接程序后将着色器从程序中分离出来? @doron 如果我注释掉glDetachShader() 行,它仍然不起作用,我仍然有GL_INVALID_OPERATOR 错误。 你的顶点着色器至少错过了投影矩阵 为什么在 opengl_get_error switch 语句中使用“神奇的”十六进制数字而不是人类可读的标记?此外,您必须在循环中调用 glGetError 或在您的情况下为 opengl_get_error,直到它返回 GL_NO_ERROR,因为在 OpenGL 中可能会累积错误。 您的create_shader_from_file 返回 0 或 1 表示成功或失败,但您将结果用作 shaderID。很可能您将同一个着色器附加了两次。 【参考方案1】:

如 cmets 中所述,问题出在函数 GLuint create_shader_from_file(GLchar *path, GLenum shader_type) 中,该函数从源文件编译着色器并返回 0 或 1 表示失败或成功。

然后将结果用作着色器 ID。

【讨论】:

以上是关于为啥片段着色器没有附加?的主要内容,如果未能解决你的问题,请参考以下文章

为啥片段着色器比渲染纹理更快?

为啥 gl_Color 不是片段着色器的内置变量?

为啥保守光栅化无法为某些三角形调用片段着色器?

为啥我必须切换纹理单元才能让我的片段着色器识别要使用的纹理?

为啥我的 Ray March 片段着色器反射纹理查找会减慢我的帧速率?

为啥在 Metal 中不允许从片段着色器中写入缓冲区?