glsl shader compilation issue at runtime

陌路散爱 提交于 2019-12-04 07:35:24

Just a quick hunch:

Have you tried calling glShaderSource with NULL as length parameter? In that case OpenGL will assume your code to be null-terminated.

(Edited because of stupidity)

You have made a mistake that others have made. This is the definition of glShaderSource:

void glShaderSource(GLuint shader,  GLsizei count,  const GLchar **string,  const GLint *length);

The string is an array of strings. It is not intended to be an array of lines in your shader. The way the compiler will interpret this array of strings is by concatenating them together, one after another. Without newlines.

Since stream.getline will not put the \n character in the string, each of the shader strings you generate will not have a newline at the end. Therefore, when glShaderSource goes to compile them, your shader will look like this:

#version 400in  vec3        VertexPosition;in  vec3        VertexColor;out vec3        Color;...

That's not legal GLSL.

The proper way to do this is to load the file as a string.

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.

Then you can just pass that along to glShaderSource easily enough:

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

If you copied this loading code from somewhere, then I strongly suggest you find a different place to learn about OpenGL. Because that's terrible coding.

datenwolf

glShaderSource( m_nShaderId, nNumLines, (const GLchar**)ppSrc, (GLint*) pnSrcLineLen );

I know the signature of glShaderSource looks tempting to send each line of the shader separately. But that's now what it's meant for. The point of being able to send is multiple arrays is so that one can mix multiple primitive shader sources into a single shader, kind of like include files. Understanding this, makes it much simpler to read in a shader file – and avoids such nasty bugs.

Using C++ you can do it much nicer and cleaner. I already wrote the follwing in Getting garbage chars when reading GLSL files


You're using C++, so I suggest you leverage that. Instead of reading into a self allocated char array I suggest you read into a std::string:

#include <string>
#include <fstream>

std::string loadFileToString(char const * const fname)
{
    std::ifstream ifile(fname);
    std::string filetext;

    while( ifile.good() ) {
        std::string line;
        std::getline(ifile, line);
        filetext.append(line + "\n");
    }

    return filetext;
}

That automatically takes care of all memory allocation and proper delimiting -- the keyword is RAII: Resource Allocation Is Initialization. Later on you can upload the shader source with something like

void glcppShaderSource(GLuint shader, std::string const &shader_string)
{
    GLchar const *shader_source = shader_string.c_str();
    GLint const shader_length = shader_string.size();

    glShaderSource(shader, 1, &shader_source, &shader_length);
}

You can use those two functions together like this:

void load_shader(GLuint shaderobject, char * const shadersourcefilename)
{
    glcppShaderSource(shaderobject, loadFileToString(shadersourcefilename));
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!