AGSL 旨在与 GLSL ES 1.0 基本兼容。如需了解详情,请参阅 OpenGL ES 着色语言文档中的等效函数。本文档会尽可能指出 AGSL 与 GLSL 之间的差异。
类型
AGSL 支持 GLSL ES 1.0 类型,以及表示矢量和矩阵类型的其他方式。AGSL 支持其他 short 和 half 类型来表示中等精度。
基本类型
| 类型 | 说明 | 
|---|---|
| void | 没有函数返回值或参数列表为空。与 GLSL 不同,没有 void 返回值类型的函数必须返回一个值。 | 
| bool, bvec2, bvec3, bvec4(bool2, bool3, bool4)。 | 布尔标量/矢量 | 
| int, ivec2, ivec3, ivec4(int2, int3, int4) | highp有符号整数/矢量 | 
| float, vec2, vec3, vec4(float2, float3, float4) | highp(单精度)浮点标量/矢量 | 
| short, short2, short3, short4 | 等同于 mediump int有符号整数/矢量 | 
| half, half2, half3, half4 | 等同于 mediump float标量/矢量 | 
| mat2, mat3, mat4(float2x2, float3x3, float4x4) | 2x2、3x3、4x4 float矩阵 | 
| half2x2, half3x3, half4x4 | 等同于 mediump float矩阵类型 | 
精度和范围最小值
这些是根据 OpenGL ES 2.0 规范与每个修饰符关联的保证最小精度和范围。由于大多数设备都支持 ES 3.0,因此它们的 highp 精度/范围和 int mediump 范围更有保证。精度修饰符可应用于标量、向量和矩阵变量和参数。我们只能保证下列最小值;lowp 实际上不一定比 mediump 的精度低,mediump 也不一定比 highp 的精度低。AGSL 目前会在最终输出中将 lowp 转换为 mediump。
| 修饰符 | 'float' 范围 | “float”幅度范围 | 'float' 精度 | 'int' 范围 | 
|---|---|---|---|---|
| highp | \(\left\{-2^{62},2^{62}\right\}\) | \(\left\{2^{-62},2^{62}\right\}\) | 相对: \(2^{-16}\) | \(\left\{-2^{16},2^{16}\right\}\) | 
| mediump | \(\left\{-2^{14},2^{14}\right\}\) | \(\left\{2^{-14},2^{14}\right\}\) | 相对: \(2^{-10}\) | \(\left\{-2^{10},2^{10}\right\}\) | 
| lowp | \(\left\{-2,2\right\}\) | \(\left\{2^{-8},2\right\}\) | 绝对值: \(2^{-8}\) | \(\left\{-2^{8},2^{8}\right\}\) | 
除了数组数字下标语法(例如 var[num])之外,长度为 2-4 的矢量的矢量分量名称由单个字母表示。组件可以进行交换和复制。例如:vect.yx、vect.yy
vect.xyzw - 在访问表示点/法向量的矢量时使用
vect.rgba - 在访问表示颜色的矢量时使用
vect.LTRB - 当矢量表示矩形时使用(不适用于 GLSL)
在 AGSL 中,0 和 1 可用于在相应通道中生成常量 0 或 1。例如:vect.rgb1 == vec4(vect.rgb,1)
结构体和数组
结构体使用与 GLSL 相同的语法进行声明,但 AGSL 仅支持全局范围的结构体。
struct type-name {
 members
} struct-name; // optional variable declaration.
仅支持使用 C 风格或 GLSL 风格语法指定显式数组大小的一维数组:
<base type>[<array size>] 变量名称 - 例如:half[10] x;
<基准类型> 变量名称 [<数组大小>] - 例如:half x[10];
无法从函数返回、复制、赋值或比较数组。数组限制会传播到包含数组的结构。数组只能使用常量或循环变量编制索引。
资格赛
| 类型 | 说明 | 
|---|---|
| const | 编译时常量或只读函数参数。 | 
| uniform | 值在处理的每个基元中都不会发生变化。系统使用 RuntimeShader 方法针对 setColorUniform、setFloatUniform、setIntUniform、setInputBuffer和setInputShader从 Android 传递均匀值。 | 
| in | 对于传入的函数参数。这是默认值。 | 
| out | 对于传出的函数参数。必须使用与函数定义相同的精度。 | 
| inout | 对于同时传入和传出函数的参数。必须使用与函数定义相同的精度。 | 
变量声明
声明必须位于显式大括号作用域中。以下示例中 y 的声明不允许:
if (condition)
    int y = 0;
矩阵/结构/数组基础知识
矩阵构造函数示例
使用单个值构建矩阵时,对对角线上的所有值赋予该值,而对其余值赋予零。因此,float2x2(1.0) 会创建一个 2x2 的单位矩阵。
使用多个值构建矩阵时,系统会先填充列(按列顺序)。
请注意,与 GLSL 不同,此语言不支持用于减少传入矢量组件数量的构造函数,但您可以使用串联来实现相同的效果。如需在 AGSL 中根据 vec4 构造行为与 GLSL 相同的 vec3,请指定 vec3 nv = quadVec.xyz。
结构体构造函数示例
struct light { float intensity; float3 pos; };
// literal integer constants auto-converted to floating point
light lightVar = light(3, float3(1, 2, 3.0));
矩阵组件
使用数组下标语法访问矩阵的组件。
float4x4 m; // represents a matrix
m[1] = float4(2.0); // sets second column to all 2.0
m[0][0] = 1.0; // sets upper left element to 1.0
m[2][3] = 2.0; // sets 4th element of 3rd column to 2.0
结构字段
使用英文句号 . 运算符选择结构体字段。运营商包括:
| 运营商 | 说明 | 
|---|---|
| . | 字段选择器 | 
| ==, != | 平等 | 
| = | 作业 | 
数组元素
使用数组下标运算符 [ ] 访问数组元素。例如:
diffuseColor += lightIntensity[3] * NdotL;
运算符
按优先顺序编号。关系运算符和等式运算符(>、<、<=、>=、==、!=)的求值结果为布尔值。如需按组件比较矢量,请使用 lessThan()、equal() 等函数。
| 运营商 | 说明 | 关联性 | |
|---|---|---|---|
| 1 | () | 括号分组 | 不适用 | 
| 2 | []  ()  .  ++ -- | 数组下标函数调用和构造函数结构字段或方法选择器、swizzle 后缀递增和递减 | 从左到右 | 
| 3 | ++ --  + - ! | 前缀递增和递减运算符 - 一元运算符 | 从右到左 | 
| 4 | * / | 乘法和除法 | 从左至右 | 
| 5 | + - | 加减 | 从左至右 | 
| 7 | < > <= >= | 关系型 | 从左至右 | 
| 8 | == != | 等式/不等式 | 从左至右 | 
| 12 | && | 逻辑与 | 从左至右 | 
| 13 | ^^ | 逻辑 XOR | 从左至右 | 
| 14 | || | 逻辑或 | 从左至右 | 
| 15 | ?\: | 选择(一个完整的运算数) | 从左到右 | 
| 16 | =   += -=   *= /= | 赋值 算术赋值 算术赋值 | 从左到右 | 
| 17 | , | 序列 | 从左至右 | 
矩阵和矢量运算
应用于标量值时,算术运算符会产生标量值。对于除取模运算符以外的运算符,如果一个操作数是标量,另一个操作数是矢量或矩阵,则运算会按分量执行,并产生相同的矢量或矩阵类型。如果这两个操作都是大小相同的矢量,则按组件执行运算(并返回相同的矢量类型)。
| 操作 | 说明 | 
|---|---|
| m = f * m | 按元素对矩阵与标量值进行相乘 | 
| v = f * v | 按分量对向量进行标量值乘法 | 
| v = v * v | 按分量对矢量值进行矢量乘法 | 
| m = m + m | 矩阵逐分加法 | 
| m = m - m | 矩阵分量级减法 | 
| m = m * m | 线性代数乘法 | 
如果一个运算数是与矩阵的行或列大小匹配的矢量,则可以使用乘法运算符进行代数行和列乘法。
| 操作 | 说明 | 
|---|---|
| m = v * m | 行矢量 * 矩阵线性代数乘法 | 
| m = m * v | 矩阵 * 列向量线性代数乘法 | 
使用内置函数计算矢量点积、叉积和分量乘法:
| 功能 | 说明 | 
|---|---|
| f = dot(v, v) | 矢量点积 | 
| v = cross(v, v) | 矢量叉积 | 
| m = matrixCompMult(m, m) | 按分量相乘 | 
程序控制
| 函数调用 | 按值返回调用 | 
|---|---|
| 迭代 | for (<init>;<test>;<next>){ break, continue } | 
| 选择 | if ( ) { }if ( ) { } else { }switch () { break, case }- 默认情况下,最后一个是正例 | 
| 跳跃 | break, continue, return(不允许舍弃) | 
| 条目 | half4 main(float2 fragCoord) | 
For 循环限制
与 GLSL ES 1.0 类似,“for”循环非常有限;编译器必须能够展开循环。这意味着,初始化程序、测试条件和 next 语句必须使用常量,以便在编译时计算所有内容。next 语句进一步限制为使用 ++, --, +=, or -=。
内建函数
GT(通用类型)是 float、float2、float3、float4 或 half、half2、half3、half4。
其中的大多数函数都是按组件运作的(即按组件应用函数)。如果不是,则会注明。
角度和三角函数
将函数参数指定为角度时,假定其单位为弧度。在任何情况下,这些函数都不会导致除数为零的错误。如果比率的分母为 0,则结果将不定义。
| 功能 | 说明 | 
|---|---|
| GT radians(GT degrees) | 将角度转换为弧度 | 
| GT degrees(GT radians) | 将弧度转换为角度 | 
| GT sin(GT angle) | 标准正弦 | 
| GT cos(GT angle) | 标准余弦 | 
| GT tan(GT angle) | 标准切线 | 
| GT asin(GT x) | 返回正弦为 x 且在 $ \left[-{\pi\over 2},{\pi\over 2}\right] $ 范围内的角度 | 
| GT acos(GT x) | 返回余弦值为 $ \left[0,\pi\right] $ 范围内的 x 的角度 | 
| GT atan(GT y, GT x) | 返回一个角,其三角函数反正割值为 $ \left[{y\over x}\right] $,且在 $ \left[-\pi,\pi\right] $ 范围内 | 
| GT atan(GT y_over_x) | 返回一个角,其三角函数反正切值为 y_over_x,且在 $ \left[-{\pi\over 2},{\pi\over 2}\right] $ 范围内 | 
指数函数
| 功能 | 说明 | 
|---|---|
| GT pow(GT x, GT y) | 返回 $ x^y $ | 
| GT exp(GT x) | 返回 $ e^x $ | 
| GT log(GT x) | 返回 $ ln(x) $ | 
| GT exp2(GT x) | 返回 $ 2^x $ | 
| GT log2(GT x) | 返回 $ log_2(x) $ | 
| GT sqrt(GT x) | 返回 $ \sqrt{x} $ | 
| GT inversesqrt(GT x) | 返回 $ 1\over{\sqrt{x}} $ | 
常用函数
| 功能 | 说明 | 
|---|---|
| GT abs(GT x) | 绝对值 | 
| GT sign(GT x) | 根据 x 的符号返回 -1.0、0.0 或 1.0 | 
| GT floor(GT x) | 最接近的整数 <= x | 
| GT ceil(GT x) | 大于等于 x 的最接近整数 | 
| GT fract(GT x) | 返回 x 的小数部分 | 
| GT mod(GT x, GT y) | 返回 x 对 y 取模的值 | 
| GT mod(GT x, float y) | 返回 x 对 y 取模的值 | 
| GT min(GT x, GT y) | 返回 x 或 y 的最小值 | 
| GT min(GT x, float y) | 返回 x 或 y 的最小值 | 
| GT max(GT x, GT y) | 返回 x 或 y 的最大值 | 
| GT max(GT x, float y) | 返回 x 或 y 的最大值 | 
| GT clamp(GT x, GTminVal, GT maxVal) | 返回将 x 限制在 minVal 和 maxVal 之间的值。 | 
| GT clamp(GT x, floatminVal, float maxVal) | 返回将 x 限制在 minVal 和 maxVal 之间的值 | 
| GT saturate(GT x) | 返回将 x 限制在 0.0 到 1.0 之间的值 | 
| GT mix(GT x, GT y,GT a) | 返回 x 和 y 的线性混合 | 
| GT mix(GT x, GT y,float a) | 返回 x 和 y 的线性混合 | 
| GT step(GT edge, GT x) | 如果 x < edge,则返回 0.0,否则返回 1.0 | 
| GT step(float edge,GT x) | 如果 x < edge,则返回 0.0,否则返回 1.0 | 
| GT smoothstep(GT edge0,GT edge1, GT x) | 当 edge0 < x < edge1 时,在 0 和 1 之间执行 Hermite 插值 | 
| GT smoothstep(floatedge0, float edge1,GT x) | 当 edge0 < x < edge1 时,在 0 和 1 之间执行 Hermite 插值 | 
几何函数
这些函数对向量执行的操作是作为向量进行的,而不是按组件进行的。GT 是大小为 2-4 的浮点/半精度矢量。
| 功能 | 说明 | 
|---|---|
| float/half length(GT x) | 返回矢量的长度 | 
| float/half distance(GTp0, GT p1) | 返回点之间的距离 | 
| float/half dot(GT x,GT y) | 返回点积 | 
| float3/half3cross(float3/half3 x,float3/half3 y) | 跨产品退货 | 
| GT normalize(GT x) | 将矢量标准化为长度为 1 | 
| GT faceforward(GT N,GT I, GT Nref) | 如果 dot(Nref, I) < 0,则返回 N,否则返回 -N。 | 
| GT reflect(GT I, GT N) | 反射方向 I - 2 * dot(N,I) * N。 | 
| GT refract(GT I, GT N,float/half eta) | 返回折射矢量 | 
矩阵函数
类型 mat 是任何方阵类型。
| 功能 | 说明 | 
|---|---|
| mat matrixCompMult(matx, mat y) | 按元素将 x 乘以 y | 
| mat inverse(mat m) | 返回 m 的倒数 | 
矢量关系函数
逐个比较 x 和 y 分量。特定调用的输入和返回矢量的大小必须一致。T 是整数和浮点向量类型的并集。BV 是一个与输入向量大小匹配的布尔向量。
| 功能 | 说明 | 
|---|---|
| BV lessThan(T x, T y) | x < y | 
| BV lessThanEqual(T x,T y) | x <= y | 
| BV greaterThan(T x,T y) | x > y | 
| BV greaterThanEqual(Tx, T y) | x >= y | 
| BV equal(T x, T y) | x == y | 
| BV equal(BV x, BV y) | x == y | 
| BV notEqual(T x, T y) | x != y | 
| BV notEqual(BV x,BV y) | x != y | 
| bool any(BV x) | 如果 x 的任何组件为 true,则为true | 
| bool all(BV x) | 如果 x 的所有分量均为 true,则为true。 | 
| BV not(BV x) | x 的逻辑补全 | 
颜色函数
| 功能 | 说明 | 
|---|---|
| vec4 unpremul(vec4color) | 将颜色值转换为未预乘的 Alpha | 
| half3 toLinearSrgb(half3color) | 颜色空间转换为线性 SRGB | 
| half3 fromLinearSrgb(half3color) | 颜色空间转换 | 
着色器采样(评估)
不支持采样器类型,但您可以评估其他着色器。如果您需要对纹理进行采样,可以创建 BitmapShader 对象,并将其添加为均匀值。您可以对任何着色器执行此操作,这意味着您可以直接评估任何 Android 着色器,而无需先将其转换为 Bitmap,包括其他 RuntimeShader 对象。这提供了极大的灵活性,但复杂着色器的评估成本可能很高,尤其是在循环中。
uniform shader image;
image.eval(coord).a   // The alpha channel from the evaluated image shader
原始缓冲区采样
虽然大多数图片包含应进行颜色管理的颜色,但有些图片包含的并非实际颜色的数据,包括存储法线、材质属性(例如粗糙度)、高度图或恰好存储在图片中的任何其他纯数学数据的图片。在 AGSL 中使用此类图片时,您可以使用 RuntimeShader#setInputBuffer 将 BitmapShader 用作通用原始缓冲区。这样可以避免色彩空间转换和滤除。
