2012-12-14 9 views
14

Tôi muốn tuyên bố chuỗi GLSL shader inline sử dụng stringification vĩ mô:GCC, xâu chuỗi và nội tuyến 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); 
} 
); 

này được xây dựng và chạy tốt sử dụng VS2010 nhưng thất bại trong việc biên dịch trên gcc với:

error: invalid preprocessing directive #version 

Có cách nào để sử dụng stringification như thế này một cách di động?

Tôi đang cố gắng để tránh mỗi dòng trích dẫn:

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

... và/hoặc tiếp tục dòng:

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

Trả lời

16

Thật không may, có chỉ thị tiền xử lý trong đối số của macro là undefined, vì vậy bạn không thể làm điều này trực tiếp. Nhưng chừng nào không ai trong số shaders bạn cần chỉ thị tiền xử lý khác hơn #version, bạn có thể làm một cái gì đó như:

#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

Tôi thích nhắm mục tiêu mở rộng GLSL để công trình này tuyệt vời! – genpfault

22

Bạn có thể sử dụng C++ 11? Nếu có, bạn có thể sử dụng raw string literals:

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

Không cần thoát hoặc dòng mới rõ ràng. Các chuỗi này bắt đầu bằng R (hoặc r). Bạn cần một dấu phân cách (tôi đã chọn END) giữa dấu ngoặc kép và dấu ngoặc đơn đầu tiên để thoát khỏi dấu ngoặc đơn mà bạn có trong đoạn mã.

+0

Điều này chủ yếu để tinh giản các chương trình/ví dụ về SSCCE (http://sscce.org/) ở đây trên SO vì lợi ích của tính di động mà tôi muốn tránh C++ 11. – genpfault

+8

Đề xuất tuyệt vời. Trình tạo bóng GLSL và hạt nhân OpenCL là một trong những trường hợp sử dụng tốt nhất cho các chuỗi ký tự thô. Nhưng lưu ý rằng dấu phân cách không phải là cần thiết, nó chỉ có thể rỗng, chỉ có 'R"() "' là bắt buộc. –

+0

@ChristianRau Bạn nói đúng. Tôi chỉ cần END để thoát khỏi một chữ) "không chỉ") – emsr

3

Để đạt được mục đích này, tôi đã sử dụng sed. Tôi có các tệp riêng biệt với GLSL mà tôi chỉnh sửa (với đánh dấu cú pháp thích hợp), và trong cùng một thời gian GLSL được nêu trong C++. Không phải rất nhiều nền tảng, nhưng với msys nó hoạt động dưới cửa sổ.

Trong C++:

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

Trong 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

Vấn đề là do macro tiền xử lý gcc có nghĩa là cho GLSL. Sử dụng tiêu chuẩn stringify và thoát chỉ thị tiền xử lý với các dòng mới trong mã GLSL đã làm việc cho tôi.

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