2012-12-14 9 views
14

Ich möchte Strings GLSL Shader erklären Inline-Makro stringification mit:GCC, Stringification und Inline GLSL?

#define STRINGIFY(A) #A 
const GLchar* vert = STRINGIFY(
#version 120\n 
attribute vec2 position; 
void main() 
{ 
    gl_Position = vec4(position, 0.0, 1.0); 
} 
); 

Dies baut und läuft gut VS2010 verwenden, aber nicht auf gcc mit kompilieren:

error: invalid preprocessing directive #version 

Gibt es eine Möglichkeit zu Verwenden Sie die Stringifizierung auf eine tragbare Weise?

Ich versuche, pro-line zu vermeiden zitiert:

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

... und/oder Linienfortsetzungs:

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

Antwort

16

Leider Präprozessordirektiven im Argument eines Makros mit undefiniert, so Du kannst das nicht direkt machen. Aber solange keine Ihrer Shadern Präprozessordirektiven andere als #version benötigen, könnten Sie so etwas wie:

#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

Ich mag es, auf nicht erweiterte GLSL zu zielen, also funktioniert das großartig! Danke! – genpfault

22

Können Sie verwenden C++ 11? Wenn dies der Fall könnten Sie raw string literals verwenden:

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

Keine Notwendigkeit für Fluchten oder explizite Zeilenumbrüchen. Diese Strings beginnen mit einem R (oder r). Sie benötigen ein Trennzeichen (ich wählte ENDE) zwischen dem Anführungszeichen und der ersten Klammer, um Klammern zu entkommen, die Sie im Code-Ausschnitt haben.

+0

Dies ist vor allem für die Straffung [SSCCE] (http://sscce.org/) Programme/Beispiele hier auf SO so im Interesse der Portabilität Ich mag C 11 ++ vermeiden. – genpfault

+8

Ausgezeichneter Vorschlag. GLSL-Shader und OpenCL-Kernel sind eine der besten Anwendungsfälle für Raw-String-Literale. Aber beachten Sie, dass das Trennzeichen nicht unbedingt notwendig ist, es kann nur leer sein, nur das "R"() "ist obligatorisch. –

+0

@ChristianRau Du hast Recht. Ich brauche nur das ENDE, um einem Literal zu entgehen) "nicht nur). – emsr

3

Um diesen Zweck zu erreichen, habe ich sed. Ich habe separate Dateien mit GLSL, die ich bearbeite (mit korrekter Syntax-Hervorhebung), und gleichzeitig GLSL in C++ inline. Nicht sehr plattformübergreifend, aber mit msys funktioniert es unter 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 
5

Das Problem aufgrund gcc Vorverarbeitung ist Makros für GLSL gemeint. Die Verwendung von Standard-Preprocessor-Direktiven mit neuen Zeilen im GLSL-Code funktionierte für mich.

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