c++ - 将clamp()添加到片段着色器时,OpenGL GLSL在标记 "::"处期望 "<int-const>"

标签 c++ opengl glsl

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

这基本上直接来 self 正在关注的教程 link ,唯一的变化是将文件读取放在ReadShaderFile函数中。

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

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

最佳答案

问题确实出在着色器加载器上。您正在添加此语句

ShaderCode +="\n"+line;

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

由于版本声明必须位于着色器的第一行,而您将其移至第二行,因此驱动程序似乎会忽略该声明。例如,我的 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 指针。

关于c++ - 将clamp()添加到片段着色器时,OpenGL GLSL在标记 "::"处期望 "<int-const>",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47895521/

相关文章:

opengl - 是否可以将索引缓冲区对象 (IBO) 与功能 'glMultiDrawElements' 一起使用?

opengl-es - glGetShaderInfoLog 返回空字符串,但着色器程序未正确链接

java - 着色器测试网格 - 线条呈锯齿状且断裂

c++ - 可以将带有类的 C++ 头文件转换为 Delphi 单元吗?

c++ - 管理对象变量生命周期的最佳方法是什么?

c++ - 将二维数组传递给 C 和 C++ 中的函数

C++:从类内访问 operator[] 的便捷方式?

c++ - 不调用 ReleaseDC 可能会发生什么坏事?

c++ - 在现代 OpenGL 和 C++ 中渲染 Quake BSP

c++ - 是否允许使用 VkBool32 作为推送常量?