21

マクロ文字列化を使用して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 );
}
);

これは、VS2010を使用して正常にビルドおよび実行されますが、次のコマンドでコンパイルできませんgcc

error: invalid preprocessing directive #version

このような文字列化をポータブルに使用する方法はありますか?

行ごとの引用符を避けようとしています:

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

...および/または行の継続:

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

5 に答える 5

27

C ++ 11を使用できますか?もしそうなら、生の文字列リテラルを使用できます:

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

エスケープや明示的な改行は必要ありません。これらの文字列はR(またはr)で始まります。コードスニペットにある括弧をエスケープするには、引用符と最初の括弧の間に区切り文字(ENDを選択)が必要です。

于 2012-12-14T04:19:28.467 に答える
20

残念ながら、マクロの引数にプリプロセッサディレクティブを含めることは定義されていないため、これを直接行うことはできません。ただし、シェーダーのいずれにもが以外のプリプロセッサーディレクティブを必要としない限り、次の#versionようなことができます。

#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 );
    }
);
于 2012-12-14T07:40:03.783 に答える
5

この目的を達成するために、私はsedを使用しました。私は(適切な構文の強調表示を使用して)編集するGLSLを使用して個別のファイルを作成し、同時にC++でインライン化されたGLSLを使用しています。クロスプラットフォームではありませんが、msysを使用するとWindowsで動作します。

C ++コードの場合:

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

Makefileの場合:

shader_processed.vert: shader.vert
    sed -f shader.sed shader.vert > shader_processed.vert

programm: shader_processed.vert main.cpp
    g++ ...

シェーダー.sed

s|\\|\\\\|g
s|"|\\"|g
s|$|\\n"|g
s|^|"|g
于 2012-12-14T07:38:06.913 に答える
5

この問題は、GLSL用のgcc前処理マクロが原因です。標準のstringifyを使用し、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 );
}
);
于 2013-07-09T07:17:21.727 に答える
0

別のアプローチ:ヘッダーファイルをインクルードしますが、.glsl拡張子は付けます。

たとえば、というファイルがありますbar.h.glsl。それは私の頂点とフラグメントシェーダーコードを生のリテラルとして公開します:

#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 -----


)";

}

次に、私のソースに、ファイルを含めるだけです。

#include "bar.h.glsl"

次のようにglsl文字列にアクセスします。

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

このように、glslファイルのCコードを少し見落とす必要がありますが、ファイルを動的にロードしなくても、glsl構文の強調表示を最大限に活用できます。

于 2020-05-08T08:05:13.613 に答える