Diferenças entre AGSL e GLSL

A AGSL e a GLSL são muito semelhantes em sintaxe, permitindo que muitos efeitos de sombreador de fragmentos GLSL sejam trazidos para o Android com mudanças mínimas. A AGSL corrige o conjunto de recursos GLSL na GLSL ES 1.0 (a linguagem de sombreamento usada pelo OpenGL ES 2.0) para fornecer o alcance máximo do dispositivo.

Um sombreador de fragmentos GLSL controla todo o comportamento da GPU entre o rasterizador e o hardware de combinação. Esse sombreador faz todo o trabalho para calcular uma cor, e a cor que ele gera é exatamente o que é alimentado no estágio de mistura do pipeline. Ao programar um sombreador na AGSL, você programa um estágio do pipeline de gráficos do Android. Muitas das diferenças linguísticas são decorrentes disso.

Execução do sombreador

Assim como em um sombreador GLSL, um sombreador da AGSL inicia a execução em uma função principal. Ao contrário da GLSL, a função usa a posição do sombreador em coordenadas "locais" como um parâmetro. Esse processo é semelhante a gl_FragCoord, mas, em vez das coordenadas do framebuffer, essas coordenadas podem ter sido convertidas antes de chamar o sombreador. Em seguida, o sombreador retorna a cor do pixel como um vec4 com precisão média ou alta (semelhante a out vec4 color ou gl_FragColor em GLSL).

mediump vec4 main(in vec2 fragCoord)

Espaço das coordenadas

Espaços coordenados de GLSL x AGSL

Shader renderizado usando GLSL em comparação com Shader quase idêntico renderizado usando AGSL

A AGSL e a GLSL usam espaços de coordenadas diferentes por padrão. Em GLSL, a coordenada do fragmento (fragCoord) é relativa ao canto inferior esquerdo. A AGSL corresponde ao sistema de coordenadas de tela de Canvas, o que significa que o eixo Y começa no canto superior esquerdo. Se necessário, é possível converter entre esses dois espaços transmitindo a resolução como um uniforme e usando resolution.y - fragCoord.y para o valor do eixo Y. Como alternativa, é possível aplicar uma matriz de transformação local ao seu sombreador.

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

Precisão e tipos

Há suporte para modificadores de precisão compatíveis com GLSL, mas a AGSL introduz os tipos half e short, que também representam precisão média.

Os tipos de vetores podem ser declarados com o nome <base type><columns>. Você pode usar float2 em vez de vec2 e bool4 em vez de bvec4. Os tipos de matriz podem ser declarados com o nome <base type><columns>x<rows>, portanto, float3x3 em vez de mat3. A AGSL também permite declarações no estilo GLSL para mat e vec, e esses tipos são mapeados para os equivalentes de ponto flutuante.

Pré-processador

A AGSL não é compatível com diretivas de pré-processador de estilo de GLSL. Converter instruções #define em variáveis constantes. O compilador da AGSL oferece suporte a dobras constantes e eliminação de ramificações para variáveis const. Portanto, elas serão eficientes.

Espaços de cor

Os aplicativos Android são gerenciados por cor. O espaço de cores de um canvas determina o espaço de cores que funciona para desenhar. O conteúdo de origem (como sombreadores, incluindo BitmapShader) também tem espaços de cor.

Para determinados efeitos, como iluminação fisicamente precisa, a matemática precisa ser feita em um espaço de cor linear. Para ajudar nisso, a AGSL fornece estas funções intrínsecas:

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

Eles convertem cores entre o espaço de cores de trabalho e o espaço de cores LINEAR_EXTENDED_SRGB do Android. Esse espaço usa as cores primárias sRGB (gamut) e uma função de transferência linear. Ele representa valores fora da gama sRGB usando valores de intervalo ampliados (abaixo de 0,0 e acima de 1,0).

Uniformes

Como a AGSL não sabe se os uniformes contêm cores, ela não vai aplicar automaticamente uma conversão de cor a eles. Você pode rotular half4/float4/vec4 com layout(color), o que informa ao Android que o uniforme será usado como uma cor, permitindo que o Android transforme o valor uniforme no espaço de cores de trabalho.

Na AGSL, declare o uniforme da seguinte maneira:

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

No código do Android, você pode definir o uniforme da seguinte forma:

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