AGSL 和 GLSL 在语法上非常相似,允许使用多种 GLSL fragment 着色器 只需极少的更改即可引入 Android 平台。AGSL 修复其 GLSL GLSL ES 1.0(OpenGL ES 2.0 使用的着色语言) 最大限度地扩大设备覆盖面
GLSL fragment 着色器控制 GPU 的 光栅化处理程序和混合硬件该着色器会完成 它生成的颜色就是供给混合阶段的颜色 流水线。使用 AGSL 编写着色器时, Android 图形管道许多语言的差异都源于此。
着色器执行
就像在 GLSL 着色器中一样,AGSL 着色器开始在 main 函数中执行。
与 GLSL 不同,该函数使用“local”中的着色器位置坐标为
参数。它与 gl_FragCoord
类似,但不是帧缓冲区
坐标,在调用您的
着色器。然后,着色器会以 vec4
(中等色)或
高精度(类似于 GLSL 中的 out vec4 color
或 gl_FragColor
)。
mediump vec4 main(in vec2 fragCoord)
坐标空间
使用 GLSL 绘制的着色器与使用 AGSL 绘制的几乎相同的着色器
默认情况下,AGSL 和 GLSL 使用不同的坐标空间。在 GLSL 中,fragment 为
坐标 (fragCoord) 相对于左下角进行定义。AGSL 匹配屏幕
Canvas 的坐标系,
也就是说,Y 轴从左上角开始。如果需要,您可以
可以通过将分辨率作为 uniform 传递,在这两个空间之间进行转换
并使用 resolution.y - fragCoord.y
作为 Y 轴值。或者
可以将局部转换矩阵应用于着色器。
// AGSL to GLSL coordinate space transformation matrix
val localMatrix = Matrix()
localMatrix.postScale(1.0f, -1.0f)
localMatrix.postTranslate(0.0f, viewHeight)
gridShader.setLocalMatrix(localMatrix)
精确率和类型
支持与 GLSL 兼容的精度修饰符,但 AGSL 引入了
half
和 short
类型,它们也表示中等精度。
矢量类型可声明为命名的 <base type><columns>。您可以使用
float2
(而非 vec2
)和 bool4
(而非 bvec4
)。
矩阵类型可声明为命名 <base type><columns>x<rows>,因此
float3x3
,而非 mat3
。AGSL 还允许使用 GLSL 样式的声明
的 mat
和 vec
,并且这些类型映射到其浮点
等效项。
预处理器
AGSL 不支持 GLSL 样式 预处理器 指令。将 #define 语句转换为常量变量。AGSL 的编译器 支持针对常量变量进行常量折叠和分支消除, 效率。
颜色空间
Android 应用支持颜色管理。画布的颜色空间决定了 用于绘制的工作颜色空间源内容(例如着色器,包括 BitmapShader) 还有颜色空间
对于某些效果(例如精确的光照效果),应该先进行数学计算 线性颜色空间中的颜色。为此,AGSL 提供了这些固有的 函数:
half3 toLinearSrgb(half3 color)
half3 fromLinearSrgb(half3 color)
这些颜色可在工作颜色空间与 Android 颜色空间之间转换颜色
LINEAR_EXTENDED_SRGB
颜色空间。该空间使用 sRGB 原色(色域),以及线性
传输函数。它使用扩展符号来表示 sRGB 色域以外的值,
范围值(低于 0.0 和高于 1.0)。
制服
由于 AGSL 不知道 uniform 是否包含颜色,因此不会自动应用
转换为这些颜色。您可以使用如下标签为 half4
/float4
/vec4
添加标签:
layout(color)
,以便 Android 知道 uniform 将用作
颜色,使 Android 能够将统一的值转换为工作颜色
空间。
在 AGSL 中,按如下方式声明 uniform:
layout(color) uniform half4 iColor; // Input color
uniform float2 iResolution; // Viewport resolution (pixels)
然后,您可以在 Android 代码中按如下方式设置 uniform:
shader.setColorUniform("iColor", Color.GREEN)
shader.setFloatUniform("iResolution", canvas.width.toFloat(), canvas.height.toFloat())