SFML community forums

Help => Graphics => Topic started by: Lolilolight on May 30, 2014, 04:14:03 pm

Title: How to use preprocessor for shader in loadFromMemory ???
Post by: Lolilolight on May 30, 2014, 04:14:03 pm
Hi.

I try to load a shader from memory, which use the version 130 of GLSL but it fails to compile :

const std::string vertexCode =
    "#version 130"
    "attribute vec3 vertexPosition_modelspace;"
    "attribute vec3 vertex_color;"
    "out vec3 color;"
    "void main() {"
        "vec4 vertex = vec4(vertexPosition_modelspace.xyz, 1.0f);"
        "gl_Position = gl_ModelViewProjectionMatrix * vertex;"
        "color = vertex_color;"
    "}";
    const std::string fragmentCode =
    "#version 130"
    "in vec3 color;"
    "out vec3 fragmentColor;"
    "void main() {"
        "fragmentColor = color;"
    "}";
 

Here is the error :
Code: [Select]
preprocessor error : syntax error, unexcepted identifier, unexpected  new line.

Is there a way to do this ?
Title: Re: How to use preprocessor for shader in loadFromMemory ???
Post by: Nexus on May 30, 2014, 04:45:53 pm
The #version 130 directive must be on its own line.

Having the shader code on multiple lines does not automatically insert newline characters. The string literals are simply concatenated without intermediate whitespace. Is there a specific reason why you don't outsource GLSL code into its own file?
Title: Re: How to use preprocessor for shader in loadFromMemory ???
Post by: Lolilolight on May 30, 2014, 05:24:38 pm
Haaa, oké, ty!

I just want that the shader code is internal of my framework, because, it's a part of the pipeline of my framework, so, I don't want to put them into a file.
Title: Re: How to use preprocessor for shader in loadFromMemory ???
Post by: Laurent on May 30, 2014, 07:51:05 pm
#define TO_STRING(x) #x

const std::string vertexCode =
TO_STRING
(
    #version 130
    attribute vec3 vertexPosition_modelspace;
    attribute vec3 vertex_color;
    out vec3 color;
    void main() {
        vec4 vertex = vec4(vertexPosition_modelspace.xyz, 1.0f);
        gl_Position = gl_ModelViewProjectionMatrix * vertex;
        color = vertex_color;
    };
)
Title: Re: How to use preprocessor for shader in loadFromMemory ???
Post by: Nexus on May 30, 2014, 08:01:50 pm
This will lead to problems when there are commas in the macro argument. Variadic macros (C++11) can help, but then the stringize operator can't be applied directly anymore and things get more complicated. And I'm not sure whether the line break is preserved then.

The preprocessor can be very complex when it comes to things like this, I've once written a bunch of preprocessor metaprogramming tools in Aurora (http://www.bromeon.ch/libraries/aurora/v1.0/doc/group___meta.html), and it was massive trial and error. Maybe AURORA_PP_STRINGIZE would help.
Title: Re: How to use preprocessor for shader in loadFromMemory ???
Post by: Jesper Juhl on May 30, 2014, 08:07:18 pm
Why not ditch all the complexity and preprocessor magic and just put the shader in a file of its own???
Title: Re: How to use preprocessor for shader in loadFromMemory ???
Post by: Ixrec on May 30, 2014, 08:08:46 pm
If you can use C++11, raw string literals should make this a lot easier.
Title: Re: How to use preprocessor for shader in loadFromMemory ???
Post by: Laurent on May 30, 2014, 09:28:19 pm
Quote
This will lead to problems when there are commas in the macro argument.
That's what I thought too, but I used it recently with a fragment shader containing commas, and had no problem.
Title: Re: How to use preprocessor for shader in loadFromMemory ???
Post by: Lolilolight on July 09, 2014, 02:13:20 pm
This code works for me :

 const std::string  vertexShader = TO_STRING(
           #pragma #version 130
           void main () {
                gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
                gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
                gl_FrontColor = gl_Color;
           }
        );
 

Thanks.
Title: Re: How to use preprocessor for shader in loadFromMemory ???
Post by: Lolilolight on July 09, 2014, 03:07:16 pm
Finally the solution was very simple !

const std::string depthGenFragShader = TO_STRING (
            "#version 130 \n"
            "uniform sampler2D depthBuffer;"
            "uniform sampler2D texture;"
            "uniform vec3 resolution;"
                "void main () {"
                  "vec2 position = ( gl_FragCoord.xy / resolution.xy );"
                  "vec4 color = texture2D(depthBuffer, position);"
                  "vec4 pixel = texture2D(texture, gl_TexCoord[0].xy);"
                  "if (gl_FragCoord.z > color.z && pixel.a >= color.a) {"
                      "gl_FragColor = vec4(0, 0,gl_FragCoord.z, pixel.a);"
                  "} else {"
                     "gl_FragColor = color;"
                  "}"
            "}";
 

You even don't need the use of a macro. :)