Unterschiede zwischen AGSL und GLSL

AGSL und GLSL haben eine sehr ähnliche Syntax, sodass viele GLSL-Fragment-Shader-Effekte mit minimalen Änderungen für Android übernommen werden können. AGSL korrigiert seinen GLSL-Funktionssatz auf GLSL ES 1.0, die von OpenGL ES 2.0 verwendete Schattierungssprache, um eine maximale Gerätereichweite zu erzielen.

Ein GLSL-Fragment-Shader steuert das gesamte Verhalten der GPU zwischen dem Raster und der zu verbindenden Hardware. Dieser Shader erledigt die ganze Arbeit, um eine Farbe zu berechnen. Die von ihm erzeugte Farbe wird genau in die Mischphase der Pipeline eingespeist. Wenn Sie einen Shader in AGSL schreiben, programmieren Sie eine Phase der Android-Grafikpipeline. Viele der Sprachunterschiede ergeben sich daraus.

Shader-Ausführung

Genau wie bei einem GLSL-Shader beginnt ein AGSL-Shader mit der Ausführung in einer Hauptfunktion. Im Gegensatz zu GLSL verwendet die Funktion die Shader-Position in "lokalen" Koordinaten als Parameter. Dies ist ähnlich wie gl_FragCoord, allerdings wurden diese Koordinaten möglicherweise vor dem Aufruf des Shaders übersetzt, aber nicht die Framebuffer-Koordinaten. Der Shader gibt dann die Pixelfarbe als vec4 mit mittlerer oder hoher Genauigkeit zurück (ähnlich wie out vec4 color oder gl_FragColor in GLSL).

mediump vec4 main(in vec2 fragCoord)

Koordinatenbereich

GLSL- und AGSL-Koordinatenbereiche

Schattierung mit GLSL gezeichnet im Vergleich zu nahezu identischem Shader mit AGSL gezeichnet

AGSL und GLSL verwenden standardmäßig unterschiedliche Koordinatenräume. In GLSL ist die Fragmentkoordinate (fragCoord) relativ zur linken unteren Ecke. AGSL entspricht dem Bildschirmkoordinatensystem von Canvas, was bedeutet, dass die Y-Achse mit der oberen linken Ecke beginnt. Bei Bedarf können Sie zwischen diesen beiden Leerzeichen konvertieren. Übergeben Sie dazu die Auflösung einheitlich und verwenden Sie resolution.y - fragCoord.y für den Wert der Y-Achse. Alternativ können Sie eine lokale Transformationsmatrix auf Ihren Shader anwenden.

// AGSL to GLSL coordinate space transformation matrix
val localMatrix = Matrix()
localMatrix.postScale(1.0f, -1.0f)
localMatrix.postTranslate(0.0f, viewHeight)
gridShader.setLocalMatrix(localMatrix)

Genauigkeit und Typen

GLSL-kompatible Präzisionsmodifikatoren werden unterstützt, aber AGSL führt die Typen half und short ein, die auch eine mittlere Genauigkeit darstellen.

Vektortypen können als <Basistyp><Spalten> deklariert werden. Sie können float2 anstelle von vec2 und bool4 anstelle von bvec4 verwenden. Matrixtypen können als <Basistyp><Spalten>x<Zeilen> bezeichnet werden, also float3x3 anstelle von mat3. AGSL ermöglicht auch Deklarationen im GLSL-Stil für mat und vec. Diese Typen werden ihren Gleitkommazahlen-Äquivalenten zugeordnet.

Präprozessor

AGSL unterstützt keine Vorprozessor-Anweisungen im GLSL-Stil. Wandeln Sie #define-Anweisungen in const-Variablen um. Der Compiler von AGSL unterstützt die konstante Faltung und die Eliminierung von Zweigen für Const-Variablen, sodass diese effizient sind.

Farbräume

Android-Apps werden farblich verwaltet. Der Farbraum eines Canvas bestimmt den Arbeitsfarbraum beim Zeichnen. Quellinhalte (wie Shader, einschließlich BitmapShader) haben ebenfalls Farbräume.

Für bestimmte Effekte, z. B. physisch korrekte Beleuchtung, sollten die Berechnungen in einem linearen Farbraum erfolgen. Zu diesem Zweck bietet AGSL die folgenden unveränderlichen Funktionen:

half3 toLinearSrgb(half3 color)
half3 fromLinearSrgb(half3 color)

Damit werden die Farben zwischen dem funktionierenden Farbraum und dem LINEAR_EXTENDED_SRGB-Farbraum von Android konvertiert. Für diesen Bereich werden die sRGB-Farbräume (Gamut) und eine lineare Übertragungsfunktion verwendet. Sie stellt Werte außerhalb des sRGB-Gamuts mithilfe von Werten mit erweitertem Bereich (unter 0.0 und über 1,0) dar.

Trikotsätze

Da AGSL nicht weiß, ob Uniformen Farben enthalten, erfolgt keine automatische Farbkonvertierung. Du kannst half4/float4/vec4 mit layout(color) beschriften. So weiß Android, dass die Einheit als Farbe verwendet wird, sodass Android den Wert der Einheit in den Arbeitsfarbraum umwandeln kann.

Im AGSL musst du die Uniform so angeben:

layout(color) uniform half4 iColor;  // Input color
uniform float2 iResolution;          // Viewport resolution (pixels)

Im Android-Code können Sie die Uniform dann so festlegen:

shader.setColorUniform("iColor", Color.GREEN)
shader.setFloatUniform("iResolution", canvas.width.toFloat(), canvas.height.toFloat())