SFML community forums

Help => Graphics => Topic started by: DragonDePlatino on July 12, 2016, 02:53:55 am

Title: [SOLVED] Loading a shader: pre-mature EOF parse error
Post by: DragonDePlatino on July 12, 2016, 02:53:55 am
For my game project, I have a fog of war shader that hides out-of-view enemies:

Code: [Select]
uniform sampler2D objtexture;
uniform sampler2D fogtexture;
uniform sampler2D lighttexture;

void main()
{
    // Load textures into pixels
    vec4 objpixel = texture2D(objtexture, gl_TexCoord[0].xy);
    vec4 fogpixel = texture2D(fogtexture, gl_TexCoord[0].xy);
    vec4 lightpixel = texture2D(lighttexture, gl_TexCoord[0].xy);
   
    // Draw objects if a lighttexture pixel is fully-transparent
    // Otherwise, hide objects behind fog
    bool changealpha = bool(ceil(lightpixel.a));
    objpixel = vec4((lightpixel.rgb) * float(changealpha) + objpixel.rgb * float(!changealpha), lightpixel.a * float(changealpha) + objpixel.a * float(!changealpha));
    objpixel = mix(objpixel, fogpixel, fogpixel.a);
   
    gl_FragColor = objpixel;
}

When running the program from Code::Blocks, everything works fine. Running the executable, it isn't finding fog.frag file. I could include the fog.frag in the download, but I'd rather not have users cheat and edit the shader. As a solution, I tried embedding the shader in my program like the example shown here (http://www.sfml-dev.org/tutorials/2.0/graphics-shader.php).

After running it through a Notepad++ macro to eliminate any human error, my shader now looks like this:

Code: [Select]
const std::string shaderdata = "uniform sampler2D objtexture;" \
"uniform sampler2D fogtexture;" \
"uniform sampler2D lighttexture;" \
"" \
"void main()" \
"{" \
"    // Load textures into pixels" \
"    vec4 objpixel = texture2D(objtexture, gl_TexCoord[0].xy);" \
"    vec4 fogpixel = texture2D(fogtexture, gl_TexCoord[0].xy);" \
"    vec4 lightpixel = texture2D(lighttexture, gl_TexCoord[0].xy);" \
"    " \
"    // Draw objects if a lighttexture pixel is fully-transparent" \
"    // Otherwise, hide objects behind fog" \
"    bool changealpha = bool(ceil(lightpixel.a));" \
"    objpixel = vec4((lightpixel.rgb) * float(changealpha) + objpixel.rgb * float(!changealpha), lightpixel.a * float(changealpha) + objpixel.a * float(!changealpha));" \
"    objpixel = mix(objpixel, fogpixel, fogpixel.a);" \
"    " \
"    gl_FragColor = objpixel;" \
"}";

Unfortunately, if I compile, I get this error:

Code: [Select]
Failed to compile fragment shader:
Fragment shader failed to compile with the following errors:
ERROR: 0:1: error(#131) Syntax error: pre-mature EOF parse error
ERROR: error(#273) 1 compilation errors.  No code generated

If I print out my shaderdata string, it looks just fine. If I remove all of the comments, line breaks and empty lines, I get the same exact error. Looking at the special characters in Notepad++, all I see are line breaks, tabs and spaces. Could someone please explain what I'm doing wrong?
Title: Re: Loading a shader: pre-mature EOF parse error
Post by: Lee R on July 26, 2016, 02:28:48 pm
I'd hazard a guess that the GLSL parser has problems reading certain code fragments when they're all munged together: since no newline character appears inside of the quoted strings, the expression used to initialize 'shaderdata' evaluates to a single line of text.

Try using C++11 raw string literals (or, if you're stuck with an older compiler, place a \n on the end of each string):
const std::string shaderdata = R"(
uniform sampler2D objtexture;
uniform sampler2D fogtexture;
uniform sampler2D lighttexture;

void main()
{
    // Load textures into pixels
    vec4 objpixel = texture2D(objtexture, gl_TexCoord[0].xy);
    vec4 fogpixel = texture2D(fogtexture, gl_TexCoord[0].xy);
    vec4 lightpixel = texture2D(lighttexture, gl_TexCoord[0].xy);

    // Draw objects if a lighttexture pixel is fully-transparent
    // Otherwise, hide objects behind fog
    bool changealpha = bool(ceil(lightpixel.a));
    objpixel = vec4((lightpixel.rgb) * float(changealpha) + objpixel.rgb * float(!changealpha), lightpixel.a * float(changealpha) + objpixel.a * float(!changealpha));
    objpixel = mix(objpixel, fogpixel, fogpixel.a);

    gl_FragColor = objpixel;
})"
;
 
Title: Re: Loading a shader: pre-mature EOF parse error
Post by: Laurent on July 26, 2016, 03:11:56 pm
If the whole shader is on the same line, everything that appears after the first // is commented out, leaving an unfinished shader code.

Your code should work without comments, but yes raw string literals are better.
Title: Re: Loading a shader: pre-mature EOF parse error
Post by: Lee R on July 26, 2016, 03:47:46 pm
Quote from: Laurent
Your code should work without comments [...]

You would think so, but apparently it didn't:
Quote
If I remove all of the comments, line breaks and empty lines, I get the same exact error.
Title: Re: Loading a shader: pre-mature EOF parse error
Post by: DragonDePlatino on July 27, 2016, 12:33:52 am
Raw string literals? Hmm! I've never heard of those. And considering I'm learning C++ as I go, that's not a huge surprise.

Anyways, that works great! Now I can run the executable without an external fog.frag. Thank you for your help. Also, could the tutorial here (http://www.sfml-dev.org/tutorials/2.3/graphics-shader.php) be updated with this information?
Title: Re: [SOLVED] Loading a shader: pre-mature EOF parse error
Post by: Mario on July 29, 2016, 10:07:09 am
Raw string literals are "new" (in C++11).

As for normal literals: Just look at the following snippet. All the strings are essentially the same, since they're concatenated and the line breaks are outside the strings:

const char *a = "Hello World!";
const char *b = "Hello"" ""World!";
const char *c = "Hello"
                " "
                "World!";