jcg
jcg

Reputation: 69

OpenGL GLSL expecting "::" at token "<int-const>" when adding clamp() to fragment shader

The following GLSL fragment shader compiles and works as expected:

#version 330 core
out vec3 color;
in float U;
in vec4 vertexNormal_worldSpace;
uniform sampler1D TextureSampler;
uniform vec4 LightPos;
void main()
{
    float cosT = dot(normalize(vertexNormal_worldSpace.xyz),normalize(LightPos.xyz));
    color = cosT * texture(TextureSampler,U).rgb;
}

However, when I change line 9 to clamp the value of "cosT" between 0 and 1:

float cosT = clamp(dot(normalize(vertexNormal_worldSpace.xyz),normalize(LightPos.xyz)),0.0,1.0);

I get the errors:

0(1) : error C0000: syntax error, unexpected integer constant, expecting "::" at token "<int-const>"
0(10) : error C7532: global function texture requires "#version 130" or later

This appears to say the error appears on the first line, but nothing has changed there at all. Furthermore the 2nd error suggests that there is an issue with the version of GLSL I am using, however #version 330 core should be a later version than #version 130, as the error message states.

EDIT: This is my code for loading in shaders:

static GLuint LoadShaders(const char* vertex_file_path, const char* frag_file_path){
    GLuint VertID = glCreateShader(GL_VERTEX_SHADER);
    GLuint FragID = glCreateShader(GL_FRAGMENT_SHADER);

    char const* VertPointer = ReadShaderFile(vertex_file_path);
    char const* FragPointer = ReadShaderFile(frag_file_path);
    glShaderSource(VertID,1,&VertPointer,NULL);
    glCompileShader(VertID);


    GLint Result = GL_FALSE;
    int InfoLogLength;
    glGetShaderiv(VertID, GL_COMPILE_STATUS, &Result);
    glGetShaderiv(VertID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    if ( InfoLogLength > 0 ){
        std::vector<char> VertexShaderErrorMessage(InfoLogLength+1);
        glGetShaderInfoLog(VertID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
        printf("%s\n", &VertexShaderErrorMessage[0]);
    }


    glShaderSource(FragID,1,&FragPointer,NULL);
    glCompileShader(FragID);
    glGetShaderiv(FragID, GL_COMPILE_STATUS, &Result);
    glGetShaderiv(FragID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    if ( InfoLogLength > 0 ){
        std::vector<char> FragmentShaderErrorMessage(InfoLogLength+1);
        glGetShaderInfoLog(FragID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
        printf("%s\n", &FragmentShaderErrorMessage[0]);
    }



    GLuint ProgramID = glCreateProgram();
    glAttachShader(ProgramID,VertID);
    glAttachShader(ProgramID,FragID);
    glLinkProgram(ProgramID);


    glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
    glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    if ( InfoLogLength > 0 ){
        std::vector<char> ProgramErrorMessage(InfoLogLength+1);
        glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
        printf("%s\n", &ProgramErrorMessage[0]);
    }
    return ProgramID;


}
static char const* ReadShaderFile(const char* path){
    std::string ShaderCode;
    std::ifstream ShaderStream(path,std::ios::in);
    if(ShaderStream.is_open()){
        std::string line = "";
        while (std::getline(ShaderStream,line)){
            ShaderCode +="\n"+line;
        }
        ShaderStream.close();
        return ShaderCode.c_str();
    }else{

    return 0;}
}

This is basically straight from the tutorial I am following link, only change is putting the file reading in the ReadShaderFile function.

EDIT 2: My OpenGL context is created with the following version:

glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR,3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR,3);

Upvotes: 2

Views: 2599

Answers (1)

BDL
BDL

Reputation: 22174

The problem is indeed the shader loader. You are adding with this statement

ShaderCode +="\n"+line;

a newline character (\n) before each line which moves everything one line down compared to your input.

Since the version statement has to be in the first line of a shader and you move it to the second, the statement seems to be ignored by your driver. My NVIDIA driver, for example, states:

error C0204: version directive must be first statement and may not be repeated

A simple fix would be to add to newline character after each line instead of before, but I would strongly encourage you not to read whole files line by line since this will give you a terrible performance. For example, the ShaderCode variable will be resized for each line which means you get a memory allocation and a copy operation for the whole string. Have a look at this question on how to read complete files.

Edit:

Another problem is that you're returning the c_str() pointer of local variable. When the ReadShaderFile method ends, the std::string ShaderCode variable goes out of scope (thus frees it's content) and the returned pointer points to an invalid memory address.

Solution: Return the std::string object instead of the const char pointer to its content.

Upvotes: 2

Related Questions