我正在开发一个使用OpenGL 4.0着色器的项目.
我必须使用char数组数组向glShaderSource()提供调用,这些数组代表着色器的来源.
着色器编译失败,出现以下错误:
(0) : error C0206: invalid token "<null atom>" in version line
(0) : error C0000: syntax error, unexpected $end at token "<EOF>"
Run Code Online (Sandbox Code Playgroud)
这是我的(hello world)着色器 - 直接来自OpenGL 4.0着色语言菜谱
#version 400
in vec3 VertexPosition;
in vec3 VertexColor;
out vec3 Color;
void main()
{
Color = VertexColor;
gl_Position = vec4( VertexColor, 1.0 );
}
Run Code Online (Sandbox Code Playgroud)
这里是我的代码读取着色器文件到我的C++代码,并在运行时编译着色器:
const int nMaxLineSize = 1024;
char sLineBuffer[nMaxLineSize];
ifstream stream;
vector<string> vsLines;
GLchar** ppSrc;
GLint* pnSrcLineLen;
int nNumLines;
stream.open( m_sShaderFile.c_str(), std::ios::in );
while( (stream.good()) && (stream.getline(sLineBuffer, nMaxLineSize)) )
{
if( strlen(sLineBuffer) > 0 )
vsLines.push_back( string(sLineBuffer) );
}
stream.close();
nNumLines = vsLines.size();
pnSrcLineLen = new GLint[nNumLines];
ppSrc = new GLchar*[nNumLines];
for( int n = 0; n < nNumLines; n ++ )
{
string & sLine = vsLines.at(n);
int nLineLen = sLine.length();
char * pNext = new char[nLineLen+1];
memcpy( (void*)pNext, sLine.c_str(), nLineLen );
pNext[nLineLen] = '\0';
ppSrc[n] = pNext;
pnSrcLineLen[n] = nLineLen+1;
}
vsLines.clear();
// just for debugging purposes (lines print out just fine..)
for( int n = 0; n < nNumLines; n ++ )
ATLTRACE( "line %d: %s\r\n", n, ppSrc[n] );
// Create the shader
m_nShaderId = glCreateShader( m_nShaderType );
// Compile the shader
glShaderSource( m_nShaderId, nNumLines, (const GLchar**)ppSrc, (GLint*) pnSrcLineLen );
glCompileShader( m_nShaderId );
// Determine compile status
GLint nResult = GL_FALSE;
glGetShaderiv( m_nShaderId, GL_COMPILE_STATUS, &nResult );
Run Code Online (Sandbox Code Playgroud)
C++代码按预期执行,但着色器编译失败.谁能发现我可能做错了什么?
我有一种感觉,这可能与某些行尾字符有关,但由于这是我第一次尝试着色器编译,我被卡住了!
我已经在着色器编译中阅读了其他SO答案,但它们似乎特定于Java /其他语言,而不是C++.如果它有帮助,我就在win32平台上.
Nic*_*las 15
你犯了别人犯过的错误.这是以下定义glShaderSource
:
void glShaderSource(GLuint shader, GLsizei count, const GLchar **string, const GLint *length);
Run Code Online (Sandbox Code Playgroud)
这string
是一个字符串数组.它不是您的着色器中的线阵列.编译器解释这个字符串数组的方式是将它们连接在一起.没有换行符.
由于stream.getline
将不会把\n
字符字符串中,每个着色器字符串你产生将不会有在最后一个换行符.因此,当glShaderSource
编译它们时,您的着色器将如下所示:
#version 400in vec3 VertexPosition;in vec3 VertexColor;out vec3 Color;...
Run Code Online (Sandbox Code Playgroud)
这不是合法的GLSL.
正确的方法是将文件作为字符串加载.
std::ifstream shaderFile(m_sShaderFile.c_str());
if(!shaderFile)
//Error out here.
std::stringstream shaderData;
shaderData << shaderFile.rdbuf(); //Loads the entire string into a string stream.
shaderFile.close();
const std::string &shaderString = shaderData.str(); //Get the string stream as a std::string.
Run Code Online (Sandbox Code Playgroud)
然后你可以glShaderSource
轻松地将它传递给它:
m_nShaderId = glCreateShader( m_nShaderType );
const char *strShaderVar = shaderString.c_str();
GLint iShaderLen = shaderString.size();
glShaderSource( m_nShaderId, 1, (const GLchar**)&strShaderVar, (GLint*)&iShaderLen );
glCompileShader( m_nShaderId );
Run Code Online (Sandbox Code Playgroud)
如果你从某个地方复制了这个加载代码,那么我强烈建议你找一个不同的地方来学习OpenGL.因为这是可怕的编码.
只是一个快速的预感:
您是否尝试过使用 NULL 作为长度参数调用 glShaderSource?在这种情况下,OpenGL 将假定您的代码以 null 终止。
(由于愚蠢而编辑)