代码之家  ›  专栏  ›  技术社区  ›  jcg

将clamp()添加到片段着色器时,OpenGL GLSL应为“:”at token“<int const>”

  •  2
  • jcg  · 技术社区  · 7 年前

    以下GLSL片段着色器按预期编译和工作:

    #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;
    }
    

    但是,当我更改第9行以将“cosT”的值钳制在0和1之间时:

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

    我得到错误:

    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
    

    这似乎表明错误出现在第一行,但那里没有任何变化。此外,第二个错误表明我使用的GLSL版本存在问题,但正如错误消息所述,#version 330 core应该是比#version 130更高的版本。

    编辑: 这是我加载着色器的代码:

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

    这基本上是直接从我下面的教程 link ,唯一的更改是将文件读取放在ReadShaderFile函数中。

    编辑2: 我的OpenGL上下文是使用以下版本创建的:

    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR,3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR,3);
    
    1 回复  |  直到 7 年前
        1
  •  2
  •   BDL Vyxzl    7 年前

    问题确实是着色器加载程序。您正在使用此语句添加

    ShaderCode +="\n"+line;
    

    换行符(\n) 之前 与您的输入相比,每行将所有内容下移一行。

    因为version语句必须位于 第一行 如果将其移动到第二个着色器,则驱动程序似乎会忽略该语句。例如,我的NVIDIA驱动程序说明:

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

    一个简单的修复方法是在每行之后而不是之前添加换行符,但我强烈建议您不要逐行阅读整个文件,因为这会给您带来糟糕的性能。例如 ShaderCode 变量将针对每一行调整大小,这意味着您将获得整个字符串的内存分配和复制操作。看看 this question on how to read complete files .

    编辑:

    另一个问题是您正在返回 c_str() 局部变量的指针。当 ReadShaderFile 方法结束时 std::string ShaderCode 变量超出范围(从而释放其内容),返回的指针指向无效的内存地址。

    解决方案:返回std::string对象,而不是指向其内容的const char指针。