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
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())