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 字符串。
如果你真的想走不同源字符串的路线,我强烈建议你先学习数组、指针、指针数组和多维数组的基础知识。
我正在构建简单的 "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 字符串。
如果你真的想走不同源字符串的路线,我强烈建议你先学习数组、指针、指针数组和多维数组的基础知识。