Différences entre AGSL et GLSL

AGSL et GLSL ont une syntaxe très similaire, ce qui permet de transférer de nombreux effets de nuanceur de fragments GLSL à Android avec un minimum de modifications. AGSL corrige son ensemble de fonctionnalités GLSL sur GLSL ES 1.0 (le langage de ombrage utilisé par OpenGL ES 2.0) afin d'assurer une portée maximale de l'appareil.

Un nuanceur de fragments GLSL contrôle l'intégralité du comportement du GPU entre le rastériseur et le matériel de combinaison. Ce nuanceur effectue tout le travail pour calculer une couleur, et la couleur qu'il génère est celle qui est transmise à l'étape de combinaison du pipeline. Lorsque vous écrivez un nuanceur en AGSL, vous programmez une étape du pipeline graphique Android. De nombreuses différences linguistiques en découlent.

Exécution du nuanceur

Tout comme dans un nuanceur GLSL, un nuanceur AGSL commence l'exécution dans une fonction principale. Contrairement au GLSL, la fonction utilise la position du nuanceur en coordonnées "locales" comme paramètre. Cette valeur est semblable à gl_FragCoord, mais au lieu des coordonnées du framebuffer, il est possible que ces coordonnées aient été traduites avant l'appel du nuanceur. Votre nuanceur renvoie ensuite la couleur du pixel sous forme de vec4 avec une précision moyenne ou élevée (semblable à out vec4 color ou gl_FragColor en GLSL).

mediump vec4 main(in vec2 fragCoord)

Espace de coordonnées

Espaces de coordonnées GLSL et AGSL

Nuanceur dessiné en GLSL et nuanceur presque identique dessiné à l'aide d'AGSL

Par défaut, AGSL et GLSL utilisent des espaces de coordonnées différents. En GLSL, les coordonnées du fragment (fragCoord) sont relatives à l'angle inférieur gauche. AGSL correspond au système de coordonnées de l'écran de Canvas, ce qui signifie que l'axe Y commence par l'angle supérieur gauche. Si nécessaire, vous pouvez effectuer une conversion entre ces deux espaces en transmettant la résolution en tant que variable uniforme et en utilisant resolution.y - fragCoord.y comme valeur de l'axe Y. Vous pouvez également appliquer une matrice de transformation locale à votre nuanceur.

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

Précision et types

Les modificateurs de précision compatibles avec le GLSL sont acceptés, mais AGSL introduit les types half et short, qui représentent également une précision moyenne.

Les types de vecteurs peuvent être déclarés comme nommés <type de base><columns>. Vous pouvez utiliser float2 au lieu de vec2 et bool4 au lieu de bvec4. Les types de matrices peuvent être déclarés comme nommés <type de base><columns>x<rows>. Ainsi, float3x3 au lieu de mat3. AGSL autorise également les déclarations de style GLSL pour mat et vec. Ces types sont mappés à leurs équivalents à virgule flottante.

Préprocesseur

AGSL n'est pas compatible avec les instructions de préprocesseur de style GLSL. Convertissez les instructions #define en variables const. Le compilateur d'AGSL prend en charge le pliage constant et l'élimination des branches pour les variables const. Elles seront donc efficaces.

Espaces colorimétriques

Les applications Android sont gérées par couleur. L'espace colorimétrique d'un canevas détermine l'espace colorimétrique de travail pour le dessin. Le contenu source (comme les nuanceurs, y compris BitmapShader) comporte également des espaces de couleur.

Pour certains effets, tels que l'éclairage physique précis, les calculs doivent être effectués dans un espace de couleur linéaire. Pour vous aider, AGSL fournit les fonctions intrinsèques suivantes:

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

Ces couleurs permettent de convertir les couleurs entre l'espace colorimétrique de travail et l'espace colorimétrique LINEAR_EXTENDED_SRGB d'Android. Cet espace utilise les primaires de couleur sRVB (gamme) et une fonction de transfert linéaire. Il représente les valeurs en dehors de la gamme sRVB à l'aide de valeurs de plage étendue (inférieures à 0,0 et supérieures à 1,0).

Uniformes

Comme AGSL ne sait pas si les variables uniformes contiennent des couleurs, il n'applique pas automatiquement une conversion de couleur. Vous pouvez étiqueter half4/float4/vec4 avec layout(color) pour indiquer à Android que la variable uniforme sera utilisée en tant que couleur, ce qui permettra à Android de transformer la valeur uniforme en espace de couleur de travail.

Dans AGSL, déclarez la variable uniforme comme suit:

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

Dans le code Android, vous pouvez ensuite définir la variable uniforme comme suit:

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