无法链接着色器。错误:LINK-9(第1行)缺少阴影的主要功能

时间:2015-11-20 18:15:40

标签: qt opengl-es opengl-es-2.0

我正在构建简单的“hello triangle”程序,从OpenGL-ES 2.0开发开始,我遇到了这个棘手的错误。它显示我无法链接着色器。我在RenderMonkey上测试了着色器编译,没关系。但在我的实际应用中,它无法链接。

void COpenGLWidget::initializeGL()
{
    const size_t nMaxLength = 255;

    glClearColor(1.0f, 0.0f, 0.0, 1.0f);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_CULL_FACE);


    char lpszVertexBuffer[][nMaxLength] =
    {
        "uniform mat4 g_MatViewProjection;\n",
        "attribute vec4 rm_Vertex;\n",
        "void main(void)\n",
        "{\n",
        "gl_Position = rm_Vertex;\n",
        "}"
    };

    char lpszFragmentBuffer[][nMaxLength] =
    {
        "precision mediump float; \n",
        "void main(void)\n",
        "{\n",
        "gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0 );\n",
        "}\n"
    };

    m_nVertexShader = glCreateShader(GL_VERTEX_SHADER);
    m_nPixelShader = glCreateShader(GL_FRAGMENT_SHADER);

    int iVertexShaderLength = 6;
    int iPixelShaderLength = 5;

    glShaderSource(m_nVertexShader, 1, (const char**)lpszVertexBuffer, &iVertexShaderLength);
    glShaderSource(m_nPixelShader, 1, (const char**)lpszFragmentBuffer, &iPixelShaderLength);

    glCompileShader(m_nVertexShader);

    int iIsOk = 0;

    glGetShaderiv(m_nVertexShader, GL_COMPILE_STATUS, &iIsOk);

    if(!iIsOk)
    {
        GLint infoLen = 0;

        glGetShaderiv(m_nVertexShader, GL_INFO_LOG_LENGTH, &infoLen);

        if(infoLen > 1)
        {
            char* infoLog = (char*)malloc(sizeof(char) * infoLen);

            glGetShaderInfoLog(m_nVertexShader, infoLen, NULL, infoLog);


            QMessageBox::warning(this, QString("Error"),
                                 QString(infoLog), QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes);

            free(infoLog);
        }

        glDeleteShader(m_nVertexShader);

        return;
    }

    glCompileShader(m_nPixelShader);

    glGetShaderiv(m_nPixelShader, GL_COMPILE_STATUS, &iIsOk);

    if(!iIsOk)
    {
        GLint infoLen = 0;

        glGetShaderiv(m_nPixelShader, GL_INFO_LOG_LENGTH, &infoLen);

        if(infoLen > 1)
        {
            char* infoLog = (char*)malloc(sizeof(char) * infoLen);

            glGetShaderInfoLog(m_nPixelShader, infoLen, NULL, infoLog);


            QMessageBox::warning(this, QString("Error"),
                                 QString(infoLog), QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes);

            free(infoLog);
        }

        glDeleteShader(m_nPixelShader);

        return;
    }

    m_nProgram = glCreateProgram();

    glAttachShader(m_nProgram, m_nVertexShader);
    glAttachShader(m_nProgram, m_nPixelShader);

    glBindAttribLocation(m_nProgram, 0, "rm_Vertex");

    glLinkProgram(m_nProgram);

    glGetProgramiv(m_nProgram, GL_LINK_STATUS, &iIsOk);

    // Fail to pass status validation
    if(!iIsOk)
    {
        GLint infoLen = 0;

        glGetProgramiv(m_nProgram, GL_INFO_LOG_LENGTH, &infoLen);

        if(infoLen > 1)
        {
            char* infoLog = (char*)malloc(sizeof(char) * infoLen);

            glGetProgramInfoLog(m_nProgram, infoLen, NULL, infoLog);


            QMessageBox::warning(this, QString("Error"),
                                 QString(infoLog), QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes);

            free(infoLog);
        }

        glDeleteProgram(m_nProgram);

        return;
    }

    glUseProgram(m_nProgram);

    connect(&m_Timer, SIGNAL(timeout()), this, SLOT(update()));
    m_Timer.start(1);
} 

1 个答案:

答案 0 :(得分:1)

您的着色器源代码的数据结构完全错误。 glShaderSource接受指针数组char*,因此是一系列字符串。您将着色器源代码存储在二维数组char中。与一个常见的神话相反,数组不是C / C ++中的指针。

此外,您告诉GL有一个行,长度为6 个字符(分别为片段着色器为5)。着色器编译器只能看到源代码的第一部分,因此报告它找不到main函数。

目前还不清楚为什么你甚至试图将着色器源分成几个字符串。这样做并没有任何好处,因为你没有重新组合不同的点点滴滴。我建议你只使用单个字符串,所以行

const char *source=
    "uniform mat4 g_MatViewProjection;\n"
    "attribute vec4 rm_Vertex;\n"
    "void main(void)\n"
    "{\n"
    "gl_Position = rm_Vertex;\n"
    "}";

在C / C ++中,你可以通过简单地将它们相互连接来连接字符串,这也适用于各行。

然后,您只需使用source指针的地址并将其输入GL:

glShaderSource(shaderName, 1, &source, NULL);

也没有必要预先计算任何长度,GL也会处理0终止的C字符串。

如果您真的想要使用不同源字符串的路径,我强烈建议您首先学习数组,指针,指针数组和多维数组的基础知识。