GCC, stringification, and inline GLSL?

前端 未结 5 972
孤城傲影
孤城傲影 2020-11-29 08:37

I\'d like to declare GLSL shader strings inline using macro stringification:

#define STRINGIFY(A)  #A
const GLchar* vert = STRINGIFY(
#version 120\\n
attribu         


        
相关标签:
5条回答
  • 2020-11-29 08:57

    An alternative approach: include a header file, but with a .glsl extension.

    For example, I have a file called bar.h.glsl. It exposes my vertex and fragment shader code as raw literals:

    #pragma once
    
    namespace bar {
    
    static const char vertex[] = R"(#version 410 core
    
    
    // ----- vertex shader start -----
    layout( location = 0 ) in vec4 vPosition;
    
    uniform float Time;
    uniform float Width;
    
    void main()
    {
        float x = vPosition.x;
        float y = vPosition.y * Width;
        float yOffset = mix(sin(Time), sin(Time * 0.75), x * 0.5 + 0.5);
        gl_Position = vec4(x, y + yOffset, vPosition.z, vPosition.w);
    }
    // ------ vertex shader end ------
    
    
    )";
    static const char fragment[] = R"(#version 410 core
    
    
    // ----- fragment shader start ----
    out vec4 fragColor;
    
    void main()
    {
        fragColor = vec4(1.0, 1.0, 1.0, 1.0);
    }
    // ------ fragment shader end -----
    
    
    )";
    
    }
    

    Then in my source, I simply include the file:

    #include "bar.h.glsl"
    

    and access the glsl strings like so:

    bool success = barShader.Compile( bar::vertex, bar::fragment );
    

    This way, although I need to overlook a bit of C code in my glsl files, I get the best of glsl syntax highlighting without having to dynamically load the file.

    0 讨论(0)
  • 2020-11-29 08:58

    Unfortunately, having preprocessor directives in the argument of a macro is undefined, so you can't do this directly. But as long as none of your shaders need preprocessor directives other than #version, you could do something like:

    #define GLSL(version, shader)  "#version " #version "\n" #shader
    
    const GLchar* vert = GLSL(120,
        attribute vec2 position;
        void main()
        {
            gl_Position = vec4( position, 0.0, 1.0 );
        }
    );
    
    0 讨论(0)
  • 2020-11-29 08:59

    To achieve this purpose I used sed. I have seperate files with GLSL which I edit (with proper syntax highlighting), and in the same time GLSL in inlined in C++. Not very cross platform, but with msys it works under windows.

    In C++ code:

    const GLchar* vert = 
    #include "shader_processed.vert"
    ;
    

    In Makefile:

    shader_processed.vert: shader.vert
        sed -f shader.sed shader.vert > shader_processed.vert
    
    programm: shader_processed.vert main.cpp
        g++ ...
    

    shader.sed

    s|\\|\\\\|g
    s|"|\\"|g
    s|$|\\n"|g
    s|^|"|g
    
    0 讨论(0)
  • 2020-11-29 09:05

    Can you use C++11? If so you could use raw string literals:

    const GLchar* vert = R"END(
    #version 120
    attribute vec2 position;
    void main()
    {
        gl_Position = vec4( position, 0.0, 1.0 );
    }
    )END";
    

    No need for escapes or explicit newlines. These strings start with an R (or r). You need a delimiter (I chose END) between the quote and the first parenthesis to escape parenthesis which you have in the code snippet.

    0 讨论(0)
  • 2020-11-29 09:09

    The problem is due to gcc preprocessing macros meant for GLSL. Using standard stringify and escaping preprocessor directives with new lines in GLSL code worked for me.

    #define STRINGIFY(A)  #A
    
    const GLchar* vert = STRINGIFY(
    
    \n#version 120\n
    \n#define MY_MACRO 999\n
    
    attribute vec2 position;
    void main()
    {
        gl_Position = vec4( position, 0.0, 1.0 );
    }
    );
    
    0 讨论(0)
提交回复
热议问题