内置函数

OpenGL 着色语言定义了用于标量和向量运算的各种内置便利函数。许多这些内置函数可以在多种类型的着色器中使用,但有些旨在提供与硬件的直接映射,因此仅适用于特定类型的着色器。

内置函数基本分为三类

  • 它们以方便的方式公开一些必要的硬件功能,例如访问纹理映射。该语言无法让着色器模拟这些函数。

  • 它们表示一个简单的操作(钳制、混合等),用户可以非常容易地编写,但它们非常常见,并且可能具有直接的硬件支持。对于编译器来说,将表达式映射到复杂的汇编指令是一个非常困难的问题。

  • 它们表示图形硬件在某些时候可能会加速的操作。三角函数属于这一类。

许多函数与常见的 C 库中同名的函数类似,但它们支持向量输入以及更传统的标量输入。

应鼓励应用程序使用内置函数,而不是在自己的着色器代码中进行等效计算,因为内置函数被认为是最佳的(例如,可能直接在硬件中支持)。

如果用户选择,可以通过简单地重新声明和定义相同的名称和参数列表,用自己的代码替换内置函数。由于内置函数比用户内置函数的作用域更外层,因此这样做将隐藏所有与重新声明的函数同名的内置函数。

当以下指定内置函数时,如果输入参数(和相应的输出)可以是 floatvec2vec3vec4,则使用 genFType 作为参数。如果输入参数(和相应的输出)可以是 intivec2ivec3ivec4,则使用 genIType 作为参数。如果输入参数(和相应的输出)可以是 uintuvec2uvec3uvec4,则使用 genUType 作为参数。如果输入参数(或相应的输出)可以是 boolbvec2bvec3bvec4,则使用 genBType 作为参数。如果输入参数(和相应的输出)可以是 doubledvec2dvec3dvec4,则使用 genDType 作为参数。对于函数的任何特定用法,为 genFTypegenITypegenUTypegenBType 替换的实际类型对于所有参数和返回类型都必须具有相同数量的组件。类似地,mat 用于任何具有单精度组件的矩阵基本类型,而 dmat 用于任何具有双精度组件的矩阵基本类型。

内置函数具有有效精度限定符。此限定符不能显式设置,并且可能与结果的精度限定符不同。

注意:一般来说,如前所述,除非以 Vulkan 为目标,否则会忽略精度限定符。

内置函数操作的精度限定符基于其形式参数和实际参数(输入参数)的精度限定符:当形式参数指定精度限定符时,将使用该限定符,否则,将使用实际(调用)参数的精度限定符。这些中的最高精度将是内置函数操作的精度。通常,这适用于内置函数的所有参数,但以下情况除外

  • bitfieldExtractbitfieldInsert 忽略 offsetbits 参数。

  • interpolateAt 函数仅查看 interpolant 参数。

内置函数结果的精度限定符通过以下方式之一确定

对于纹理采样和图像加载函数,返回类型的精度与图像或纹理组合采样器类型的精度匹配

uniform lowp sampler2D texSampler;
highp vec2 coord;
...
lowp vec4 col = texture (texSampler, coord); // texture() returns lowp

否则

  • 对于未指定结果精度限定符的原型,精度将与操作的精度相同(如前所述)。

  • 对于确实指定了结果精度限定符的原型,指定的精度限定符是结果的精度限定符。

在以下部分中指定方程的内置函数中,整个方程将在操作的精度下进行求值。这可能会导致结果下溢或溢出,即使可以在操作精度中表示正确的结果。

角度和三角函数

指定为 angle 的函数参数假定以弧度为单位。在任何情况下,这些函数都不会导致除零错误。如果比率的除数为 0,则结果将是未定义的。

这些都是按组件操作的。描述是每个组件的。

语法 描述

genFType radians(genFType degrees)

degrees 转换为弧度,即 (π / 180) ⋅ degrees

genFType degrees(genFType radians)

radians 转换为度,即 (180 / π) ⋅ radians

genFType sin(genFType angle)

标准三角正弦函数。

genFType cos(genFType angle)

标准三角余弦函数。

genFType tan(genFType angle)

标准三角正切。

genFType asin(genFType x)

反正弦。返回正弦值为 x 的角度。此函数返回的值的范围为 [-π / 2, π / 2]。如果 |x| > 1,则结果未定义。

genFType acos(genFType x)

反余弦。返回余弦值为 x 的角度。此函数返回的值的范围为 [0,π]。如果 |x| > 1,则结果未定义。

genFType atan(genFType y, genFType x)

反正切。返回正切值为 y / x 的角度。xy 的符号用于确定角度所在的象限。此函数返回的值的范围为 [-π, π]。如果 xy 都为 0,则结果未定义。

genFType atan(genFType y_over_x)

反正切。返回正切值为 y_over_x 的角度。此函数返回的值的范围为 [-π / 2, π / 2]

genFType sinh(genFType x)

返回双曲正弦函数 (ex - e-x) / 2

genFType cosh(genFType x)

返回双曲余弦函数 (ex + e-x) / 2

genFType tanh(genFType x)

返回双曲正切函数 sinh(x) / cosh(x)

genFType asinh(genFType x)

反双曲正弦;返回 sinh 的反函数。

genFType acosh(genFType x)

反双曲余弦;返回 cosh 的非负反函数。如果 x < 1,则结果未定义。

genFType atanh(genFType x)

反双曲正切;返回 tanh 的反函数。如果 |x| ≥ 1,则结果未定义。

指数函数

这些都是按组件操作的。描述是每个组件的。

语法 描述

genFType pow(genFType x, genFType y)

返回 xy 次幂,即 xy。如果 x < 0,则结果未定义。如果 x = 0y ≤ 0,则结果未定义。

genFType exp(genFType x)

返回 x 的自然指数,即 ex

genFType log(genFType x)

返回 x 的自然对数,即返回满足方程 x = ey 的值 y。如果 x ≤ 0,则结果未定义。

genFType exp2(genFType x)

返回 2 的 x 次幂,即 2x

genFType log2(genFType x)

返回 x 的以 2 为底的对数,即返回满足方程 x = 2y 的值 y。如果 x ≤ 0,则结果未定义。

genFType sqrt(genFType x)
genDType sqrt(genDType x)

返回 sqrt(x)。如果 x < 0,则结果未定义。

genFType inversesqrt(genFType x)
genDType inversesqrt(genDType x)

返回 1 / sqrt(x)。如果 x ≤ 0,则结果未定义。

常用函数

这些都是按组件操作的。描述是每个组件的。

语法 描述

genFType abs(genFType x)
genIType abs(genIType x)
genDType abs(genDType x)

如果 x ≥ 0,则返回 x;否则返回 -x

genFType sign(genFType x)
genIType sign(genIType x)
genDType sign(genDType x)

如果 x > 0,则返回 1.0;如果 x = 0,则返回 0.0;如果 x < 0,则返回 -1.0。

genFType floor(genFType x)
genDType floor(genDType x)

返回小于或等于 x 的最接近的整数值。

genFType trunc(genFType x)
genDType trunc(genDType x)

返回最接近 x 的整数,其绝对值不大于 x 的绝对值。

genFType round(genFType x)
genDType round(genDType x)

返回最接近 x 的整数值。小数部分为 0.5 将以实现方式选择的方向进行舍入,大概是最快的方向。这包括 round(x) 对于所有 x 值返回与 roundEven(x) 相同值的可能性。

genFType roundEven(genFType x)
genDType roundEven(genDType x)

返回最接近 x 的整数值。小数部分为 0.5 将向最接近的偶数整数舍入。(对于 x,3.5 和 4.5 都将返回 4.0。)

genFType ceil(genFType x)
genDType ceil(genDType x)

返回大于或等于 x 的最接近的整数值。

genFType fract(genFType x)
genDType fract(genDType x)

返回 x - floor(x)。

genFType mod(genFType x, float y)
genFType mod(genFType x, genFType y)
genDType mod(genDType x, double y)
genDType mod(genDType x, genDType y)

取模。返回 x - y ⋅ floor(x / y)

请注意,实现可能使用对余数的廉价近似,并且由于 floor 中的不连续性,误差可能很大。在某些情况下,这可能会产生数学上意想不到的结果,例如 mod(x,x) 计算 x 而不是 0,并且还可能导致结果的符号与无限精确的结果不同。

genFType modf(genFType x, out genFType i)
genDType modf(genDType x, out genDType i)

返回 x 的小数部分,并将 i 设置为整数部分(作为整数浮点值)。返回值和输出参数都将具有与 x 相同的符号。

genFType min(genFType x, genFType y)
genFType min(genFType x, float y)
genDType min(genDType x, genDType y)
genDType min(genDType x, double y)
genIType min(genIType x, genIType y)
genIType min(genIType x, int y)
genUType min(genUType x, genUType y)
genUType min(genUType x, uint y)

如果 y < x,则返回 y;否则返回 x。如果其中一个操作数是 NaN,则未定义哪个操作数是结果。

genFType max(genFType x, genFType y)
genFType max(genFType x, float y)
genDType max(genDType x, genDType y)
genDType max(genDType x, double y)
genIType max(genIType x, genIType y)
genIType max(genIType x, int y)
genUType max(genUType x, genUType y)
genUType max(genUType x, uint y)

如果 x < y,则返回 y;否则返回 x。如果其中一个操作数是 NaN,则未定义哪个操作数是结果。

genFType clamp(genFType x, genFType minVal, genFType maxVal)
genFType clamp(genFType x, float minVal, float maxVal)
genDType clamp(genDType x, genDType minVal, genDType maxVal)
genDType clamp(genDType x, double minVal, double maxVal)
genIType clamp(genIType x, genIType minVal, genIType maxVal)
genIType clamp(genIType x, int minVal, int maxVal)
genUType clamp(genUType x, genUType minVal, genUType maxVal)
genUType clamp(genUType x, uint minVal, uint maxVal)

返回 min(max(x, minVal), maxVal)。如果 minVal > maxVal,则结果未定义。

genFType mix(genFType x, genFType y, genFType a)
genFType mix(genFType x, genFType y, float a)
genDType mix(genDType x, genDType y, genDType a)
genDType mix(genDType x, genDType y, double a)

返回 xy 的线性混合,即 x ⋅ (1 - a) + y ⋅ a

genFType mix(genFType x, genFType y, genBType a)
genDType mix(genDType x, genDType y, genBType a)
genIType mix(genIType x, genIType y, genBType a)
genUType mix(genUType x, genUType y, genBType a)
genBType mix(genBType x, genBType y, genBType a)

选择返回的每个分量来自哪个向量。对于 a 的一个分量为 false,则返回 x 的对应分量。对于 a 的一个分量为 true,则返回 y 的对应分量。未被选择的 xy 的分量允许是无效的浮点值,并且不会对结果产生影响。因此,这提供了与例如以下不同的功能:
genFType mix(genFType x, genFType y, genFType(a))
其中 a 是一个布尔向量。

genFType step(genFType edge, genFType x)
genFType step(float edge, genFType x)
genDType step(genDType edge, genDType x)
genDType step(double edge, genDType x)

如果 x < edge,则返回 0.0;否则返回 1.0。

genFType smoothstep(genFType edge0, genFType edge1, genFType x)
genFType smoothstep(float edge0, float edge1, genFType x)
genDType smoothstep(genDType edge0, genDType edge1, genDType x)
genDType smoothstep(double edge0, double edge1, genDType x)

如果 x ≤ edge0,则返回 0.0;如果 x ≥ edge1,则返回 1.0,并且当 edge0 < x < edge1 时,在 0 和 1 之间执行平滑的埃尔米特插值。这在您希望具有平滑过渡的阈值函数的情况下很有用。这等效于

genFType t;
t = clamp ((x - edge0) / (edge1 - edge0), 0, 1);
return t * t * (3 - 2 * t);

(对于双精度类型类似。)如果 edge0 ≥ edge1,则结果未定义。

genBType isnan(genFType x)
genBType isnan(genDType x)

如果 x 包含 NaN,则返回 true。否则,返回 false。如果未实现 NaN,则始终返回 false

genBType isinf(genFType x)
genBType isinf(genDType x)

如果 x 包含正无穷大或负无穷大,则返回 true。否则,返回 false

genIType floatBitsToInt(highp genFType value)
genUType floatBitsToUint(highp genFType value)

返回一个有符号或无符号整数值,表示浮点值的编码。保留 float 值的位级表示。

genFType intBitsToFloat(highp genIType value)
genFType uintBitsToFloat(highp genUType value)

返回与浮点值的有符号或无符号整数编码相对应的浮点值。如果传入 NaN,则不会发出信号,并且结果值是未指定的。如果传入 Inf,则结果值是相应的 Inf。如果传入次正规数,则结果可能被刷新为 0。否则,将保留位级表示。

genFType fma(genFType a, genFType b, genFType c)
genDType fma(genDType a, genDType b, genDType c)

计算并返回 a * b + c。在返回值最终被声明为 precise 的变量使用的情况下

  • fma() 被视为单个操作,而声明为 precise 的变量使用的表达式 a * b + c 被视为两个操作。

  • fma() 的精度可能与表达式 a * b + c 的精度不同。

  • fma() 将以与任何其他被精确变量使用的 fma() 相同的精度进行计算,从而为 abc 的相同输入值提供不变的结果。

否则,在没有 precise 使用的情况下,对 fma() 和表达式 a * b + c 之间的操作数量或精度差异没有特殊约束。

genFType frexp(highp genFType x, out highp genIType exp) genDType frexp(genDType x, out genIType exp)

x 分解为范围在 [0.5,1.0] 内的浮点尾数,以及 2 的整数指数,使得

x = 尾数 ⋅ 2指数

尾数由函数返回,指数在参数 exp 中返回。对于零的浮点值,尾数和指数均为零。

如果实现支持有符号零,则负零的输入值应返回负零的尾数。对于作为无穷大或不是数字的浮点值,结果未定义。

如果输入 x 是一个向量,则此操作将以分量方式执行;函数返回的值和写入 exp 的值是与 x 具有相同分量数的向量。

genFType ldexp(highp genFType x, highp genIType exp)
genDType ldexp(genDType x, genIType exp)

xexp 中相应的 2 的整数指数构建浮点数,返回

尾数 ⋅ 2指数

如果此乘积太大而无法以浮点类型表示,则结果未定义。

如果 exp 大于 +128(单精度)或 +1024(双精度),则返回的值未定义。如果 exp 小于 -126(单精度)或 -1022(双精度),则返回的值可能会被刷新为零。此外,使用 frexp() 将值分解为尾数和指数,然后使用 ldexp() 重建浮点值应该为零和所有有限的非次正规值产生原始输入。
如果输入 x 是一个向量,则此操作将以分量方式执行;传入 exp 的值和函数返回的值是与 x 具有相同分量数的向量。

浮点打包和解包函数

这些函数不以分量方式操作,而是如每种情况中所述。

语法 描述

highp uint packUnorm2x16(vec2 v)
highp uint packSnorm2x16(vec2 v)
uint packUnorm4x8(vec4 v)
uint packSnorm4x8(vec4 v)

首先,将归一化浮点值 v 的每个分量转换为 16 位 (2x16) 或 8 位 (4x8) 整数值。然后,将结果打包到返回的 32 位无符号整数中。

v 的分量 c 转换为定点数的步骤如下:

packUnorm2x16: round(clamp(c, 0, +1) * 65535.0)
packSnorm2x16: round(clamp(c, -1, +1) * 32767.0)
packUnorm4x8: round(clamp(c, 0, +1) * 255.0)
packSnorm4x8: round(clamp(c, -1, +1) * 127.0)

向量的第一个分量将被写入输出的最低有效位;最后一个分量将被写入最高有效位。

vec2 unpackUnorm2x16(highp uint p)
vec2 unpackSnorm2x16(highp uint p)
vec4 unpackUnorm4x8(highp uint p)
vec4 unpackSnorm4x8(highp uint p)

首先,将一个 32 位无符号整数 p 解包为一对 16 位无符号整数,一对 16 位有符号整数,四个 8 位无符号整数或四个 8 位有符号整数。然后,每个分量被转换为归一化浮点值,以生成返回的二分量或四分量向量。

解包的定点值 f 转换为浮点值的过程如下:

unpackUnorm2x16: f / 65535.0
unpackSnorm2x16: clamp(f / 32767.0, -1, +1)
unpackUnorm4x8: f / 255.0
unpackSnorm4x8: clamp(f / 127.0, -1, +1)

返回向量的第一个分量将从输入的最低有效位中提取;最后一个分量将从最高有效位中提取。

uint packHalf2x16( vec2 v)

返回一个无符号整数,该整数是通过将二分量浮点向量的分量转换为 API 的 16 位浮点表示,然后将这两个 16 位整数打包成一个 32 位无符号整数而获得的。

第一个向量分量指定结果的 16 个最低有效位;第二个分量指定 16 个最高有效位。

vec2 unpackHalf2x16( uint v)

返回一个二分量浮点向量,其分量是通过将 32 位无符号整数解包为一对 16 位值,根据 API 将这些值解释为 16 位浮点数,并将它们转换为 32 位浮点值而获得的。

向量的第一个分量从 v 的 16 个最低有效位获得;第二个分量从 v 的 16 个最高有效位获得。

double packDouble2x32(uvec2 v)

返回一个双精度值,该值是通过将 v 的分量打包成一个 64 位值而获得的。如果创建了 IEEE 754 Inf 或 NaN,则不会发出信号,并且生成的浮点值是未指定的。否则,v 的位级表示将被保留。第一个向量分量指定 32 个最低有效位;第二个分量指定 32 个最高有效位。

uvec2 unpackDouble2x32(double v)

返回 v 的二分量无符号整数向量表示形式。v 的位级表示将被保留。向量的第一个分量包含双精度的 32 个最低有效位;第二个分量由 32 个最高有效位组成。

几何函数

这些函数将向量作为向量进行操作,而不是按分量进行操作。

语法 描述

float length(genFType x)
double length(genDType x)

返回向量 x 的长度,即 sqrt( x02 + x12 + …​ )

float distance(genFType p0, genFType p1)
double distance(genDType p0, genDType p1)

返回 p0p1 之间的距离,即 length(p0 - p1)

float dot(genFType x, genFType y)
double dot(genDType x, genDType y)

返回 xy 的点积,即 x0 ⋅ y0 + x1 ⋅ y1 + …​

vec3 cross(vec3 x, vec3 y)
dvec3 cross(dvec3 x, dvec3 y)

返回 xy 的叉积,即 (x1 ⋅ y2 - y1 ⋅ x2, x2 ⋅ y0 - y2 ⋅ x0, x0 ⋅ y1 - y0 ⋅ x1)

genFType normalize(genFType x)
genDType normalize(genDType x)

返回一个与 x 方向相同但长度为 1 的向量,即 x / length(x)。

仅兼容性配置文件
vec4 ftransform()

仅在使用兼容性配置文件时可用。对于核心 OpenGL,请使用 invariant
仅适用于顶点着色器。此函数将确保以与 OpenGL 的固定功能变换产生完全相同结果的方式变换传入的顶点值。它旨在用于计算 gl_Position,例如

gl_Position = ftransform()

例如,当应用程序在单独的通道中渲染相同的几何体时,应该使用此函数,其中一个通道使用固定功能路径进行渲染,而另一个通道使用可编程着色器。

genFType faceforward(genFType N, genFType I, genFType Nref)
genDType faceforward(genDType N, genDType I, genDType Nref)

如果 dot(Nref, I) < 0,则返回 N,否则返回 -N

genFType reflect(genFType I, genFType N)
genDType reflect(genDType I, genDType N)

对于入射向量 I 和表面方向 N,返回反射方向:I - 2 ⋅ dot(N, I) ⋅ N。为了获得想要的结果,N 必须已经归一化。

genFType refract(genFType I, genFType N, float eta)
genDType refract(genDType I, genDType N, double eta)

对于入射向量 I 和表面法线 N 以及折射率比 eta,返回折射向量。结果是通过下面显示的 折射方程 计算得出的。

The input parameters for the incident vector _I_ and the surface
normal _N_ must already be normalized to get the desired results.

折射方程

矩阵函数

对于以下每个内置矩阵函数,都有一个单精度浮点版本(其中所有参数和返回值都是单精度)和一个双精度浮点版本(其中所有参数和返回值都是双精度)。仅显示单精度浮点版本。

语法 描述

mat matrixCompMult(mat x, mat y)

按分量将矩阵 x 乘以矩阵 y,即 result[i][j] 是 x[i][j] 和 y[i][j] 的标量积。

注意:要获得线性代数矩阵乘法,请使用乘法运算符 (*)。

mat2 outerProduct(vec2 c, vec2 r)
mat3 outerProduct(vec3 c, vec3 r)
mat4 outerProduct(vec4 c, vec4 r)
mat2x3 outerProduct(vec3 c, vec2 r)
mat3x2 outerProduct(vec2 c, vec3 r)
mat2x4 outerProduct(vec4 c, vec2 r)
mat4x2 outerProduct(vec2 c, vec4 r)
mat3x4 outerProduct(vec4 c, vec3 r)
mat4x3 outerProduct(vec3 c, vec4 r)

将第一个参数c视为列向量(单列矩阵),第二个参数r视为行向量(单行矩阵),并执行线性代数矩阵乘法 c * r,得到一个矩阵,其行数是 c 中分量的数量,列数是 r 中分量的数量。

mat2 transpose(mat2 m)
mat3 transpose(mat3 m)
mat4 transpose(mat4 m)
mat2x3 transpose(mat3x2 m)
mat3x2 transpose(mat2x3 m)
mat2x4 transpose(mat4x2 m)
mat4x2 transpose(mat2x4 m)
mat3x4 transpose(mat4x3 m)
mat4x3 transpose(mat3x4 m)

返回矩阵 m 的转置。输入矩阵 m 不会被修改。

float determinant(mat2 m)
float determinant(mat3 m)
float determinant(mat4 m)

返回 m 的行列式。

mat2 inverse(mat2 m)
mat3 inverse(mat3 m)
mat4 inverse(mat4 m)

返回矩阵 m 的逆矩阵。输入矩阵 m 不会被修改。如果 m 是奇异的或病态的(接近奇异),则返回矩阵中的值是未定义的。

向量关系函数

关系运算符和相等运算符(<, <=, >, >=, ==, !=)被定义为对标量进行操作并产生标量布尔结果。对于向量结果,请使用以下内置函数。下面,使用以下占位符表示列出的特定类型

占位符 允许的特定类型

bvec

bvec2, bvec3, bvec4

ivec

ivec2, ivec3, ivec4

uvec

uvec2, uvec3, uvec4

vec

vec2, vec3, vec4, dvec2, dvec3, dvec4

在所有情况下,任何特定调用的所有输入和返回向量的大小都必须匹配。

语法 描述

bvec lessThan(vec x, vec y)
bvec lessThan(ivec x, ivec y)
bvec lessThan(uvec x, uvec y)

返回 x < y 的逐分量比较结果。

bvec lessThanEqual(vec x, vec y)
bvec lessThanEqual(ivec x, ivec y)
bvec lessThanEqual(uvec x, uvec y)

返回 x ≤ y 的逐分量比较结果。

bvec greaterThan(vec x, vec y)
bvec greaterThan(ivec x, ivec y)
bvec greaterThan(uvec x, uvec y)

返回 x > y 的逐分量比较结果。

bvec greaterThanEqual(vec x, vec y)
bvec greaterThanEqual(ivec x, ivec y)
bvec greaterThanEqual(uvec x, uvec y)

返回 x ≥ y 的逐分量比较结果。

bvec equal(vec x, vec y)
bvec equal(ivec x, ivec y)
bvec equal(uvec x, uvec y)
bvec equal(bvec x, bvec y)

返回 x == y 的逐分量比较结果。

bvec notEqual(vec x, vec y)
bvec notEqual(ivec x, ivec y)
bvec notEqual(uvec x, uvec y)
bvec notEqual(bvec x, bvec y)

返回 x ≠ y 的逐分量比较结果。

bool any(bvec x)

如果 x 的任何分量为 true,则返回 true

bool all(bvec x)

仅当 x 的所有分量都为 true 时才返回 true

bvec not(bvec x)

返回 x 的逐分量逻辑补码。

整数函数

这些函数都按分量进行操作。描述是针对每个分量的。[a, b] 表示从位号 a 到位号 b(包括 ab)的位集合。最低有效位为位 0。“位号”始终指从最低有效位(位 0)向上计数的位。

语法 描述

genUType uaddCarry(highp genUType x, highp genUType y, out lowp genUType carry)

将 32 位无符号整数 xy 相加,返回模 232 的和。如果和小于 232,则将 carry 的值设置为零;否则设置为一。

genUType usubBorrow(highp genUType x, highp genUType y, out lowp genUType borrow)

x 中减去 32 位无符号整数 y,如果差值为非负数,则返回差值;否则返回 232 加差值。如果 x ≥ y,则将 borrow 的值设置为零;否则设置为一。

void umulExtended(highp genUType x, highp genUType y, out highp genUType msb, out highp genUType lsb)
void imulExtended(highp genIType x, highp genIType y, out highp genIType msb, out highp genIType lsb)

将 32 位无符号或有符号整数 xy 相乘,产生一个 64 位结果。32 个最低有效位在 lsb 中返回。32 个最高有效位在 msb 中返回。

genIType bitfieldExtract(genIType value, int offset, int bits)
genUType bitfieldExtract(genUType value, int offset, int bits)

value 中提取位 [offset, offset + bits - 1],并将它们返回在结果的最低有效位中。

对于无符号数据类型,结果的最高有效位将被设置为零。对于有符号数据类型,最高有效位将被设置为位 offset + bits - 1 的值。

如果 bits 为零,则结果将为零。如果 offsetbits 为负数,或者 offsetbits 的和大于用于存储操作数的位数,则结果将是未定义的。请注意,对于 bitfieldExtract() 的向量版本,所有分量共享一对 offsetbits 值。

genIType bitfieldInsert(genIType base, genIType insert, int offset, int bits)
genUType bitfieldInsert(genUType base, genUType insert, int offset, int bits)

insertbits 个最低有效位插入到 base 中。

结果的位 [offset, offset + bits - 1] 将取自 insert 的位 [0, bits - 1],所有其他位直接取自 base 的相应位。如果 bits 为零,则结果将只是 base。如果 offsetbits 为负数,或者 offsetbits 的和大于用于存储操作数的位数,则结果将是未定义的。
请注意,对于 bitfieldInsert() 的向量版本,所有分量共享一对 offsetbits 值。

genIType bitfieldReverse(highp genIType value)
genUType bitfieldReverse(highp genUType value)

反转 value 的位。结果的第 n 位将取自 value 的第 (bits - 1) - n 位,其中 bits 是用于表示 value 的总位数。

genIType bitCount(genIType value)
genIType bitCount(genUType value)

返回 value 的二进制表示中 1 的位数。

genIType findLSB(genIType value)
genIType findLSB(genUType value)

返回 value 的二进制表示中最低有效位 1 的位号。如果 value 为零,则返回 -1。

genIType findMSB(highp genIType value)
genIType findMSB(highp genUType value)

返回 value 的二进制表示中最高有效位的位号。

对于正整数,结果将是最高有效位 1 的位号。对于负整数,结果将是最高有效位 0 的位号。对于零或负一的 value,将返回 -1。

纹理函数

纹理查找函数在所有着色阶段都可用。但是,细节级别仅针对片段着色器隐式计算。其他着色器操作时,就好像基本细节级别计算为零。下表中的函数提供通过纹理组合采样器访问纹理的能力,这些采样器是通过 API 设置的。纹理属性(例如大小、像素格式、维度数量、过滤方法、mipmap 级别数、深度比较等)也由 API 调用定义。当通过下面定义的内置函数访问纹理时,会考虑这些属性。

纹理数据可以由 GL 存储为单精度浮点数、归一化整数、无符号整数或有符号整数数据。这由纹理的内部格式类型决定。

提供了纹理查找函数,可以根据传递给查找函数的采样器类型,将其结果作为浮点数、无符号整数或有符号整数返回。必须注意使用正确的采样器类型进行纹理访问。下表列出了支持的采样器类型和纹理内部格式的组合。空白条目不受支持。对于不支持的组合执行纹理查找将返回未定义的值。

对于深度/模板纹理,内部纹理格式由通过 API 设置的被访问的组件决定。当深度/模板纹理模式设置为 DEPTH_COMPONENT 时,应使用深度组件的内部格式。当深度/模板纹理模式设置为 STENCIL_INDEX 时,应使用模板组件的内部格式。

内部纹理格式 浮点采样器类型 有符号整数采样器类型 无符号整数采样器类型

浮点数

支持

归一化整数

支持

有符号整数

支持

无符号整数

支持

如果使用整数采样器类型,则纹理查找的结果是一个 ivec4。如果使用无符号整数采样器类型,则纹理查找的结果是一个 uvec4。如果使用浮点采样器类型,则纹理查找的结果是一个 vec4

在下面的原型中,返回类型 gvec4 中的 g 用作占位符,表示什么都没有、iu,从而生成 vec4ivec4uvec4 的返回类型。在这些情况下,采样器参数类型也以 g 开头,表示对返回类型进行了相同的替换;它是单精度浮点数、有符号整数或无符号整数采样器,与上述返回类型的基本类型匹配。

对于阴影形式(采样器参数为阴影类型),按照 OpenGL 规范 的 8.23 节“纹理比较模式”中所述,对绑定到 sampler 的深度纹理执行深度比较查找。有关哪个组件指定 Dref,请参见下表。绑定到 sampler 的纹理必须是深度纹理,否则结果未定义。如果对启用了深度比较的表示深度纹理的采样器进行非阴影纹理调用,则结果未定义。如果对关闭了深度比较的表示深度纹理的采样器进行阴影纹理调用,则结果未定义。如果对不表示深度纹理的采样器进行阴影纹理调用,则结果未定义。

在下面的所有函数中,bias 参数对于片段着色器是可选的。在任何其他着色阶段都不接受 bias 参数。对于片段着色器,如果存在 bias,则将其添加到隐式的细节级别中,然后再执行纹理访问操作。不支持矩形纹理、多采样纹理或纹理缓冲区的 biaslod 参数,因为这些类型的纹理不允许使用 mipmap。

隐式细节级别的选择如下:对于未进行 mipmap 处理的纹理,直接使用该纹理。如果它进行了 mipmap 处理并且在片段着色器中运行,则使用实现计算出的细节级别进行纹理查找。如果它进行了 mipmap 处理并且在非片段着色器中运行,则使用基本纹理。

某些纹理函数(非“Lod”和非“Grad”版本)可能需要隐式导数。隐式导数在非均匀控制流中和非片段着色器纹理获取中是未定义的。

对于 Cube 形式,P 的方向用于选择在哪个面上进行二维纹理查找,如 OpenGL 规范 的 8.13 节“立方体贴图纹理选择”中所述。

对于 Array 形式,使用的数组层将是

其中 d 是纹理数组的深度,layer 来自下表中指示的组件。

纹理查询函数

textureSize 函数查询纹理组合采样器的特定纹理级别的尺寸。

textureQueryLod 函数仅在片元着色器中可用。它们获取 P 的分量,并计算纹理管道将用于通过正常纹理查找访问该纹理的细节级别信息。细节级别 OpenGL 规范的公式 3.18)是在任何细节级别偏差之后,但在钳制到 [TEXTURE_MIN_LOD, TEXTURE_MAX_LOD] 之前获得的。 还会计算将要访问的 mipmap 数组。 如果访问单个细节级别,则会返回相对于基础级别的细节级别编号。 如果将访问多个细节级别,则会返回两个级别之间的浮点数,其中小数部分等于计算和钳制的细节级别的小数部分。

所使用的算法由以下伪代码给出

float ComputeAccessedLod(float computedLod)
{
    // Clamp the computed LOD according to the texture LOD clamps.
    if (computedLod < TEXTURE_MIN_LOD) computedLod = TEXTURE_MIN_LOD;
    if (computedLod > TEXTURE_MAX_LOD) computedLod = TEXTURE_MAX_LOD;

    // Clamp the computed LOD to the range of accessible levels.
    if (computedLod < 0.0)
        computedLod = 0.0;
    if (computedLod > (float) maxAccessibleLevel)
        computedLod = (float) maxAccessibleLevel;

    // Return a value according to the min filter.
    if (TEXTURE_MIN_FILTER is LINEAR or NEAREST) {
        return 0.0;
    } else if (TEXTURE_MIN_FILTER is NEAREST_MIPMAP_NEAREST
               or LINEAR_MIPMAP_NEAREST) {
        return ceil(computedLod + 0.5) - 1.0;
    } else {
        return computedLod;
    }
}

maxAccessibleLevel 是 mipmap 数组的最小可访问级别的级别编号(OpenGL 规范的 8.14.3 节“Mipmapping”中的值 q)减去基础级别。

语法 描述

int textureSize(gsampler1D sampler, int lod)
ivec2 textureSize(gsampler2D sampler, int lod)
ivec3 textureSize(gsampler3D sampler, int lod)
ivec2 textureSize(gsamplerCube sampler, int lod)
int textureSize(sampler1DShadow sampler, int lod)
ivec2 textureSize(sampler2DShadow sampler, int lod)
ivec2 textureSize(samplerCubeShadow sampler, int lod) ivec3 textureSize(gsamplerCubeArray sampler, int lod)
ivec3 textureSize(samplerCubeArrayShadow sampler, int lod)
ivec2 textureSize(gsampler2DRect sampler)
ivec2 textureSize(sampler2DRectShadow sampler)
ivec2 textureSize(gsampler1DArray sampler, int lod)
ivec2 textureSize(sampler1DArrayShadow sampler, int lod)
ivec3 textureSize(gsampler2DArray sampler, int lod)
ivec3 textureSize(sampler2DArrayShadow sampler, int lod)
int textureSize(gsamplerBuffer sampler)
ivec2 textureSize(gsampler2DMS sampler)
ivec3 textureSize(gsampler2DMSArray sampler)

返回绑定到 sampler 的纹理的 lod 级别的尺寸(如果存在),如OpenGL 规范的 11.1.3.4 节“纹理查询”中所述。
返回值中的分量按顺序填充,依次为纹理的宽度、高度和深度。

对于数组形式,返回值的最后一个分量是纹理数组中的层数,或是纹理立方体贴图数组中的立方体数。

vec2 textureQueryLod(gsampler1D sampler, float P)
vec2 textureQueryLod(gsampler2D sampler, vec2 P)
vec2 textureQueryLod(gsampler3D sampler, vec3 P)
vec2 textureQueryLod(gsamplerCube sampler, vec3 P)
vec2 textureQueryLod(gsampler1DArray sampler, float P)
vec2 textureQueryLod(gsampler2DArray sampler, vec2 P)
vec2 textureQueryLod(gsamplerCubeArray sampler, vec3 P)
vec2 textureQueryLod(sampler1DShadow sampler, float P)
vec2 textureQueryLod(sampler2DShadow sampler, vec2 P)
vec2 textureQueryLod(samplerCubeShadow sampler, vec3 P)
vec2 textureQueryLod(sampler1DArrayShadow sampler, float P)
vec2 textureQueryLod(sampler2DArrayShadow sampler, vec2 P)
vec2 textureQueryLod(samplerCubeArrayShadow sampler, vec3 P)

返回将在返回值的 x 分量中访问的 mipmap 数组。

返回返回值的 y 分量中相对于基础级别的计算细节级别。

如果在不完整的纹理上调用,则结果未定义。

int textureQueryLevels(gsampler1D sampler)
int textureQueryLevels(gsampler2D sampler)
int textureQueryLevels(gsampler3D sampler)
int textureQueryLevels(gsamplerCube sampler)
int textureQueryLevels(gsampler1DArray sampler)
int textureQueryLevels(gsampler2DArray sampler)
int textureQueryLevels(gsamplerCubeArray sampler)
int textureQueryLevels(sampler1DShadow sampler)
int textureQueryLevels(sampler2DShadow sampler)
int textureQueryLevels(samplerCubeShadow sampler)
int textureQueryLevels(sampler1DArrayShadow sampler)
int textureQueryLevels(sampler2DArrayShadow sampler)
int textureQueryLevels(samplerCubeArrayShadow sampler)

返回与 sampler 关联的纹理中可访问的 mipmap 级别数,如OpenGL 规范中所定义。

如果没有纹理或不完整的纹理与 sampler 关联,则将返回值零。

在所有着色器阶段都可用。

int textureSamples(gsampler2DMS sampler)
int textureSamples(gsampler2DMSArray sampler)

返回绑定到 sampler 的纹理的样本数。

Texel 查找函数

语法 描述

gvec4 texture(gsampler1D sampler, float P [, float bias] )
gvec4 texture(gsampler2D sampler, vec2 P [, float bias] )
gvec4 texture(gsampler3D sampler, vec3 P [, float bias] )
gvec4 texture(gsamplerCube sampler, vec3 P[, float bias] )
float texture(sampler1DShadow sampler, vec3 P [, float bias])
float texture(sampler2DShadow sampler, vec3 P [, float bias])
float texture(samplerCubeShadow sampler, vec4 P [, float bias] )
gvec4 texture(gsampler2DArray sampler, vec3 P [, float bias] )
gvec4 texture(gsamplerCubeArray sampler, vec4 P [, float bias] )
gvec4 texture(gsampler1DArray sampler, vec2 P [, float bias] )
float texture(sampler1DArrayShadow sampler, vec3 P [, float bias] )
float texture(sampler2DArrayShadow sampler, vec4 P)
gvec4 texture(gsampler2DRect sampler, vec2 P)
float texture(sampler2DRectShadow sampler, vec3 P)
float texture(samplerCubeArrayShadow sampler, vec4 P, float compare)

使用纹理坐标 P 在当前绑定到 sampler 的纹理中进行纹理查找。

对于阴影形式:当存在 compare 时,它用作 Dref,并且数组层来自 P 的最后一个分量。当不存在 compare 时,P 的最后一个分量用作 Dref,数组层来自 P 的倒数第二个分量。(对于 1D 阴影查找,P 的第二个分量未使用。)

对于非阴影形式:数组层来自 P 的最后一个分量。

gvec4 textureProj(gsampler1D sampler, vec2 P [, float bias] )
gvec4 textureProj(gsampler1D sampler, vec4 P [, float bias] )
gvec4 textureProj(gsampler2D sampler, vec3 P [, float bias] )
gvec4 textureProj(gsampler2D sampler, vec4 P [, float bias] )
gvec4 textureProj(gsampler3D sampler, vec4 P [, float bias] )
float textureProj(sampler1DShadow sampler, vec4 P [, float bias] )
float textureProj(sampler2DShadow sampler, vec4 P [, float bias] )
gvec4 textureProj(gsampler2DRect sampler, vec3 P)
gvec4 textureProj(gsampler2DRect sampler, vec4 P)
float textureProj(sampler2DRectShadow sampler, vec4 P)

执行带投影的纹理查找。从P中提取的纹理坐标(不包括P的最后一个分量)除以P的最后一个分量,形成投影坐标P'。阴影形式中得到的P的第三个分量被用作Dref。当sampler类型为gsampler2DP类型为vec4时,P的第三个分量将被忽略。计算这些值后,纹理查找将按照texture中的方式进行。

gvec4 textureLod(gsampler1D sampler, float P, float lod)
gvec4 textureLod(gsampler2D sampler, vec2 P, float lod)
gvec4 textureLod(gsampler3D sampler, vec3 P, float lod)
gvec4 textureLod(gsamplerCube sampler, vec3 P, float lod)
float textureLod(sampler2DShadow sampler, vec3 P, float lod)
float textureLod(sampler1DShadow sampler, vec3 P, float lod)
gvec4 textureLod(gsampler1DArray sampler, vec2 P, float lod)
float textureLod(sampler1DArrayShadow sampler, vec3 P, float lod)
gvec4 textureLod(gsampler2DArray sampler, vec3 P, float lod)
gvec4 textureLod(gsamplerCubeArray sampler, vec4 P, float lod)

执行纹理查找,如同 texture 一样,但具有显式的细节层次;lod 指定 λbase 并按如下方式设置偏导数
(参见 OpenGL 规范 的 8.14 节 “纹理缩小” 和公式 8.4-8.6。)

∂u / ∂x = ∂v / ∂x = ∂w / ∂x = 0
∂u / ∂y = ∂v / ∂y = ∂w / ∂y = 0

gvec4 textureOffset(gsampler1D sampler, float P, int offset [, float bias] )
gvec4 textureOffset(gsampler2D sampler, vec2 P, ivec2 offset [, float bias] )
gvec4 textureOffset(gsampler3D sampler, vec3 P, ivec3 offset [, float bias] )
float textureOffset(sampler2DShadow sampler, vec3 P, ivec2 offset [, float bias] )
gvec4 textureOffset(gsampler2DRect sampler, vec2 P, ivec2 offset)
float textureOffset(sampler2DRectShadow sampler, vec3 P, ivec2 offset)
float textureOffset(sampler1DShadow sampler, vec3 P, int offset [, float bias] )
gvec4 textureOffset(gsampler1DArray sampler, vec2 P, int offset [, float bias] )
gvec4 textureOffset(gsampler2DArray sampler, vec3 P, ivec2 offset [, float bias] )
float textureOffset(sampler1DArrayShadow sampler, vec3 P, int offset [, float bias] )
float textureOffset(sampler2DArrayShadow sampler, vec4 P, ivec2 offset)

执行纹理查找,如同 texture 一样,但在查找每个纹素之前,将 *offset* 添加到 (u,v,w) 纹素坐标。offset 值必须是常量表达式。支持的 offset 值范围有限;最小和最大 offset 值取决于实现,并分别由 *gl_MinProgramTexelOffset* 和 *gl_MaxProgramTexelOffset* 给出。

请注意,*offset* 不适用于纹理数组的图层坐标。 这在 OpenGL 规范 的 8.14.2 节 “坐标环绕和纹素选择” 中有详细说明,其中 *offset* 是 u, δv, δw)
请注意,立方体贴图也不支持纹素偏移。

gvec4 texelFetch(gsampler1D sampler, int P, int lod)
gvec4 texelFetch(gsampler2D sampler, ivec2 P, int lod)
gvec4 texelFetch(gsampler3D sampler, ivec3 P, int lod) gvec4 texelFetch(gsampler2DRect sampler, ivec2 P)
gvec4 texelFetch(gsampler1DArray sampler, ivec2 P, int lod)
gvec4 texelFetch(gsampler2DArray sampler, ivec3 P, int lod)
gvec4 texelFetch(gsamplerBuffer sampler, int P)
gvec4 texelFetch(gsampler2DMS sampler, ivec2 P, int sample)
gvec4 texelFetch(gsampler2DMSArray sampler, ivec3 P, int sample)

使用整数纹理坐标 *P* 从 *sampler* 中查找单个纹素。 对于数组形式,数组层来自 *P* 的最后一个分量。 细节层次 *lod*(如果存在)如 OpenGL 规范 的 11.1.3.2 节 “纹素获取” 和 8.14.1 节 “缩放因子和细节层次” 中所述。

gvec4 texelFetchOffset(gsampler1D sampler, int P, int lod, int offset)
gvec4 texelFetchOffset(gsampler2D sampler, ivec2 P, int lod, ivec2 offset)
gvec4 texelFetchOffset(gsampler3D sampler, ivec3 P, int lod, ivec3 offset)
gvec4 texelFetchOffset(gsampler2DRect sampler, ivec2 P, ivec2 offset)
gvec4 texelFetchOffset(gsampler1DArray sampler, ivec2 P, int lod, int offset)
gvec4 texelFetchOffset(gsampler2DArray sampler, ivec3 P, int lod, ivec2 offset)

获取单个纹素,如 texelFetch 中所述,并按 textureOffset 中所述偏移 *offset*。

gvec4 textureProjOffset(gsampler1D sampler, vec2 P, int offset [, float bias] )
gvec4 textureProjOffset(gsampler1D sampler, vec4 P, int offset [, float bias] )
gvec4 textureProjOffset(gsampler2D sampler, vec3 P, ivec2 offset [, float bias] )
gvec4 textureProjOffset(gsampler2D sampler, vec4 P, ivec2 offset [, float bias] )
gvec4 textureProjOffset(gsampler3D sampler, vec4 P, ivec3 offset [, float bias] )
gvec4 textureProjOffset(gsampler2DRect sampler, vec3 P, ivec2 offset)
gvec4 textureProjOffset(gsampler2DRect sampler, vec4 P, ivec2 offset)
float textureProjOffset(sampler2DRectShadow sampler, vec4 P, ivec2 offset)
float textureProjOffset(sampler1DShadow sampler, vec4 P, int offset [, float bias] )
float textureProjOffset(sampler2DShadow sampler, vec4 P, ivec2 offset [, float bias] )

执行如 textureProj 中所述的投影纹理查找,并按 textureOffset 中所述偏移 *offset*。

gvec4 textureLodOffset(gsampler1D sampler, float P, float lod, int offset)
gvec4 textureLodOffset(gsampler2D sampler, vec2 P, float lod, ivec2 offset)
gvec4 textureLodOffset(gsampler3D sampler, vec3 P, float lod, ivec3 offset)
float textureLodOffset(sampler1DShadow sampler, vec3 P, float lod, int offset)
float textureLodOffset(sampler2DShadow sampler, vec3 P, float lod, ivec2 offset)
gvec4 textureLodOffset(gsampler1DArray sampler, vec2 P, float lod, int offset)
gvec4 textureLodOffset(gsampler2DArray sampler, vec3 P, float lod, ivec2 offset)
float textureLodOffset(sampler1DArrayShadow sampler, vec3 P, float lod, int offset)

执行带显式细节层次的偏移纹理查找。请参见 textureLodtextureOffset

gvec4 textureProjLod(gsampler1D sampler, vec2 P, float lod)
gvec4 textureProjLod(gsampler1D sampler, vec4 P, float lod)
gvec4 textureProjLod(gsampler2D sampler, vec3 P, float lod)
gvec4 textureProjLod(gsampler2D sampler, vec4 P, float lod)
gvec4 textureProjLod(gsampler3D sampler, vec4 P, float lod)
float textureProjLod(sampler1DShadow sampler, vec4 P, float lod)
float textureProjLod(sampler2DShadow sampler, vec4 P, float lod)

执行带显式细节层次的投影纹理查找。请参阅 textureProjtextureLod

gvec4 textureProjLodOffset(gsampler1D sampler, vec2 P, float lod, int offset)
gvec4 textureProjLodOffset(gsampler1D sampler, vec4 P, float lod, int offset)
gvec4 textureProjLodOffset(gsampler2D sampler, vec3 P, float lod, ivec2 offset)
gvec4 textureProjLodOffset(gsampler2D sampler, vec4 P, float lod, ivec2 offset)
gvec4 textureProjLodOffset(gsampler3D sampler, vec4 P, float lod, ivec3 offset)
float textureProjLodOffset(sampler1DShadow sampler, vec4 P, float lod, int offset)
float textureProjLodOffset(sampler2DShadow sampler, vec4 P, float lod, ivec2 offset)

执行带偏移量和显式细节层次的投影纹理查找。请参阅 textureProjtextureLodtextureOffset

gvec4 textureGrad(gsampler1D sampler, float P, float dPdx, float dPdy)
gvec4 textureGrad(gsampler2D sampler, vec2 P, vec2 dPdx, vec2 dPdy)
gvec4 textureGrad(gsampler3D sampler, vec3 P, vec3 dPdx, vec3 dPdy)
gvec4 textureGrad(gsamplerCube sampler, vec3 P, vec3 dPdx, vec3 dPdy)
gvec4 textureGrad(gsampler2DRect sampler, vec2 P, vec2 dPdx, vec2 dPdy)
float textureGrad(sampler2DRectShadow sampler, vec3 P, vec2 dPdx, vec2 dPdy)
float textureGrad(sampler1DShadow sampler, vec3 P, float dPdx, float dPdy)
gvec4 textureGrad(gsampler1DArray sampler, vec2 P, float dPdx, float dPdy)
float textureGrad(sampler1DArrayShadow sampler, vec3 P, float dPdx, float dPdy)
float textureGrad(sampler2DShadow sampler, vec3 P, vec2 dPdx, vec2 dPdy)
float textureGrad(samplerCubeShadow sampler, vec4 P, vec3 dPdx, vec3 dPdy)
gvec4 textureGrad(gsampler2DArray sampler, vec3 P, vec2 dPdx, vec2 dPdy)
float textureGrad(sampler2DArrayShadow sampler, vec4 P, vec2 dPdx, vec2 dPdy)
gvec4 textureGrad(gsamplerCubeArray sampler, vec4 P, vec3 dPdx, vec3 dPdy)

执行纹理查找,如同 texture,但带有如下所示的显式梯度P 的偏导数是相对于窗口 x 和窗口 y 的。对于立方体版本,P 的偏导数假定为在纹理坐标投影到适当的立方体面之前使用的坐标系中。

gvec4 textureGradOffset(gsampler1D sampler, float P, float dPdx, float dPdy, int offset)
gvec4 textureGradOffset(gsampler2D sampler, vec2 P, vec2 dPdx, vec2 dPdy, ivec2 offset)
gvec4 textureGradOffset(gsampler3D sampler, vec3 P, vec3 dPdx, vec3 dPdy, ivec3 offset)
gvec4 textureGradOffset(gsampler2DRect sampler, vec2 P, vec2 dPdx, vec2 dPdy, ivec2 offset)
float textureGradOffset(sampler2DRectShadow sampler, vec3 P, vec2 dPdx, vec2 dPdy, ivec2 offset)
float textureGradOffset(sampler1DShadow sampler, vec3 P, float dPdx, float dPdy, int offset)
float textureGradOffset(sampler2DShadow sampler, vec3 P, vec2 dPdx, vec2 dPdy, ivec2 offset)
gvec4 textureGradOffset(gsampler2DArray sampler, vec3 P, vec2 dPdx, vec2 dPdy, ivec2 offset)
gvec4 textureGradOffset(gsampler1DArray sampler, vec2 P, float dPdx, float dPdy, int offset)
float textureGradOffset(sampler1DArrayShadow sampler, vec3 P, float dPdx, float dPdy, int offset)
float textureGradOffset(sampler2DArrayShadow sampler, vec4 P, vec2 dPdx, vec2 dPdy, ivec2 offset)

执行带有显式梯度和偏移量的纹理查找,如 textureGradtextureOffset 中所述。

gvec4 textureProjGrad(gsampler1D sampler, vec2 P, float dPdx, float dPdy)
gvec4 textureProjGrad(gsampler1D sampler, vec4 P, float dPdx, float dPdy)
gvec4 textureProjGrad(gsampler2D sampler, vec3 P, vec2 dPdx, vec2 dPdy)
gvec4 textureProjGrad(gsampler2D sampler, vec4 P, vec2 dPdx, vec2 dPdy)
gvec4 textureProjGrad(gsampler3D sampler, vec4 P, vec3 dPdx, vec3 dPdy)
gvec4 textureProjGrad(gsampler2DRect sampler, vec3 P, vec2 dPdx, vec2 dPdy)
gvec4 textureProjGrad(gsampler2DRect sampler, vec4 P, vec2 dPdx, vec2 dPdy)
float textureProjGrad(sampler2DRectShadow sampler, vec4 P, vec2 dPdx, vec2 dPdy)
float textureProjGrad(sampler1DShadow sampler, vec4 P, float dPdx, float dPdy)
float textureProjGrad(sampler2DShadow sampler, vec4 P, vec2 dPdx, vec2 dPdy)

执行投影纹理查找,如 textureProj 中所述,并带有显式梯度,如 textureGrad 中所述。偏导数 dPdxdPdy 假定为已投影。

gvec4 textureProjGradOffset(gsampler1D sampler, vec2 P, float dPdx, float dPdy, int offset)
gvec4 textureProjGradOffset(gsampler1D sampler, vec4 P, float dPdx, float dPdy, int offset)
gvec4 textureProjGradOffset(gsampler2D sampler, vec3 P, vec2 dPdx, vec2 dPdy, ivec2 offset)
gvec4 textureProjGradOffset(gsampler2D sampler, vec4 P, vec2 dPdx, vec2 dPdy, ivec2 offset)
gvec4 textureProjGradOffset(gsampler3D sampler, vec4 P, vec3 dPdx, vec3 dPdy, ivec3 offset)
gvec4 textureProjGradOffset(gsampler2DRect sampler, vec3 P, vec2 dPdx, vec2 dPdy, ivec2 offset)
gvec4 textureProjGradOffset(gsampler2DRect sampler, vec4 P, vec2 dPdx, vec2 dPdy, ivec2 offset)
float textureProjGradOffset(sampler2DRectShadow sampler, vec4 P, vec2 dPdx, vec2 dPdy, ivec2 offset)
float textureProjGradOffset(sampler1DShadow sampler, vec4 P, float dPdx, float dPdy, int offset)
float textureProjGradOffset(sampler2DShadow sampler, vec4 P, vec2 dPdx, vec2 dPdy, ivec2 offset)

执行投影纹理查找,并带有显式梯度,如 textureProjGrad 中所述,以及带有偏移量,如 textureOffset 中所述。

显式梯度

在上面描述的 textureGrad 函数中,显式梯度控制纹理查找如下:

纹理收集函数

纹理收集函数将单个浮点向量操作数的各个分量作为纹理坐标,确定一组要从指定纹理图像的基本细节级别中采样的四个纹素,并在一个四分量结果向量中返回每个纹素的一个分量。

当执行纹理收集操作时,将忽略缩小和放大过滤器,并应用OpenGL规范中关于线性过滤的规则,以确定纹理图像基本级别的四个纹素 i0 j1i1 j1i1 j0i0 j0。然后,根据表 15.1 将这些纹素转换为纹理基本颜色 (Rs, Gs, Bs, As),再按照OpenGL规范第 15.2.1 节 “纹理访问” 中的描述应用纹理置换。通过按照 (i0 j1, i1 j1, i1 j0, i0 j0) 的顺序,从每个置换后的纹理源颜色中选取选定的分量,组装成一个四分量向量。

对于使用纹理组合阴影采样器类型的纹理收集函数,每个纹素查找都会针对传入的深度参考值 (refZ) 执行深度比较,并在结果向量的相应分量中返回该比较的结果。

与其他纹理查找函数一样,如果引用的纹理不是深度纹理或禁用了深度比较,则阴影采样器的纹理收集结果是未定义的;如果引用的纹理是启用了深度比较的深度纹理,则非阴影采样器的纹理收集结果也是未定义的。

语法 描述

gvec4 textureGather(gsampler2D sampler, vec2 P [, int comp])
gvec4 textureGather(gsampler2DArray sampler, vec3 P [, int comp])
gvec4 textureGather(gsamplerCube sampler, vec3 P [, int comp])
gvec4 textureGather(gsamplerCubeArray sampler, vec4 P[, int comp])
gvec4 textureGather(gsampler2DRect sampler, vec2 P[, int comp])
vec4 textureGather(sampler2DShadow sampler, vec2 P, float refZ)
vec4 textureGather(sampler2DArrayShadow sampler, vec3 P, float refZ)
vec4 textureGather(samplerCubeShadow sampler, vec3 P, float refZ)
vec4 textureGather(samplerCubeArrayShadow sampler, vec4 P, float refZ)
vec4 textureGather(sampler2DRectShadow sampler, vec2 P, float refZ)

返回值

vec4(Sample_i0_j1(P, base).comp,
     Sample_i1_j1(P, base).comp,
     Sample_i1_j0(P, base).comp,
     Sample_i0_j0(P, base).comp)

如果指定了 comp 的值,则它必须是一个值为 0、1、2 或 3 的常量整数表达式,分别标识每个纹素的四分量向量查找结果的置换后的 xyzw 分量。如果未指定 comp,则将其视为 0,选择每个纹素的 x 分量来生成结果。

gvec4 textureGatherOffset(gsampler2D sampler, vec2 P, ivec2 offset, [ int comp])
gvec4 textureGatherOffset(gsampler2DArray sampler, vec3 P, ivec2 offset [ int comp])
vec4 textureGatherOffset(sampler2DShadow sampler, vec2 P, float refZ, ivec2 offset)
vec4 textureGatherOffset(sampler2DArrayShadow sampler, vec3 P, float refZ, ivec2 offset)
gvec4 textureGatherOffset(gsampler2DRect sampler, vec2 P, ivec2 offset [ int comp])
vec4 textureGatherOffset(sampler2DRectShadow sampler, vec2 P, float refZ, ivec2 offset)

执行与 textureGather 中相同的纹理收集操作,但会像 textureOffset 中描述的那样进行 offset 偏移。不同之处在于,offset 可以是可变的(非常量),并且实现相关的最小和最大偏移值分别由 MIN_PROGRAM_TEXTURE_GATHER_OFFSET 和 MAX_PROGRAM_TEXTURE_GATHER_OFFSET 给出。

gvec4 textureGatherOffsets(gsampler2D sampler, vec2 P, ivec2 offsets[4] [, int comp])
gvec4 textureGatherOffsets(gsampler2DArray sampler, vec3 P, ivec2 offsets[4] [, int comp])
vec4 textureGatherOffsets(sampler2DShadow sampler, vec2 P, float refZ, ivec2 offsets[4])
vec4 textureGatherOffsets(sampler2DArrayShadow sampler, vec3 P, float refZ, ivec2 offsets[4])
gvec4 textureGatherOffsets(gsampler2DRect sampler, vec2 P, ivec2 offsets[4] [, int comp])
vec4 textureGatherOffsets(sampler2DRectShadow sampler, vec2 P, float refZ, ivec2 offsets[4])

textureGatherOffset 的操作相同,但使用 offsets 来确定要采样的四个纹素的位置。通过将 offsets 中相应的偏移量作为 (u, v) 坐标偏移应用于 P 来获取每个纹素,从而确定四纹素线性足迹,然后选择该足迹的纹素 i0 j0offsets 中指定的值必须是常量整数表达式。

兼容性配置文件纹理函数

以下纹理函数仅存在于兼容性配置文件中。

语法 描述

vec4 texture1D(sampler1D sampler, float coord [, float bias] )
vec4 texture1DProj(sampler1D sampler, vec2 coord [, float bias] )
vec4 texture1DProj(sampler1D sampler, vec4 coord [, float bias] )
vec4 texture1DLod(sampler1D sampler, float coord, float lod)
vec4 texture1DProjLod(sampler1D sampler, vec2 coord, float lod)
vec4 texture1DProjLod(sampler1D sampler, vec4 coord, float lod)

请参阅上面没有 “1D” 名称的相应签名。

vec4 texture2D(sampler2D sampler, vec2 coord [, float bias] )
vec4 texture2DProj(sampler2D sampler, vec3 coord [, float bias] )
vec4 texture2DProj(sampler2D sampler, vec4 coord [, float bias] )
vec4 texture2DLod(sampler2D sampler, vec2 coord, float lod)
vec4 texture2DProjLod(sampler2D sampler, vec3 coord, float lod)
vec4 texture2DProjLod(sampler2D sampler, vec4 coord, float lod)

请参阅上面没有 “2D” 名称的相应签名。

vec4 texture3D(sampler3D sampler, vec3 coord [, float bias] )
vec4 texture3DProj(sampler3D sampler, vec4 coord [, float bias] )
vec4 texture3DLod(sampler3D sampler, vec3 coord, float lod)
vec4 texture3DProjLod(sampler3D sampler, vec4 coord, float lod)

请参阅上面没有 “3D” 名称的相应签名。
使用纹理坐标 coord 在当前绑定到 sampler 的 3D 纹理中执行纹理查找。对于投影(“Proj”)版本,纹理坐标除以 coord.q

vec4 textureCube(samplerCube sampler, vec3 coord [, float bias] )
vec4 textureCubeLod(samplerCube sampler, vec3 coord, float lod)

请参阅上面没有 “Cube” 名称的相应签名。

vec4 shadow1D(sampler1DShadow sampler, vec3 coord [, float bias] )
vec4 shadow2D(sampler2DShadow sampler, vec3 coord [, float bias] )
vec4 shadow1DProj(sampler1DShadow sampler, vec4 coord [, float bias] )
vec4 shadow2DProj(sampler2DShadow sampler, vec4 coord [, float bias] )
vec4 shadow1DLod(sampler1DShadow sampler, vec3 coord, float lod)
vec4 shadow2DLod(sampler2DShadow sampler, vec3 coord, float lod)
vec4 shadow1DProjLod(sampler1DShadow sampler, vec4 coord, float lod)
vec4 shadow2DProjLod(sampler2DShadow sampler, vec4 coord, float lod)

功能与上面基于 “texture” 的名称相同,签名也相同。

原子计数器函数

本节中的原子计数器操作彼此之间是原子性的。它们对于任何单个计数器都是原子性的,这意味着一个着色器实例中对特定计数器进行的任何这些操作都不能被另一个着色器实例中对同一计数器进行的任何这些操作所分割。不能保证这些操作相对于对计数器的其他形式的访问是原子性的,也不能保证当应用于单独的计数器时它们是串行化的。如果需要原子性或串行化,则此类情况需要额外使用栅栏、屏障或其他形式的同步。

底层计数器是一个 32 位无符号整数。操作的结果将回绕到 [0, 232-1]。

语法 描述

uint atomicCounterIncrement(atomic_uint c)

原子地

  1. 递增 c 的计数器,并且

  2. 返回递增操作之前的值。

这两个步骤相对于此表中的原子计数器函数是原子地完成的。

uint atomicCounterDecrement(atomic_uint c)

原子地

  1. 递减 c 的计数器,并且

  2. 返回递减操作产生的值。

这两个步骤相对于此表中的原子计数器函数是原子地完成的。

uint atomicCounter(atomic_uint c)

返回 c 的计数器值。

uint atomicCounterAdd(atomic_uint c, uint data)

原子地

  1. data 的值加到 c 的计数器,并且

  2. 返回操作之前的值。

这两个步骤相对于此表中的原子计数器函数是原子地完成的。

uint atomicCounterSubtract(atomic_uint c, uint data)

原子地

  1. c 的计数器中减去 data 的值,并且

  2. 返回操作之前的值。

这两个步骤相对于此表中的原子计数器函数是原子地完成的。

uint atomicCounterMin(atomic_uint c, uint data)

原子地

  1. c 的计数器设置为计数器的值和 data 的值中的最小值,并且

  2. 返回操作之前的值。

这两个步骤相对于此表中的原子计数器函数是原子地完成的。

uint atomicCounterMax(atomic_uint c, uint data)

原子地

  1. c 的计数器设置为计数器的值和 data 的值中的最大值,并且

  2. 返回操作之前的值。

这两个步骤相对于此表中的原子计数器函数是原子地完成的。

uint atomicCounterAnd(atomic_uint c, uint data)

原子地

  1. c 的计数器设置为计数器的值和 data 的值的按位与,并且

  2. 返回操作之前的值。

这两个步骤相对于此表中的原子计数器函数是原子地完成的。

uint atomicCounterOr(atomic_uint c, uint data)

原子地

  1. c 的计数器设置为计数器的值和 data 的值的按位或,并且

  2. 返回操作之前的值。

这两个步骤相对于此表中的原子计数器函数是原子地完成的。

uint atomicCounterXor(atomic_uint c, uint data)

原子地

  1. c 的计数器设置为计数器的值和 data 的值的按位异或,并且

  2. 返回操作之前的值。

这两个步骤相对于此表中的原子计数器函数是原子地完成的。

uint atomicCounterExchange(atomic_uint c, uint data)

原子地

  1. c 的计数器值设置为 data 的值,并且

  2. 返回操作之前的值。

这两个步骤相对于此表中的原子计数器函数是原子地完成的。

uint atomicCounterCompSwap(atomic_uint c, uint compare, uint data)

原子地

  1. 比较 compare 的值和 c 的计数器值

  2. 如果值相等,则将 c 的计数器值设置为 data 的值,并且

  3. 返回操作之前的值。

这三个步骤相对于此表中的原子计数器函数是原子地完成的。

原子内存函数

原子内存函数对存储在缓冲区对象或共享变量存储中的单个有符号或无符号整数执行原子操作。所有原子内存操作都会从内存中读取一个值,使用下面描述的操作之一计算一个新值,将新值写入内存,并返回读取的原始值,并转换为着色器中声明的精度。请注意,操作是在存储的内存中精度下执行的,这可能与着色器中声明的精度不同。

保证在读取原始值和写入新值之间,任何着色器调用中的任何其他赋值或原子内存函数都不会修改原子操作正在更新的内存内容。

原子内存函数仅支持有限的变量集。如果传递给原子内存函数的 mem 参数的值与缓冲区或共享变量不对应,则着色器将无法编译。只要基础数组或向量是缓冲区或共享变量,则将数组的元素或向量的单个分量传递给原子内存函数的 mem 参数是可接受的。

本节中的所有内置函数都接受具有 restrictcoherentvolatile 内存限定的组合的参数,尽管它们没有在原型中列出。原子操作将根据调用参数的内存限定(而不是内置函数的形参内存限定)的要求进行操作。

语法 描述

uint atomicAdd(inout uint mem, uint data)
int atomicAdd(inout int mem, int data)

通过将 data 的值加到 mem 的内容来计算新值。

uint atomicMin(inout uint mem, uint data)
int atomicMin(inout int mem, int data)

通过取 data 的值和 mem 的内容的最小值来计算新值。

uint atomicMax(inout uint mem, uint data)
int atomicMax(inout int mem, int data)

通过取 data 的值和 mem 的内容的最大值来计算新值。

uint atomicAnd(inout uint mem, uint data)
int atomicAnd(inout int mem, int data)

通过对 data 的值和 mem 的内容执行按位与来计算新值。

uint atomicOr(inout uint mem, uint data)
int atomicOr(inout int mem, int data)

通过对 data 的值和 mem 的内容执行按位或来计算新值。

uint atomicXor(inout uint mem, uint data)
int atomicXor(inout int mem, int data)

通过对 data 的值和 mem 的内容执行按位异或来计算新值。

uint atomicExchange(inout uint mem, uint data)
int atomicExchange(inout int mem, int data)

通过简单地复制 data 的值来计算新值。

uint atomicCompSwap(inout uint mem, uint compare, uint data)
int atomicCompSwap(inout int mem, int compare, int data)

比较 compare 的值和 mem 的内容。如果值相等,则新值由 data 给出;否则,新值取自 mem 的原始内容。

图像函数

使用图像基本类型之一的变量可以通过本节中定义的内置着色器图像内存函数来读取和写入纹理的各个纹素。每个图像变量都引用一个图像单元,该单元附加了一个纹理图像。

当下面的图像内存函数访问内存时,图像中的单个纹素将使用对应于 P 值的 (i)、(i, j) 或 (i, j, k) 坐标进行标识。对于 image2DMSimage2DMSArray 变量(以及对应的 int/unsigned int 类型),对应于多重采样纹理,每个纹素可能具有多个采样,并且使用整数 sample 参数标识单个采样。坐标和采样号用于选择单个纹素,其方式在 OpenGL 规范 的第 8.26 节“纹理图像加载和存储”中描述。

加载和存储支持浮点型、整型和无符号整型。下面以 gimage 开头的数据类型充当占位符,表示以“image”、“iimage”或“uimage”开头的类型,其方式与前面部分中的 "gvec" 或 "gsampler" 相同。

下面原型中的 IMAGE_PARAMS 是一个占位符,表示 33 个独立的函数,每个函数对应一种不同的图像变量类型。IMAGE_PARAMS 占位符将替换为以下参数列表之一

gimage2D image, ivec2 P

gimage3D image, ivec3 P

gimageCube image, ivec3 P

gimageBuffer image, int P

gimage2DArray image, ivec3 P

gimageCubeArray image, ivec3 P

gimage1D image, int P

gimage1DArray image, ivec2 P

gimage2DRect image, ivec2 P

gimage2DMS image, ivec2 P, int sample

gimage2DMSArray image, ivec3 P, int sample

其中每一行表示三种不同的图像变量类型之一,并且 imagePsample 指定要操作的单个纹素。根据 imagePsample 标识要操作的单个纹素的方法,以及读取和写入纹素的方法在 OpenGL 规范 的第 8.26 节“纹理图像加载和存储”中指定。

原子函数对图像变量的单个纹素或采样执行操作。原子内存操作从选定的纹素读取一个值,使用下面描述的操作之一计算一个新值,将新值写入选定的纹素,并返回读取的原始值。保证在读取原始值和写入新值之间,原子操作正在更新的纹素的内容不会被任何其他图像存储或原子函数修改。

原子内存操作仅支持所有图像变量类型的一个子集;image 必须是

  • 一个带符号的整型图像变量(类型以“iimage”开头),且格式限定符为 r32i,与类型为 intdata 参数一起使用,或者

  • 一个无符号的整型图像变量(类型以“uimage”开头),且格式限定符为 r32ui,与类型为 uintdata 参数一起使用,或者

  • 一个浮点型图像变量(类型以“image”开头),且格式限定符为 r32f,与类型为 floatdata 参数一起使用(仅 imageAtomicExchange)。

本节中的所有内置函数都接受带有 restrictcoherentvolatile 内存限定的参数组合,尽管在原型中没有列出这些限定。图像操作将按照调用参数的内存限定要求进行操作,而不是按照内置函数的正式参数内存限定进行操作。

语法 描述

int imageSize(readonly writeonly gimage1D image)
ivec2 imageSize(readonly writeonly gimage2D image)
ivec3 imageSize(readonly writeonly gimage3D image)
ivec2 imageSize(readonly writeonly gimageCube image)
ivec3 imageSize(readonly writeonly gimageCubeArray image)
ivec3 imageSize(readonly writeonly gimage2DArray image)
ivec2 imageSize(readonly writeonly gimage2DRect image)
ivec2 imageSize(readonly writeonly gimage1DArray image)
ivec2 imageSize(readonly writeonly gimage2DMS image)
ivec3 imageSize(readonly writeonly gimage2DMSArray image)
int imageSize(readonly writeonly gimageBuffer image)

返回绑定到 image 的图像的维度。对于数组图像,返回值的最后一个分量将保存数组的大小。立方体图像仅返回一个面的维度,以及立方体贴图数组中的立方体数量(如果已数组化)。
注意:限定词 readonly writeonly 接受使用 readonlywriteonly、两者或两者都不是限定的变量。这意味着正式参数将不用于读取或写入底层内存。

int imageSamples(readonly writeonly gimage2DMS image)
int imageSamples(readonly writeonly gimage2DMSArray image)

返回绑定到 image 的图像的采样数。

gvec4 imageLoad(readonly IMAGE_PARAMS)

从图像单元 image(在 IMAGE_PARAMS 中)加载坐标 P 处的纹素。对于多重采样加载,采样号由 sample 给出。当 imagePsample 标识有效的纹素时,用于表示内存中选定纹素的位将转换为 vec4ivec4uvec4,其方式在 OpenGL 规范 的第 8.26 节“纹理图像加载和存储”中描述并返回。

void imageStore(writeonly IMAGE_PARAMS, gvec4 data)

data 存储到由 image 指定的图像中坐标 P 处的纹素中。对于多重采样存储,采样号由 sample 给出。当 imagePsample 标识有效的纹素时,用于表示 data 的位将转换为图像单元的格式,其方式在 OpenGL 规范 的第 8.26 节“纹理图像加载和存储”中描述并存储到指定的纹素。

uint imageAtomicAdd(IMAGE_PARAMS, uint data)
int imageAtomicAdd(IMAGE_PARAMS, int data)

通过将 data 的值添加到选定纹素的内容来计算新值。

uint imageAtomicMin(IMAGE_PARAMS, uint data)
int imageAtomicMin(IMAGE_PARAMS, int data)

通过取 data 的值和选定纹素内容的最小值来计算新值。

uint imageAtomicMax(IMAGE_PARAMS, uint data)
int imageAtomicMax(IMAGE_PARAMS, int data)

通过取 data 的值和选定纹素内容的最大值来计算新值。

uint imageAtomicAnd(IMAGE_PARAMS, uint data)
int imageAtomicAnd(IMAGE_PARAMS, int data)

通过对 data 的值和选定纹素的内容执行按位与操作来计算新值。

uint imageAtomicOr(IMAGE_PARAMS, uint data)
int imageAtomicOr(IMAGE_PARAMS, int data)

通过对 data 的值和选定纹素的内容执行按位或操作来计算新值。

uint imageAtomicXor(IMAGE_PARAMS, uint data)
int imageAtomicXor(IMAGE_PARAMS, int data)

通过对 data 的值和选定纹素的内容执行按位异或操作来计算新值。

uint imageAtomicExchange(IMAGE_PARAMS, uint data)
int imageAtomicExchange(IMAGE_PARAMS, int data)
float imageAtomicExchange(IMAGE_PARAMS, float data)

通过简单地复制 data 的值来计算新值。

uint imageAtomicCompSwap(IMAGE_PARAMS, uint compare, uint data)
int imageAtomicCompSwap(IMAGE_PARAMS, int compare, int data)

比较 compare 的值和选定纹素的内容。如果值相等,则新值由 data 给出;否则,从纹素加载的原始值中获取。

几何着色器函数

这些函数仅在几何着色器中可用。它们将在下表中进行更详细的描述。

语法 描述

void EmitStreamVertex(int stream)

将输出变量的当前值发射到流 stream 上的当前输出图元。stream 的参数必须是常量整数表达式。从此调用返回后,所有输出变量的值都将是不确定的。
只有在支持多个输出流时才能使用。

void EndStreamPrimitive(int stream)

完成流 stream 上的当前输出图元,并启动一个新的图元。stream 的参数必须是常量整数表达式。不会发射顶点。
只有在支持多个输出流时才能使用。

void EmitVertex()

将输出变量的当前值发射到当前输出图元。当支持多个输出流时,这等效于调用 EmitStreamVertex(0)。
从此调用返回后,输出变量的值是不确定的。

void EndPrimitive()

完成当前输出图元,并启动一个新的图元。当支持多个输出流时,这等效于调用 EndStreamPrimitive(0)。
不会发射顶点。

函数 EmitStreamVertex() 指定顶点已完成。使用与 stream 关联的所有内置和用户定义的输出变量的当前值,将顶点添加到顶点流 stream 中的当前输出图元。调用 EmitStreamVertex() 后,所有输出流的所有输出变量的值都不确定。如果几何着色器调用发射的顶点数超过了输出布局限定符 max_vertices 允许的数量,则调用 EmitStreamVertex() 的结果是不确定的。

函数 EndStreamPrimitive() 指定顶点流 stream 的当前输出图元已完成,并且任何后续的 EmitStreamVertex() 将启动新的输出图元(类型相同)。此函数不会发射顶点。如果输出布局声明为 points,则调用 EndStreamPrimitive() 是可选的。

几何着色器以每个流的没有顶点的输出图元开始。当几何着色器终止时,每个流的当前输出图元会自动完成。如果几何着色器仅写入单个图元,则无需调用 EndStreamPrimitive()。

仅当输出图元类型声明为 points 时,才支持多个输出流。如果程序包含调用 EmitStreamVertex() 或 EndStreamPrimitive() 的几何着色器,但其输出图元类型不是 points,则会出现编译时或链接时错误。

片段处理函数

片段处理函数仅在片段着色器中可用。

导数函数

导数可能在计算上很昂贵和/或数值不稳定。因此,实现方式可以使用快速但不完全准确的导数计算来近似真实的导数。导数在非均匀控制流中是不确定的。

导数的预期行为是使用前向/后向差分指定的。

前向差分

后向差分

对于单样本光栅化, 在公式 1b 和 2b 中使用。对于多重采样光栅化, 在公式 1b 和 2b 中使用。

的近似方式类似,只是用 y 替换了 x

对于多重采样光栅化,对于任何给定的片元或采样,可以考虑相邻的片元或采样。

通常会考虑一个 2x2 的片元或采样正方形,并为每行计算独立的 dFdxFine,为每列计算独立的 dFdyFine,同时为整个 2x2 正方形仅计算一个 dFdxCoarse 和一个 dFdyCoarse。因此,所有二阶粗导数,例如 dFdxCoarse(dFdxCoarse(x)),即使对于非线性参数,也可能为 0。但是,二阶精细导数,例如 dFdxFine(dFdyFine(x)),将正确反映在 2x2 正方形内计算的独立精细导数之间的差异。

该方法可能因片元而异,但受限于该方法可能因窗口坐标而不是屏幕坐标而异。在 OpenGL 规范 的第 14.2 节“不变性”中描述的不变性要求,对于导数计算被放宽,因为该方法可能是片元位置的函数。

在某些实现中,可以通过提供 GL 提示(请参阅 OpenGL 规范 的第 21.4 节“提示”)来获得 dFdxdFdy 的不同程度的导数精度,从而允许用户在图像质量与速度之间进行权衡。这些提示对 dFdxCoarsedFdyCoarsedFdxFinedFdyFine 没有影响。

语法 描述

genFType dFdx(genFType p)

根据实现选择,返回 dFdxFine(p) 或 dFdxCoarse(p) 中的一个,可能是速度更快的那个,或者通过 API 中质量与速度提示选择的那个。

genFType dFdy(genFType p)

根据实现选择,返回 dFdyFine(p) 或 dFdyCoarse(p) 中的一个,可能是速度更快的那个,或者通过 API 中质量与速度提示选择的那个。

genFType dFdxFine(genFType p)

返回 p 相对于窗口 x 坐标的偏导数。将使用基于当前片元及其相邻片元(们) 的 p 值的局部差分。

genFType dFdyFine(genFType p)

返回 p 相对于窗口 y 坐标的偏导数。将使用基于当前片元及其相邻片元(们) 的 p 值的局部差分。

genFType dFdxCoarse(genFType p)

返回 p 相对于窗口 x 坐标的偏导数。将使用基于当前片元的相邻片元的 p 值的局部差分,并且可能但不一定包括当前片元的 p 值。也就是说,在给定区域上,实现可以比 dFdxFine(p) 允许的更少的唯一位置计算 x 导数。

genFType dFdyCoarse(genFType p)

返回 p 相对于窗口 y 坐标的偏导数。将使用基于当前片元的相邻片元的 p 值的局部差分,并且可能但不一定包括当前片元的 p 值。也就是说,在给定区域上,实现可以比 dFdyFine(p) 允许的更少的唯一位置计算 y 导数。

genFType fwidth(genFType p)

返回 abs(dFdx(p)) + abs(dFdy(p))。

genFType fwidthFine(genFType p)

返回 abs(dFdxFine(p)) + abs(dFdyFine(p))。

genFType fwidthCoarse(genFType p)

返回 abs(dFdxCoarse(p)) + abs(dFdyCoarse(p))。

插值函数

内置插值函数可用于计算片段着色器输入变量在着色器指定的 (x, y) 位置的插值。对于内置函数的每次调用,可以使用单独的 (x, y) 位置,并且这些位置可能与用于生成输入默认值的默认 (x, y) 位置不同。

对于所有插值函数,interpolant 必须是 in 声明中的左值;这可以包括变量、块或结构成员、数组元素,或者它们的某种组合。此外,可以将组件选择运算符(例如 .xy.xxz)应用于 interpolant,在这种情况下,插值函数将返回将组件选择运算符应用于 interpolant 插值的的结果(例如,interpolateAt(v.xxz) 定义为返回 interpolateAt(v).xxz)。可以使用通用(非均匀)整数表达式索引数组输入。

如果使用 flat 限定符声明 interpolant,则对于单个图元,插值将具有相同的值,因此用于插值的位置不起作用,并且函数仅返回相同的值。如果使用 centroid 限定符声明 interpolant,则 interpolateAtSample() 和 interpolateAtOffset() 返回的值将在指定的位置进行计算,忽略通常与 centroid 限定符一起使用的位置。如果使用 noperspective 限定符声明 interpolant,则将在不进行透视校正的情况下计算插值。

语法 描述

float interpolateAtCentroid(float interpolant)
vec2 interpolateAtCentroid(vec2 interpolant)
vec3 interpolateAtCentroid(vec3 interpolant)
vec4 interpolateAtCentroid(vec4 interpolant)

返回在像素和正在处理的图元内的位置采样的输入 interpolant 的值。如果使用 centroid 限定符声明输入变量,则获得的值将与分配给输入变量的值相同。

float interpolateAtSample(float interpolant, int sample)
vec2 interpolateAtSample(vec2 interpolant, int sample)
vec3 interpolateAtSample(vec3 interpolant, int sample)
vec4 interpolateAtSample(vec4 interpolant, int sample)

返回在样本编号为 sample 的位置的输入 interpolant 变量的值。如果多重采样缓冲区不可用,则将在像素中心评估输入变量。如果样本 sample 不存在,则用于插值输入变量的位置是未定义的。

float interpolateAtOffset(float interpolant, vec2 offset)
vec2 interpolateAtOffset(vec2 interpolant, vec2 offset)
vec3 interpolateAtOffset(vec3 interpolant, vec2 offset)
vec4 interpolateAtOffset(vec4 interpolant, vec2 offset)

返回在由 offset 指定的像素中心偏移位置采样的输入 interpolant 变量的值。offset 的两个浮点分量分别给出 xy 方向的像素偏移。
偏移量 (0, 0) 表示像素中心。此函数支持的偏移范围和粒度取决于实现。

噪声函数

从 GLSL 的 4.4 版本开始,噪声函数 noise1noise2noise3noise4 已被弃用。在不生成 SPIR-V 时,它们被定义为返回值 0.0 或分量全为 0.0 的向量。在生成 SPIR-V 时,不声明噪声函数,并且可能不使用噪声函数。

与之前的版本一样,噪声函数在语义上不被认为是编译时常量表达式。

语法(已弃用) 描述(已弃用)

float noise1(genFType x)

基于输入值 x 返回一维噪声值。

vec2 noise2(genFType x)

基于输入值 x 返回二维噪声值。

vec3 noise3(genFType x)

基于输入值 x 返回三维噪声值。

vec4 noise4(genFType x)

基于输入值 x 返回四维噪声值。

着色器调用控制函数

着色器调用控制函数仅在曲面细分控制着色器和计算着色器中可用。它用于控制多个着色器调用的相对执行顺序,这些调用用于处理补丁(在曲面细分控制着色器的情况下)或工作组(在计算着色器的情况下),否则这些调用的相对顺序未定义。

语法 描述

void barrier()

对于 barrier() 的任何给定静态实例,单个输入补丁的所有曲面细分控制着色器调用都必须进入它,然后才允许任何调用继续超出它,或者单个工作组的所有计算着色器调用都必须进入它,然后才允许任何调用继续超出它。

函数 barrier() 在着色器调用之间提供了一个部分定义的执行顺序。它确保,对于某些类型的内存访问,在给定静态 barrier() 实例之前,由一个调用写入的值可以由其他调用在调用相同静态实例 barrier() 之后安全地读取。由于调用可能在这些屏障调用之间以未定义的顺序执行,因此曲面细分控制着色器的每个顶点或每个补丁输出变量的值,或者计算着色器的 shared 变量的值,将在 “输出变量”(对于曲面细分控制着色器)和 “共享变量”(对于计算着色器)中列出的多种情况下未定义。

对于曲面细分控制着色器,barrier() 函数只能放置在着色器的函数 main() 内,并且不能在任何控制流中调用。在函数 main() 的 return 语句之后也禁止使用屏障。任何此类放置错误的屏障都会导致编译时错误。

barrier() 会影响控制流,但仅同步对 shared 变量和曲面细分控制输出变量的内存访问。对于其他内存访问,它不能确保在给定静态 barrier() 实例之前由一个调用写入的值可以由其他调用在调用相同静态实例 barrier() 之后安全地读取。要实现此目的,需要同时使用 barrier() 和内存屏障。

对于计算着色器,barrier() 函数可以放置在控制流中,但是该控制流必须是统一控制流。也就是说,导致屏障执行的所有控制表达式必须是动态统一的表达式。这确保了如果任何着色器调用进入条件语句,则所有调用都将进入它。虽然鼓励编译器在它们可以检测到可能不会发生这种情况时给出警告,但是编译器不能完全确定这一点。因此,作者有责任确保 barrier() 仅存在于统一的控制流内部。否则,某些着色器调用将无限期地停滞,等待其他调用永远无法到达的屏障。

着色器内存控制函数

在单个着色器调用中,该调用进行的写入的可见性和顺序是明确定义的。但是,来自多个单独着色器调用的对单个共享内存地址的读取和写入的相对顺序在很大程度上是未定义的。此外,单个着色器调用执行的对多个内存地址的访问的顺序(如其他着色器调用所观察到的)也是未定义的。

以下内置函数可用于控制读取和写入的顺序

语法 描述

void memoryBarrier()

控制单个着色器调用发出的内存事务的顺序。

void memoryBarrierAtomicCounter()

控制单个着色器调用发出的对原子计数器变量的访问顺序。

void memoryBarrierBuffer()

控制单个着色器调用中发出的对缓冲区变量的内存事务处理顺序。

void memoryBarrierShared()

控制单个着色器调用中发出的对共享变量的内存事务处理顺序,此顺序是同一工作组中的其他调用所看到的。
仅在计算着色器中可用。

void memoryBarrierImage()

控制单个着色器调用中发出的对图像的内存事务处理顺序。

void groupMemoryBarrier()

控制单个着色器调用中发出的所有内存事务处理的顺序,此顺序是同一工作组中的其他调用所看到的。
仅在计算着色器中可用。

内存屏障内置函数可用于对存储在其他着色器调用可访问的内存中的变量的读写操作进行排序。调用这些函数时,它们将等待调用方先前执行的所有对所选变量类型的读取和写入操作完成,然后返回,而没有其他效果。内置函数 memoryBarrierAtomicCounter()、memoryBarrierBuffer()、memoryBarrierImage() 和 memoryBarrierShared() 分别等待对原子计数器、缓冲区、图像和共享变量的访问完成。内置函数 memoryBarrier() 和 groupMemoryBarrier() 等待对上述所有变量类型的访问完成。函数 memoryBarrierShared() 和 groupMemoryBarrier() 仅在计算着色器中可用;其他函数在所有着色器类型中均可用。

当这些函数返回时,在调用之前使用一致性变量执行的任何内存存储的效果对于任何其他着色器调用对同一内存执行的任何未来1一致性访问都将可见。特别是,当后续阶段中的着色器调用是由原始着色器调用的执行触发时(例如,由特定几何着色器调用产生的基元的片元着色器调用),保证在着色器阶段中以此方式写入的值对由这些着色器调用执行的一致性内存访问可见。

1

仅当在存储和加载之间建立“先行发生”(happens-before)关系时,访问才是未来的访问。

此外,内存屏障函数会按照其他着色器调用的观察顺序来排列调用调用执行的存储。如果没有内存屏障,如果一个着色器调用对一致性变量执行两次存储,则第二个着色器调用可能会在看到第一个存储写入的值之前看到第二个存储写入的值。但是,如果第一个着色器调用在两个存储之间调用内存屏障函数,则选定的其他着色器调用将永远不会在看到第一个存储的结果之前看到第二个存储的结果。当使用函数 groupMemoryBarrier() 或 memoryBarrierShared() 时,此排序保证仅适用于同一计算着色器工作组中的其他着色器调用;所有其他内存屏障函数都向所有其他着色器调用提供此保证。不需要内存屏障来保证执行存储的调用所观察到的内存存储顺序;一个调用读取其先前写入的变量时,始终会看到最近写入的值,除非另一个着色器调用也写入了同一内存。

子通道输入函数

仅当目标为 Vulkan 片元阶段时,子通道输入函数才可用。

子通道输入通过以下内置函数读取。g 再次是占位符,可以是无、iu,表示浮点数、有符号整数或无符号整数,并且这些必须在参数类型和返回类型之间匹配。

语法 描述

gvec4 subpassLoad(gsubpassInput subpass)
gvec4 subpassLoad(gsubpassInputMS subpass, int sample)

从子通道输入读取,从当前片元坐标的隐式位置 (x, y, layer) 读取。

着色器调用组函数

OpenGL 着色语言的实现可以选择将单个着色器阶段的多个着色器调用分组到单个 SIMD 调用组中,其中调用以未定义且与实现相关的方式分配到组中。此类实现上的着色器算法可能会受益于能够评估组中所有活动调用上的布尔值的组合。

语法 描述

bool anyInvocation(bool value)

当且仅当组中至少有一个活动调用的 valuetrue 时,返回 true

bool allInvocations(bool value)

当且仅当组中所有活动调用的 value 均为 true 时,返回 true

bool allInvocationsEqual(bool value)

如果组中所有活动调用的 value 相同,则返回 true

对于所有这些函数,会将相同的结果返回到组中的所有活动调用。

可以在有条件执行的代码中调用这些函数。在某些调用未执行函数调用的组中,函数返回的值不受任何未调用该函数的调用的影响,即使该调用的 value 是明确定义的。

由于这些函数依赖于未定义的一组调用中 value 的值,因此这些函数返回的值在很大程度上是未定义的。但是,如果 valuetrue,则保证 anyInvocation() 返回 true;如果 valuefalse,则保证 allInvocations() 返回 false

由于不需要实现将调用合并到组中,因此对于 anyInvocation() 和 allInvocations() 简单地返回 value,以及对于 allInvocationsEqual() 返回 true 是这些函数的合法实现。

对于片元着色器,SIMD 调用组中的调用可能包括与正在光栅化的基元覆盖的像素相对应的调用,以及与未被基元覆盖的相邻像素相对应的调用。可以创建辅助调用(请参阅“内置语言变量”),并且此类辅助调用像素的 value 值可能会影响 anyInvocation()、allInvocations() 和 allInvocationsEqual() 返回的值。