2016-08-27 6 views
-1

Я довольно новичок в использовании/написании шейдеров, поэтому мне может быть что-то не хватает, но следующий шейдер 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

Edit: конкретный вывод ошибок заключается в следующем:

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

+0

Какая ошибка? –

+0

@NicolBolas извините за это. Теперь добавляется сообщение об ошибке. – Drako0812

+0

Является ли это фактическим InfoLog, который вы вернетесь из OpenGL, или это что-то еще? Кроме того, я подозреваю, что ваш код загрузки виноват; давайте получим полный [mcve]. –

ответ

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 
+0

Хорошо, спасибо. Да, это должен быть профиль совместимости. Как я уже сказал, я довольно новичок в GLSL. Трудно выучить методы, когда примеры, которые можно найти в Интернете, не совсем ясны, для какой версии OpenGL они предназначены, а также для совместимости или профилей ядра. – Drako0812

Смежные вопросы