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\}\) |
除了数组数字下标语法 ex: var[num]外,长度为 2-4 的向量的向量组件名称由单个字母表示。组件可以交换和复制。ex:
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 样式语法
<基本类型>[<数组大小>] 变量名 - 例如:half[10] x;
<基本类型> 变量名[<数组大小>] - 例如:half x[10];
数组不能从函数返回、复制、赋值或比较。数组限制会传播到包含数组的结构体。数组只能使用常量或循环变量进行索引。
限定符
类型 | 描述 |
---|---|
const
|
编译时常量或只读函数参数。 |
uniform
|
值在正在处理的图元中不会改变。统一变量通过 Android 使用 RuntimeShader 方法传递,用于setColorUniform 、setFloatUniform 、setIntUniform 、setInputBuffer 和setInputShader 。 |
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
(泛型类型)可以是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)
|
返回余弦值为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。这将避免颜色空间转换和过滤。