GCC, Stringifizierung und Inline-GLSL?

Lesezeit: 4 Minuten

GCC Stringifizierung und Inline GLSL
Genpfault

Ich möchte GLSL-Shader-Strings inline mit Makro-Stringifizierung deklarieren:

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

Dies wird mit VS2010 erstellt und ausgeführt, kann jedoch nicht kompiliert werden gcc mit:

error: invalid preprocessing directive #version

Gibt es eine Möglichkeit, eine solche Stringifizierung portabel zu verwenden?

Ich versuche, zeilenweise Anführungszeichen zu vermeiden:

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

…und/oder Zeilenfortsetzung:

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

1643387406 250 GCC Stringifizierung und Inline GLSL
emsr

Können Sie C++11 verwenden? Wenn ja, könnten Sie verwenden rohe Zeichenfolgenliterale:

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

Es sind keine Escapezeichen oder explizite Zeilenumbrüche erforderlich. Diese Zeichenfolgen beginnen mit einem R (oder r). Sie benötigen ein Trennzeichen (ich habe END gewählt) zwischen dem Anführungszeichen und der ersten Klammer, um der Klammer zu entkommen, die Sie im Code-Snippet haben.

  • Dies dient hauptsächlich der Rationalisierung SSCCE Programme/Beispiele hier auf SO, also möchte ich im Interesse der Portabilität C++11 vermeiden.

    – Genpfault

    14. Dezember 12 um 5:03 Uhr

  • Ausgezeichneter Vorschlag. GLSL-Shader und OpenCL-Kernel sind einer der besten Anwendungsfälle für rohe Zeichenfolgenliterale. Beachten Sie jedoch, dass das Trennzeichen nicht unbedingt erforderlich ist, es kann nur leer sein, nur das R"()" ist obligatorisch.

    – Christian Rau

    14. Dezember 2012 um 8:50 Uhr

  • @ChristianRau Du hast recht. Ich brauche das END nur, um einem wörtlichen )” zu entkommen, nicht nur ).

    – Emsr

    14. Dezember 2012 um 12:21 Uhr

  • @genpfault Oder beginne einfach mit const GLchar* vert = R"END(#version 120 ohne Zeilenumbruch. Ich habe meine Antwort nur so geschrieben, damit sie schöner aussieht. (Mir).

    – Emsr

    19. Februar 19 um 23:01 Uhr


  • @genpfault: Klingt so, als würden sie die Spezifikation nicht genau befolgen, da sie besagt: “Die Direktive #version muss vor allem anderen in einem Shader vorkommen, außer bei Kommentaren und Leerzeichen.”, und Zeilenumbrüche sind Leerzeichen.

    – Chris Dodd

    23. September 19 um 17:50 Uhr

Leider ist das Vorhandensein von Präprozessordirektiven im Argument eines Makros nicht definiert, sodass Sie dies nicht direkt tun können. Aber solange keiner Ihrer Shader andere Präprozessordirektiven benötigt als #version, könntest du so etwas tun:

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

  • Ich ziele gerne auf nicht erweitertes GLSL ab, also funktioniert das großartig! Danke!

    – Genpfault

    14. Dezember 12 um 18:59 Uhr

Um diesen Zweck zu erreichen, habe ich sed verwendet. Ich habe separate Dateien mit GLSL, die ich bearbeite (mit richtiger Syntaxhervorhebung), und gleichzeitig ist GLSL in C++ eingebettet. Nicht sehr plattformübergreifend, aber mit msys funktioniert es unter Windows.

Im C++-Code:

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

Im 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

Das Problem liegt an gcc-Vorverarbeitungsmakros, die für GLSL gedacht sind. Die Verwendung von Standard-Stringify- und Escaping-Präprozessordirektiven mit neuen Zeilen im GLSL-Code hat für mich funktioniert.

#define STRINGIFY(A)  #A

const GLchar* vert = STRINGIFY(

n#version 120n
n#define MY_MACRO 999n

attribute vec2 position;
void main()
{
    gl_Position = vec4( position, 0.0, 1.0 );
}
);

GCC Stringifizierung und Inline GLSL
Mattijs

Ein alternativer Ansatz: Binden Sie eine Header-Datei ein, aber mit einer .glsl Verlängerung.

Zum Beispiel habe ich eine Datei namens bar.h.glsl. Es legt meinen Vertex- und Fragment-Shader-Code als Rohliterale offen:

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


)";

}

Dann füge ich in meine Quelle einfach die Datei ein:

#include "bar.h.glsl"

und greifen Sie wie folgt auf die glsl-Strings zu:

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

Obwohl ich in meinen glsl-Dateien ein wenig C-Code übersehen muss, erhalte ich auf diese Weise das Beste aus der glsl-Syntaxhervorhebung, ohne die Datei dynamisch laden zu müssen.

.

676760cookie-checkGCC, Stringifizierung und Inline-GLSL?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy