运行时glsl着色器编译问题

5 c++ windows opengl glsl

我正在开发一个使用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.因为这是可怕的编码.


She*_*ing 2

只是一个快速的预感:

您是否尝试过使用 NULL 作为长度参数调用 glShaderSource?在这种情况下,OpenGL 将假定您的代码以 null 终止。

(由于愚蠢而编辑)

  • @freefallr:请不要使用任何将每一行作为单独的字符串加载到“glShaderSource”中的代码。只是不要这样做。 (3认同)