AGSL 快速参考

AGSL 设计为与 GLSL ES 1.0 大致兼容。有关更多信息,请参阅OpenGL ES 着色语言文档中的等效函数。在可能的情况下,本文档尝试指出演示 AGSL 和 GLSL 之间的差异。

类型

AGSL 支持 GLSL ES 1.0 类型以及表示向量和矩阵类型的其他方式。AGSL 支持其他shorthalf 类型来表示中等精度。

基本类型

类型 描述
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\}\)

除了数组数字下标语法 ex: var[num]外,长度为 2-4 的向量的向量组件名称由单个字母表示。组件可以交换和复制。ex:vect.yxvect.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 样式语法

<基本类型>[<数组大小>] 变量名 - 例如:half[10] x;

<基本类型> 变量名[<数组大小>] - 例如:half x[10];

数组不能从函数返回、复制、赋值或比较。数组限制会传播到包含数组的结构体。数组只能使用常量或循环变量进行索引。

限定符

类型 描述
const 编译时常量或只读函数参数。
uniform 值在正在处理的图元中不会改变。统一变量通过 Android 使用 RuntimeShader 方法传递,用于setColorUniformsetFloatUniformsetIntUniformsetInputBuffersetInputShader
in 用于传入函数参数。这是默认值。
out 用于传出函数参数。必须使用与函数定义相同的精度。
inout 用于既传入又传出函数的参数。必须使用与函数定义相同的精度。

变量声明

声明必须在显式的大括号范围内。以下示例中y 的声明是不允许的

if (condition)
    int y = 0;

矩阵/结构体/数组基础知识

矩阵构造函数示例

当使用单个值构造矩阵时,对角线上的所有值都赋予该值,而其余值则赋予零。float2x2(1.0) 因此将创建一个 2x2 单位矩阵。

当使用多个值构造矩阵时,将首先填充列(列主序)。

请注意,与 GLSL 不同,减少传入向量组件数量的构造函数不受支持,但您可以使用交换来获得相同的效果。要在 AGSL 中使用与 GLSL 相同的行为从vec4 构造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 () 括号分组 N/A
2 [] () . ++ -- 数组下标函数调用 & 构造函数结构体字段或方法选择器、交换后缀增量和减量 从左到右
3 ++ -- + - ! 前缀增量和减量一元 从右到左
4 * / 乘法和除法 从左到右
5 + - 加法和减法 从左到右
7 < > <= >= 关系 从左到右
8 == != 相等/不相等 从左到右
12 && 逻辑 AND 从左到右
13 ^^ 逻辑 XOR 从左到右
14 || 逻辑 OR 从左到右
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 (<初始化>;<测试>;<下一步>)
{ break, continue }
选择 if ( ) { }
if ( ) { } else { }
switch () { break, case } - default case 最后
跳转 break, continue, return
(discard 不允许)
入口 half4 main(float2 fragCoord)

For循环限制

与GLSL ES 1.0类似,'for'循环的限制比较多;编译器必须能够展开循环。这意味着初始化语句、测试条件和next语句必须使用常量,以便在编译时计算所有内容。next语句进一步限制为使用++, --, +=, 或 -=

内置函数

GT(泛型类型)可以是floatfloat2float3float4halfhalf2half3half4

大多数这些函数按组件操作(每个组件应用该函数)。如果情况并非如此,则会进行说明。

角度和三角函数

指定为角度的函数参数假定以弧度为单位。在任何情况下,这些函数都不会导致除以零错误。如果比率的除数为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) 返回余弦值为x的角度,范围为$ \left[0,\pi\right] $
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, GT minVal, GT maxVal) 返回夹在minVal和maxVal之间的x。
GT clamp(GT x, float minVal, float maxVal) 返回夹在minVal和maxVal之间的x
GT saturate(GT x) 返回夹在0.0和1.0之间的x
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(float edge0, float edge1, GT x) 当edge0 < x < edge1时,执行0到1之间的Hermite插值

几何函数

这些函数对向量作为向量进行操作,而不是按组件进行操作。GT是大小为2-4的float/half向量。

函数 描述
float/half length (GT x) 返回向量的长度
float/half distance(GT p0, GT p1) 返回两点之间的距离
float/half dot(GT x, GT y) 返回点积
float3/half3 cross(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(mat x, 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(T x, 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(vec4 color) 将颜色值转换为非预乘alpha
half3 toLinearSrgb(half3 color) 颜色空间转换为线性SRGB
half3 fromLinearSrgb(half3 color) 颜色空间转换

着色器采样(评估)

不支持采样器类型,但您可以评估其他着色器。如果您需要采样纹理,您可以创建一个BitmapShader对象,并将其添加为uniform。您可以对任何着色器执行此操作,这意味着您可以直接评估任何Android着色器,而无需先将其转换为Bitmap,包括其他RuntimeShader对象。这提供了极大的灵活性,但复杂的着色器评估成本可能很高,尤其是在循环中。

uniform shader image;

image.eval(coord).a   // The alpha channel from the evaluated image shader

原始缓冲区采样

尽管大多数图像包含应进行颜色管理的颜色,但某些图像包含实际上并非颜色的数据,包括存储法线、材质属性(例如粗糙度)、高度图或任何其他碰巧存储在图像中的纯数学数据。在AGSL中使用此类图像时,您可以使用BitmapShader作为通用原始缓冲区,使用RuntimeShader#setInputBuffer。这将避免颜色空间转换和过滤。