AGSL 与 GLSL 之间的区别

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 colorgl_FragColor)。

mediump vec4 main(in vec2 fragCoord)

坐标空间

GLSL 与 AGSL 坐标空间的比较

使用 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 引入了 halfshort 类型,它们也表示中等精度。

矢量类型可声明为命名的 <base type><columns>。您可以使用 float2(而非 vec2)和 bool4(而非 bvec4)。 矩阵类型可声明为命名 <base type><columns>x<rows>,因此 float3x3,而非 mat3。AGSL 还允许使用 GLSL 样式的声明 的 matvec,并且这些类型映射到其浮点 等效项。

预处理器

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