OpenGL ES着色器语言规范 6.1 函数定义

目录

6.1 函数定义

6.1.1 函数调用惯例


6.1 函数定义

如上面的语法所示,有效着色器是一系列全局声明和函数定义。 声明一个函数,如下例所示:

// prototype
returnType functionName (type0 arg0, type1 arg1, ..., typen argn);

而函数定义如下:

// definition
returnType functionName (type0 arg0, type1 arg1, ..., typen argn)
{
 // do some computation
 return returnValue;
}

其中returnType必须存在且包含类型。 每个typeN必须包含一个类型,并且可以选择包括参数限定符const精度限定符

通过使用其名称后跟括号中的参数列表来调用函数。

允许数组作为参数,但不允许作为返回类型。 当数组声明为形式参数时,必须包含它们的大小。通过使用数组名称而不使用任何下标或括号将数组传递给函数,并且传入的数组参数的大小必须与形式参数声明中指定的大小匹配。

结构也被允许作为参数。 如果结构不包含数组,则返回类型也可以是结构。

有关声明和定义函数的语法的权威性参考,请参见第9节“着色语言语法”。

所有函数必须使用原型声明,或者在调用之前使用带有方法体的方式定义。例如:

float myfunc (float f, // f is an input parameter
 out float g); // g is an output parameter

函数声明必须指定返回类型。 此类型可能void。 如果返回类型不是void,则函数定义中的任何return语句都必须包含return表达式,并且表达式的类型必须与返回类型匹配。 如果函数的返回类型指定为void,则任何此类return语句都不能包含return表达式。不接受输入参数的函数不需要在参数列表中使用void,因为原型(或定义)是必需的,因此当声明空参数列表“()”时没有歧义。 为方便起见,提供了作为参数列表的约定俗成的表达“(void)”

函数名称可以重载。 这允许相同的函数名称用于多个函数,只要参数列表类型不同即可。如果函数的名称和参数类型匹配,则它们的返回类型和参数限定符也必须匹配。 函数签名匹配仅基于参数类型,不使用限定符。 重载在内置函数中使用很多。 当解析重载函数(或实际上任何函数)时,寻求函数签名的精确匹配。 这包括数组大小的精确匹配。 不会对返回类型或输入参数类型进行升级或降级。 必须将所有预期的输入和输出组合定义为单独的功能。

例如,内置点乘函数具有以下原型:

float dot (float x, float y);
float dot (vec2 x, vec2 y);
float dot (vec3 x, vec3 y);
float dot (vec4 x, vec4 y);

用户定义的函数可以有多个声明,但只有一个定义。

函数main用作着色器的入口点。 顶点着色器和片段着色器都必须包含名为main的函数。 此函数不带参数,不返回任何值,并且必须声明为void类型:

void main()
{
 ...
}

函数main可以包含return的用法。 更多详细信息,请参见第6.4节“跳转”。
使用任何其他签名声明名为main的函数是错误的

6.1.1 函数调用惯例

函数由value-return调用。 这意味着输入参数在调用时被复制到函数中,输出参数在函数退出之前被复制回调用者。 因为该函数适用于参数的本地副本,所以在函数中没有关于变量别名的问题。

要控制通过函数定义或声明复制和/或复制的参数:

  • 关键字in用作限定符,表示要复制进的参数,但不能复制出去。
  • 关键字out用作限定符,表示要复制出的参数,但不能复制进。这个应该尽可能的使用,以避免不必要地复制参数。
  • 关键字inout用作限定符,表示要复制进和复制出去的参数。
  • 声明没有以上的限定符的函数参数意味着与指定in相同

所有参数在调用时按顺序从左到右进行计算。对in参数只是复制其形式参数,而out参数则是在函数返回时将值赋值给它,而inout参数则是在调用时复制其作为形式参数的值进行计算,在函数返回时则将值赋值给它。

输出参数复制回调用方的顺序未定义。

在函数中,仅输入参数是允许被写入的。 只是函数的副本被修改了。 这个问题可以通过使用const限定符声明参数来防止。

调用函数时,不计算为左值的表达式不能传递给声明为outinout的参数。

如果函数未写入out参数,则函数返回时,实际参数的值表现为未定义的。

如果使用非void返回类型声明函数并且函数返回而不执行return语句,则返回的值是未定义的。

在函数的返回类型上只允许使用精度限定符来修饰

结构声明不允许作为参数声明或返回类型声明的一部分。

函数原型:

精度修饰符 类型 方法名(const修饰符 参数修饰符 精度修饰符 类型 名称 数组修饰符)

类型:

基础类型,结构名称,或结构定义

const修饰符:

const

参数修饰符:

in

out

inout

名称:

自定义

数组修饰符:

[数组长度]

但是,const限定符不能与out或inout一起使用。以上用于函数声明(即原型)和函数定义。 因此,函数定义可以具有未命名的参数(但是在实现方法的时候是需要有参数名的)。

不允许静态和动态递归,(很多底层芯片没有实现)。

OpenGL ES着色器语言规范 6.1 函数定义
Android,OpenGL ES,图形学