2012-12-14 9 views
14

vorrei dichiarare stringhe GLSL di shader in linea con macro in stringa:GCC, stringificazione e GLSL in linea?

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

Questo costruisce e funziona benissimo con VS2010, ma non riesce a compilare il gcc con:

error: invalid preprocessing directive #version 

C'è un modo per usare la stringificazione come questa in modo portatile?

Sto cercando di evitare per linea Citazioni:

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

... e/o di continuazione di riga:

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

risposta

16

Sfortunatamente, avente le direttive del preprocessore nell'argomento di una macro è indefinito, così non puoi farlo direttamente Ma fino a quando nessuno dei vostri shaders bisogno di direttive del preprocessore diversi #version, si potrebbe fare qualcosa di simile:

#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

Mi piace prendere di mira GLSL non esteso, quindi funziona alla grande! Grazie! – genpfault

22

si può utilizzare C++ 11? Se è così si potrebbe usare raw string literals:

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

Non c'è bisogno di fughe o ritorni a capo espliciti. Queste stringhe iniziano con una R (o r). È necessario un delimitatore (ho scelto END) tra la citazione e la prima parentesi per evitare le parentesi che hai nel frammento di codice.

+0

Questo è in gran parte per la razionalizzazione [SSCCE] (http://sscce.org/) programmi/esempi qui su SO quindi nell'interesse della portabilità vorrei evitare di C++ 11. – genpfault

+8

Eccellente suggerimento. Gli shader GLSL e i kernel OpenCL sono uno dei migliori casi d'uso per i letterali stringhe raw. Ma nota che il delimitatore non è strettamente necessario, può essere solo vuoto, solo il 'R"() "' è obbligatorio. –

+0

@ChristianRau Hai ragione. Ho solo bisogno della FINE per sfuggire a un letterale) "non solo). – emsr

3

Per raggiungere questo scopo ho usato sed. Ho file separati con GLSL che modifico (con l'evidenziazione della sintassi corretta), e nello stesso tempo GLSL inline in C++. Non molto multipiattaforma, ma con msys funziona sotto Windows.

Nel codice C++:

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

Il problema è dovuto alle macro di pre-elaborazione gcc significato per GLSL. Ho lavorato per me con l'uso di stringify standard e le direttive per il preprocessore di escape con nuove righe nel codice GLSL.

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