为什么这个GLSL着色器会产生语法错误?

时间:2016-08-27 01:27:02

标签: opengl glsl

我使用/编写着色器相当新,所以我可能会遗漏一些东西,但是下面的GLSL片段着色器会产生语法错误。

复古frag.glsl

#version 440

uniform sampler2D texture;
uniform ivec3 precision; // A syntax error happens on this line for some reason

void main() {
    vec3 prec_fac = vec3(float(1 << precision.x), float(1 << precision.y), float(1 << precision.z));
    vec3 factor_adjust = 1.0f / (prec_fac - 1.0f);
    vec4 color = texture2D(texture, gl_TexCoord[0].xy);
    vec4 low_color = vec4(
        floor(color.x * (prec_fac.x + 0.01f)) * factor_adjust.x,
        floor(color.y * (prec_fac.y + 0.01f)) * factor_adjust.y,
        floor(color.z * (prec_fac.z + 0.01f)) * factor_adjust.z,
        1.0f);

    gl_FragColor = low_color;
}

的main.cpp

#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <SFML/System.hpp>

#include <iostream>
#include <string>
#include <memory>
#include <cmath>

constexpr sf::Uint8 ColorFloatToU8(float val) {
    return static_cast<sf::Uint8>(255.0f * val);
}

sf::Color ColorFromHSV(float hue, float sat, float val, float alpha=1.0f) {
    int i;
    float f, p, q, t;
    sf::Uint8 a = ColorFloatToU8(alpha);
    sf::Uint8 r,g,b;

    if(sat == 0) {
        r = g = b = ColorFloatToU8(val);
        return sf::Color(r, g, b, a);
    }

    hue *= 6.0;
    hue = std::fmod(hue, 6.0f);
    i = std::floor(hue);

    f = hue - i;
    p = val * (1 - sat);
    q = val * (1 - sat * f);
    t = val * (1 - sat * (1 - f));

    switch(i) {
    case 0:
        r = ColorFloatToU8(val);
        g = ColorFloatToU8(t);
        b = ColorFloatToU8(p);
        break;
    case 1:
        r = ColorFloatToU8(q);
        g = ColorFloatToU8(val);
        b = ColorFloatToU8(p);
        break;
    case 2:
        r = ColorFloatToU8(p);
        g = ColorFloatToU8(val);
        b = ColorFloatToU8(t);
        break;
    case 3:
        r = ColorFloatToU8(p);
        g = ColorFloatToU8(q);
        b = ColorFloatToU8(val);
        break;
    case 4:
        r = ColorFloatToU8(t);
        g = ColorFloatToU8(p);
        b = ColorFloatToU8(val);
        break;
    default:
        r = ColorFloatToU8(val);
        g = ColorFloatToU8(p);
        b = ColorFloatToU8(q);
    }

    return sf::Color(r, g, b, a);
}

int main() {
    std::cout << "Creating RenderWindow\n";
    sf::RenderWindow window(
        sf::VideoMode(800, 600),
        "SFML window",
        sf::Style::Close,
        sf::ContextSettings(0, 0, 0, 4, 4, sf::ContextSettings::Default, true)
    );

    std::cout << "Loading Shader\n";
    sf::Shader shader;

    // vvv ATTENTION: This is where the glsl shader is failing to compile! vvv
    if(!shader.loadFromFile("retro-frag.glsl", sf::Shader::Fragment)) {
        std::cerr << "ERROR: Unable to load shader!\n";
        return 1;
    }

    std::cout << "Creating Image : ";
    sf::Image img;
    if(!img.loadFromFile("sample_photo_00.jpg")) {
        std::cerr << "ERROR: Unable to load image!\n";
        return 1;
    }

    std::cout << "Creating Texture\n"; std::cout.flush();
    sf::Texture tex;
    tex.loadFromImage(img);
    sf::Texture tex2;
    tex2.loadFromImage(img);

    std::cout << "Creating Sprites\n"; std::cout.flush();
    sf::Sprite sprite(tex);
    sf::Sprite sprite2(tex2);
    sprite2.setPosition(400, 0);
    shader.setUniform("texture", sf::Shader::CurrentTexture);
    shader.setUniform("precision", sf::Glsl::Vec3(3, 3, 2));

    std::cout << "Starting Game Loop\n"; std::cout.flush();
    while(window.isOpen()) {
        sf::Event event;
        while(window.pollEvent(event)) {
            if(event.type == sf::Event::Closed)
                window.close();
        }

        window.clear(sf::Color::Green);
        window.draw(sprite);
        window.draw(sprite2, &shader);
        window.display();
    }

    return 0;
}

Github Gist链接:https://gist.github.com/drako0812/0f47ad46f6d4b4c5c15b234cbc15e280

编辑:具体错误输出如下:

Failed to compile fragment shader:
Fragment shader failed to compile with the following errors:
ERROR: 0:4: error(#132) Syntax error: ERROR: error(#273) 1 compilation errors.  No code generated

编辑2:添加了加载着色器的c ++代码。

编辑3:解决了。修正后的GLSL着色器如下:

复古frag.glsl

#version 440 compatibility

uniform sampler2D texture;
uniform ivec3 bit_precision; // A syntax error happens on this line for some reason

void main() {
    vec3 prec_fac = vec3(float(1 << bit_precision.x), float(1 << bit_precision.y), float(1 << bit_precision.z));
    vec3 factor_adjust = 1.0f / (prec_fac - 1.0f);
    vec4 color = texture2D(texture, gl_TexCoord[0].xy);
    vec4 low_color = vec4(
        floor(color.x * (prec_fac.x + 0.01f)) * factor_adjust.x,
        floor(color.y * (prec_fac.y + 0.01f)) * factor_adjust.y,
        floor(color.z * (prec_fac.z + 0.01f)) * factor_adjust.z,
        1.0f);

    gl_FragColor = low_color;
}

此外,在main.cpp中,行shader.setUniform("precision", sf::Glsl::Vec3(3, 3, 2));现在应为shader.setUniform("bit_precision", sf::Glsl::Vec3(3, 3, 2));

1 个答案:

答案 0 :(得分:3)

这一行会出错:

uniform ivec3 precision;

因为precision是关键字,您无法使用关键字作为变量名称。它用于精确限定符。虽然精度限定符在桌面OpenGL着色器中没有任何功能,但它们被添加到语法中以与OpenGL ES中的着色器兼容。

另请注意,您在此处使用的texture2D()功能已在核心配置文件中弃用:

vec4 color = texture2D(texture, gl_TexCoord[0].xy);

在核心配置文件中,它将被重载的texture()函数替换:

vec4 color = texture(texture, gl_TexCoord[0].xy);

实际上,如果您使用gl_TexCoord,则无论如何都需要使用兼容性配置文件。这在核心配置文件中不可用。因此,除非您完全转换到核心配置文件,否则代码中的第一行必须是:

#version 440 compatibility