Darüber hinaus haben wir eine vordefinierte gl_FragColor.
Beginnen wir damit. Nein, Sie haben das nicht vordefiniert gl_FragColor. Das wurde aus OpenGL 3.1 und höher entfernt. Es sei denn, Sie verwenden Kompatibilität (in diesem Fall sollten Ihre 3.30-Shader sagen#version 330 compatibility oben stehen), sollten Sie diese niemals verwenden.
Zurück zu den benutzerdefinierten Fragment-Shader-Ausgaben. Aber zuerst eine kurze Analogie.
Erinnern Sie sich, wie Sie in Vertex-Shadern Eingaben haben? Und diese Eingänge repräsentieren Vertexattribut - Indizes, die Zahlen , die Sie passieren zu glVertexAttribPointerund glEnableVertexAttribArrayund so weiter? Sie legen fest, welche Eingabe von welchem Attribut abgerufen wird. In GLSL 3.30 verwenden Sie diese Syntax:
layout(location = 2) in color;
Dadurch wird festgelegt, dass die colorVertex-Shader-Eingabe von Attributposition 2 stammt. Vor 3.30 (oder ohne ARB_explicit_attrib_location) müssten Sie dies entweder explizit mit einrichten, glBindAttrbLocationbevor Sie das Programm verknüpfen, oder das Programm nach dem Attributindex abfragen glGetAttribLocation. Wenn Sie keinen expliziten Attributspeicherort angeben, weist GLSL einen Speicherort willkürlich zu (dh auf implementierungsdefinierte Weise).
Das Einstellen im Shader ist fast immer die bessere Option.
In jedem Fall funktionieren Fragment-Shader-Ausgaben fast genauso. Fragment-Shader können in mehrere Ausgabefarben schreiben , die selbst mehreren Puffern im Framebuffer zugeordnet werden . Daher müssen Sie angeben, welche Ausgabe an welche Fragmentausgabefarbe gesendet wird.
Dieser Prozess beginnt mit dem Wert des Fragmentausgabestandorts. Es ist sehr ähnlich zu den Vertex-Shader-Eingabepositionen eingestellt:
layout(location = 1) out secColor;
Es gibt auch die API-Funktionen glBindFragDataLocationund glGetFragDataLocation, die analog zu glBindAttribLocationund sindglGetAttribLocation .
Wenn Sie keine expliziten Zuweisungen vornehmen, weisen Implementierungen normalerweise eine Ihrer Ausgabevariablen Position 0 zu. Der OpenGL-Standard erfordert dies jedoch nicht dieses Verhalten , sodass Sie sich auch nicht darauf verlassen sollten.
Um fair zu sein, sollte Ihr Programm nicht verknüpft werden können, wenn Sie zwei Ausgaben verwendet haben, die keine unterschiedlichen Ausgabestellen erhalten haben. Was wahrscheinlich passiert ist, war, dass Ihr Compiler den optimiert hat, an den Sie nicht geschrieben haben, sodass er es irgendwie vergessen hat, als es an der Zeit war, nach Linkerfehlern zu suchen.