You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用SFML编译GLSL着色器时出现“Duplicate storage qualifier”错误

SFML着色器编译错误:duplicate storage qualifier 解决方法

编译SFML应用时出现以下错误:

Failed to compile vertex shader:
0:1(1): error: duplicate storage qualifier

问题代码

main.cpp

#include <SFML/Graphics.hpp>
int main()
{
    sf::RenderWindow window(sf::VideoMode(800, 600), "SFML works!");
    sf::CircleShape shape(100.f);
    shape.setFillColor(sf::Color::Green);
    sf::Shader shader;
    shader.loadFromFile("vertex_shader.vert", "fragment_shader.frag");

    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
        }

        window.clear();
        window.draw(shape, &shader);
        window.display();
    }

    return 0;
}

原始vertex_shader.vert

varying out vec4 vert_pos;

void main()
{
    // transform the vertex position
    vert_pos = gl_ModelViewProjectionMatrix * gl_Vertex;
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; 

    // transform the texture coordinates
    gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;

    // forward the vertex color
    gl_FrontColor = gl_Color;
}

原始fragment_shader.frag

varying in vec4 vert_pos;

uniform sampler2D texture;
uniform bool hasTexture;
uniform vec2 lightPos;

void main()
{
    //Ambient light
    vec4 ambient = vec4(0.02, 0.02, 0.5, 1.0);
    
    //Convert light to view coords
    lightPos = (gl_ModelViewProjectionMatrix * vec4(lightPos, 0, 1)).xy;
    
    //Calculate the vector from light to pixel (Make circular)
    vec2 lightToFrag = lightPos - vert_pos.xy;
    lightToFrag.y = lightToFrag.y / 1.7;

    //Length of the vector (distance)
    float vecLength = clamp(length(lightToFrag) * 2, 0, 1);

    // lookup the pixel in the texture
    vec4 pixel = texture2D(texture, gl_TexCoord[0].xy);

    // multiply it by the color and lighting
    if(hasTexture == true)
    {
        gl_FragColor = gl_Color * pixel * (clamp(ambient + vec4(1-vecLength, 1-vecLength, 1-vecLength, 1), 0, 1));
    }
    else
    {
        gl_FragColor = gl_Color;
    }
}

错误原因

在GLSL 1.20及更早版本中,varying关键字已经明确了变量是用于顶点着色器与片段着色器之间的传递,不需要额外添加in或out修饰符。你在顶点着色器中写了varying out vec4 vert_pos;,片段着色器中写了varying in vec4 vert_pos;,这里的varying与in/out属于重复的存储限定符,导致编译报错。

另外,片段着色器中尝试修改uniform变量lightPos也是错误的——uniform变量是只读的,不能直接赋值。

修复后的代码

修改后的vertex_shader.vert

varying vec4 vert_pos;

void main()
{
    // transform the vertex position
    vert_pos = gl_ModelViewProjectionMatrix * gl_Vertex;
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; 

    // transform the texture coordinates
    gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;

    // forward the vertex color
    gl_FrontColor = gl_Color;
}

修改后的fragment_shader.frag

varying vec4 vert_pos;

uniform sampler2D texture;
uniform bool hasTexture;
uniform vec2 lightPos;

void main()
{
    //Ambient light
    vec4 ambient = vec4(0.02, 0.02, 0.5, 1.0);
    
    //Convert light to view coords(用局部变量存储转换后的值,避免修改uniform)
    vec2 transformedLightPos = (gl_ModelViewProjectionMatrix * vec4(lightPos, 0, 1)).xy;
    
    //Calculate the vector from light to pixel (Make circular)
    vec2 lightToFrag = transformedLightPos - vert_pos.xy;
    lightToFrag.y = lightToFrag.y / 1.7;

    //Length of the vector (distance)
    float vecLength = clamp(length(lightToFrag) * 2, 0, 1);

    // lookup the pixel in the texture
    vec4 pixel = texture2D(texture, gl_TexCoord[0].xy);

    // multiply it by the color and lighting
    if(hasTexture == true)
    {
        gl_FragColor = gl_Color * pixel * (clamp(ambient + vec4(1-vecLength, 1-vecLength, 1-vecLength, 1), 0, 1));
    }
    else
    {
        gl_FragColor = gl_Color;
    }
}

验证修复

重新编译运行SFML应用,此时着色器应该能正常编译,不会再出现“duplicate storage qualifier”错误,同时也修复了uniform变量的修改问题。

内容的提问来源于stack exchange,提问作者Floggy X

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 01:15:00