使用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
相关产品推荐
相关产品推荐

