Cannot link shaders. ERROR:LINK-9 (line - 1) Missing main function for shade

Cannot link shaders. ERROR:LINK-9 (line - 1) Missing main function for shade

我正在构建简单的 "hello triangle" 程序以开始 OpenGL-ES 2.0 开发,但我遇到了这个棘手的错误。它显示我无法 link 着色器。我在RenderMonkey上测试了shader编译,没问题。但在我的实际应用中它无法 link.

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);
} 

你得到的着色器源代码的数据结构完全错误。 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 字符串。

如果你真的想走不同源字符串的路线,我强烈建议你先学习数组、指针、指针数组和多维数组的基础知识。