简介
GLSL
(OpenGL Shading Language) 全称 OpenGL 着色语言,是用来在 OpenGL 中着色编程的语言,也即开发人员写的短小的自定义程序,他们是在图形卡的 GPU上执行的,代替了固定的渲染管线的一部分,使渲染管线中不同层次具有可编程性。 GLSL
其使用 C 语言作为基础高阶着色语言,避免了使用汇编语言或硬件规格语言的复杂性。
基础语法
注释
单行注释:// 多行注释:/* */
变量命名
GLSL的变量命名方式与C语言类似。变量的名称可以使用字母,数字以及下划线,但变量名不能以数字开头,还有变量名不能以gl_作为前缀,这个是GLSL保留的前缀,用于GLSL的内部变量。当然还有一些GLSL保留的名称是不能够作为变量的名称的。
变量命名
GLSL
的变量命名方式与 C 语言类似,可使用字母,数字以及下划线,不能以数字开头。还需要注意的是,变量名不能以 gl_
作为前缀,这个是 GLSL
保留的前缀,用于 GLSL
的内部变量。
表达式
运算符
优先级(越小越高) | 运算符 | 说明 | 结合性 |
---|---|---|---|
1 | () | 聚组:a*(b+c) | N/A |
2 | [] () . ++ -- | 数组下标__[],方法参数__fun(arg1,arg2,arg3),属性访问a.b,自增/减后缀a++ a-- | L - R |
3 | ++ -- + - ! | 自增/减前缀++a --a,正负号(一般正号不写)a ,-a,取反!false | R - L |
4 | * / | 乘除数学运算 | L - R |
5 | + - | 加减数学运算 | L - R |
7 | < > <= >= | 关系运算符 | L - R |
8 | == != | 相等性运算符 | L - R |
12 | && | 逻辑与 | L - R |
13 | ^^ | 逻辑排他或(用处基本等于!=) | L - R |
14 | II | 逻辑或 | L - R |
15 | ? : | 三目运算符 | L - R |
16 | = += -= *= /= | 赋值与复合赋值 | L - R |
17 | , | 顺序分配运算 | L - R |
左值与右值:
1 | 左值:表示一个储存位置,可以是变量,也可以是表达式,但表达式最后的结果必须是一个储存位置. |
操作符
GLSL语言的操作符与C语言相似。如下表(操作符的优先级从高到低排列)
操作符 | 描述 |
---|---|
() | 用于表达式组合,函数调用,构造 |
[] | 数组下标,向量或矩阵的选择器 |
. | 结构体和向量的成员选择 |
++ -- | 前缀或后缀的自增自减操作符 |
+ – ! | 一元操作符,表示正 负 逻辑非 |
* / | 乘 除操作符 |
+ - | 二元操作符 表示加 减操作 |
<> <= >= == != | 小于,大于,小于等于, 大于等于,等于,不等于 判断符 |
&& || ^^ | 逻辑与 ,或, 异或 |
?: | 条件判断符 |
= += –= *= /= | 赋值操作符 |
, | 表示序列 |
求地址的& 和 解引用的 * 操作符不再GLSL中出现,因为GLSL不能直接操作地址。
类型转换操作也是不允许的。
位操作符(&,|,^,~, <<, >> ,&=, |=, ^=, <<=, >>=)是GLSL保留的操作符,将来可能会被使用。
求模操作(%,%=)也是保留的。
数组访问
数组的下标从0开始。合理的范围是[0, size - 1]。跟C语言一样。如果数组访问越界了,那行为是未定义的。如果着色器的编译器在编译时知道数组访问越界了,就会提示编译失败。
1 | vec4 myColor, ambient, diffuse[6], specular[6]; |
语句
流控制
glsl的流控制和c语言非常相似,这里不必再做过多说明,唯一不同的是片段着色器中有一种特殊的控制流discard
. 使用discard会退出片段着色器,不执行后面的片段着色操作。片段也不会写入帧缓冲区。
1 | for (l = 0; l < numLights; l++) |
discard
片段着色器中有一种特殊的控制流成为discard。使用discard会退出片段着色器,不执行后面的片段着色操作。片段也不会写入帧缓冲区。
1 | if (ture) |
分量访问
分量访问符 | 符号描述 |
---|---|
(x,y,z,w) | 与位置相关的分量 |
(r,g,b,a) | 与颜色相关的分量 |
(s,t,p,q) | 与纹理坐标相关的分量 |
GLSL函数
glsl允许在程序的最外部声明函数.函数不能嵌套,不能递归调用,且必须声明返回值类型(无返回值时声明为void) 在其他方面glsl函数与c函数非常类似.
1 | vec4 getPosition(){ |
GLSL预编译指令
以 # 开头的是预编译指令,常用的有:
1 | #define #undef #if #ifdef #ifndef #else |
比如 #version 100 他的意思是规定当前shader使用 GLSL ES 1.00标准进行编译,如果使用这条预编译指令,则他必须出现在程序的最开始位置.
内置的宏:
__LINE__
: 当前源码中的行号.
__VERSION__
: 一个整数,指示当前的glsl版本 比如 100 ps: 100 = v1.00
GL_ES
: 如果当前是在 OPGL ES 环境中运行则 GL_ES 被设置成1,一般用来检查当前环境是不是 OPENGL ES.
GL_FRAGMENT_PRECISION_HIGH
: 如果当前系统glsl的片元着色器支持高浮点精度,则设置为1.一般用于检查着色器精度.
实例:
1.如何通过判断系统环境,来选择合适的精度:
1 | #ifdef GL_ES // |
2.自定义宏:
1 | #define NUM 100 |
数据类型
基础数据类型
类型 | 描述 |
---|---|
void | 跟 C 语言的 void 类似,表示空类型。作为函数的返回类型,表示这个函数不返回值。 |
bool | 布尔类型,true 或 false,以及可以产生布尔型的表达式。 |
int | 有符号整型 |
uint | 无符号整形 |
float | 浮点型 |
纹理采样类型
类型 | 描述 |
---|---|
sampler1D | 用于内建的纹理函数中引用指定的 1D纹理的句柄。只可以作为一致变量或者函数参数使用 |
sampler2D | 二维纹理句柄 |
sampler3D | 三维纹理句柄 |
samplerCube | cube map 纹理句柄 |
sampler1DShadow | 一维深度纹理句柄 |
sampler2DShadow | 二维深度纹理句柄 |
聚合类型(向量和矩阵类型)
向量类型
类型 | 描述 |
---|---|
vec2,vec3,vec4 | 2分量、3分量和4分量浮点向量 |
ivec2,ivec3,ivec4 | 2分量、3分量和4分量整数向量 |
uvec2,uvec3,uvec4 | 2分量、3分量和4分量无符号整数向量 |
bvec2,vbec3,bvec4 | 2分量、3分量和4分量布尔向量 |
A、向量声明--4分量的float 类型向量
1 | vec4 V1; |
B、声明向量并对其进行构造
1 | vec4 V2 = vec4(1,2,3,4); |
C、向量运算
1 | vec4 v; |
D、向量元素的获取(成分选择)
向量中单独的成分可以通过 {x,y,z,w}, {r,g,b,a} 或者 {s,t,p,q} 的记法来表示。这些不同的记法用于 顶点,颜色,纹理坐标。在成分选择中,你不可以混合使用这些记法。其中 {s,t,p,q} 中的 p 替换了纹理的 r 坐标,因为与颜色 r 重复了。下面是用法举例: 例如有向量 v1 和 v2:
1 | vec3 v1 = {0.5, 0.35, 0.7}; |
可以通过 {x,y,z,w}, {r,g,b,a} 或者 {s,t,p,q} 来取出向量中的元素值。 通过 x,y,z,w:
1 | v2.x = 3.0f; |
通过 r,g,b,a:
1 | v2.r = 3.0f; |
通过 s,t,q,r:
1 | v2.stqr = vec2(1.0f, 0.0f, 0.0f, 1.0f); |
错误示例:
1 | float myQ = v1.q;// 出错,数组越界访问,q代表第四个元素 |
向量还支持一次性对所有分量操作
1
2
3
4
v1.x = v2.x +5.0f;
v1.y = v2.y +4.0f;
v1.z = v2.z +3.0f;
v1.xyz = v2.xyz + vec3(5.0f,4.0f,3.0f);
1 | v1.x = v2.x +5.0f; |
(2)矩阵类型
类型 | 描述 |
---|---|
mat2 或 mat2x2 | 2x2的浮点数矩阵类型 |
mat3 或 mat3x3 | 3x3的浮点数矩阵类型 |
mat4 或 mat4x4 | 4x4的浮点数矩阵类型 |
mat2x3 | 2列3行的浮点矩阵(OpenGL的矩阵是列主顺序的) |
mat2x4 | 2列4行的浮点矩阵 |
mat3x2 | 3列2行的浮点矩阵 |
mat3x4 | 3列4行的浮点矩阵 |
mat4x2 | 4列2行的浮点矩阵 |
mat4x3 | 4列3行的浮点矩阵 |
创建矩阵:
1 | mat4 m1,m2,m3; |
构造单元矩阵:
1 | mat4 m2 = mat4(1.0f,0.0f,0.0f,0.0f |
或者
1 | mat4 m4 = mat4(1.0f); |
向量矩阵运算
1、不同类型 float 与 int 间的运算:**
float 与 int 之间进行运算,需要进行一次显示转换,以下表达式都是正确的:
1
2
3
4
5
6
int a = int(2.0);
float a = float(2);
int a = int(2.0)*2 + 1;
float a = float(2)*6.0+2.3;
复制代码
1 | int a = int(2.0); |
2、float 与 vec(向量)、mat(矩阵) 的运算:
- 逐分量运算 vec,mat 这些类型其实是由 float 复合而成的,当它们与float 运算时,其实就是在每一个分量上分别与 float 进行运算,这就是所谓的 逐分量运算。GLSL 里,大部分涉及 vec,mat 的运算都是逐分量运算,但也并不全是。下文中就会讲到特例。 逐分量运算 是线性的,这就是说 vec 与 float 的运算结果是还是 vec。
int 与 vec,mat 之间是不可运算的,因为 vec 和 mat 中的每一个分量都是 float 类型的,无法与 int 进行逐分量计算。
下面枚举了几种 float 与 vec,mat 运算的情况:
1 | vec3 a = vec3(1.0, 2.0, 3.0); |
3、vec(向量) 与 vec(向量)运算:
两向量间的运算首先要保证操作数的阶数都相同,否则不能计算。例如: vec3\*vec2
和 vec4+vec3
等等都是不行的。
它们的计算方式是两操作数在同位置上的分量分别进行运算,其本质还是逐分量进行的,这和上面所说的 float 类型的逐分量运算可能有一点点差异,相同的是 vec 与 vec 运算结果还是 vec,且阶数不变。
1 | vec3 a = vec3(1.0, 2.0, 3.0); |
AB=[a1,1a1,2a2,1a2,2][b1,1b1,2b2,1b2,2]=[a1,1b1,1+a1,2b2,1a1,1b1,2+a1,2b2,2a2,1b1,1+a2,2b2,1a2,1b1,2+a2,2b2,2]
4、vec(向量) 与 mat(矩阵):
要保证操作数的阶数相同,且 vec 与 mat 间只存在乘法运算。 它们的计算方式和线性代数中的矩阵乘法相同,不是逐分量运算。
1 | vec2 v = vec2(10., 20.); |
5、mat(矩阵) 与 mat(矩阵):
要保证操作数的阶数相同。
在 mat 与 mat 的运算中,除了乘法是线性代数中的矩阵乘法外,其余的运算仍为逐分量运算。简单说就是只有乘法是特殊的,其余都和 vec 与 vec 运算类似。
1 | mat2 a = mat2(1., 2., 3., 4.); |
结构体
结构体可以组合基本类型和数组来形成用户自定义的类型。在定义一个结构体的同时,你可以定义一个结构体实例。或者后面再定义。
1 | struct fogStruct { |
可以通过 = 为结构体赋值,或者使用 ==,!= 来判断两个结构体是否相等。
1 | fogVar = fogStruct(vec4(1.0,0.0,0.0,1.0),0.5,2.0); |
构造函数
glsl中变量可以在声明的时候初始化,float pSize = 10.0
也可以先声明然后等需要的时候在进行赋值.
聚合类型对象如(向量,矩阵,数组,结构) 需要使用其构造函数来进行初始化. vec4 color = vec4(0.0, 1.0, 0.0, 1.0);
1 | //一般类型 |
数组
GLSL
中只可以使用一维的数组。数组的类型可以是一切基本类型或者结构体。下面的几种数组声明是合法的:
1 | float floatArray[4]; |
数组类型内建了一个length()
函数,可以返回数组的长度。
1 | lightPositions.length() // 返回数组的长度 |
类型转换
glsl可以使用构造函数进行显式类型转换,各值如下:
1 | bool t= true; |
glsl中,没有隐式类型转换,原则上glsl要求任何表达式左右两侧(l-value),(r-value)的类型必须一致 也就是说以下表达式都是错误的:
1
2
3
4
5
6
int a =2.0; //错误,r-value为float 而 lvalue 为int.
int a =1.0+2;
float a =2;
float a =2.0+1;
bool a = 0;
vec3 a = vec3(1.0, 2.0, 3.0) * 2;
1 | int a =2.0; //错误,r-value为float 而 lvalue 为int. |
精度限定
glsl在进行光栅化着色的时候,会产生大量的浮点数运算,这些运算可能是当前设备所不能承受的,所以glsl提供了3种浮点数精度,我们可以根据不同的设备来使用合适的精度.
在变量前面加上 highp
mediump
lowp
即可完成对该变量的精度声明.
1 | lowp float color; |
我们一般在片元着色器(fragment shader)最开始的地方加上 precision mediump float;
便设定了默认的精度.这样所有没有显式表明精度的变量 都会按照设定好的默认精度来处理.
如何确定精度:
变量的精度首先是由精度限定符决定的,如果没有精度限定符,则要寻找其右侧表达式中,已经确定精度的变量,一旦找到,那么整个表达式都将在该精度下运行.如果找到多个, 则选择精度较高的那种,如果一个都找不到,则使用默认或更大的精度类型.
1 | uniform highp float h1; |
invariant关键字:
由于shader在编译时会进行一些内部优化,可能会导致同样的运算在不同shader里结果不一定精确相等.这会引起一些问题,尤其是vertx shader向fragmeng shader传值的时候. 所以我们需要使用invariant
关键字来显式要求计算结果必须精确一致. 当然我们也可使用 #pragma STDGL invariant(all)
来命令所有输出变量必须精确一致, 但这样会限制编译器优化程度,降低性能.
1 | #pragma STDGL invariant(all) //所有输出变量为 invariant |
限定符的顺序:
当需要用到多个限定符的时候要遵循以下顺序:
1.在一般变量中: invariant > storage > precision
2.在参数中: storage > parameter > precision
我们来举例说明:
1 | invariant varying lowp float color; // invariant > storage > precision |
修饰符
1、变量存储限定符
限定符 | 描述 |
---|---|
(默认的可省略)只是普通的本地变量,可读可写,外部不可见,外部不可访问 | |
const | 常量值必须在声明时初始化,它是只读的不可修改的 |
varying | 顶点着色器的输出,主要负责在 vertex 和 fragment 之间传递变量。例如颜色或者纹理坐标,(插值后的数据)作为片段着色器的只读输入数据。必须是全局范围声明的全局变量。可以是浮点数类型的标量,向量,矩阵。不能是数组或者结构体。 |
uniform | 一致变量。在着色器执行期间一致变量的值是不变的。与 const 常量不同的是,这个值在编译时期是未知的是由着色器外部初始化的。一致变量在顶点着色器和片段着色器之间是共享的。它也只能在全局范围进行声明。 |
attribute | 表示只读的顶点数据,只用在顶点着色器中。数据来自当前的顶点状态或者顶点数组。它必须是全局范围声明的,不能再函数内部。一个 attribute 可以是浮点数类型的标量,向量,或者矩阵。不可以是数组或则结构体 |
centorid varying | 在没有多重采样的情况下,与 varying 是一样的意思。在多重采样时,centorid varying 在光栅化的图形内部进行求值而不是在片段中心的固定位置求值。 |
invariant | (不变量)用于表示顶点着色器的输出和任何匹配片段着色器的输入,在不同的着色器中计算产生的值必须是一致的。所有的数据流和控制流,写入一个 invariant 变量的是一致的。编译器为了保证结果是完全一致的,需要放弃那些可能会导致不一致值的潜在的优化。除非必要,不要使用这个修饰符。在多通道渲染中避免 z-fighting 可能会使用到。 |
2、函数参数限定符
GLSL
允许自定义函数,但参数默认是以值形式(in
限定符)传入的,也就是说任何变量在传入时都会被拷贝一份,若想以引用方式传参,需要增加函数参数限定符。
限定符 | 描述 |
---|---|
in | 用在函数的参数中,表示这个参数是输入的,在函数中改变这个值,并不会影响对调用的函数产生副作用。(相当于C语言的传值),这个是函数参数默认的修饰符 |
out | 用在函数的参数中,表示该参数是输出参数,值是会改变的。 |
inout | 用在函数的参数,表示这个参数即是输入参数也是输出参数。 |
其中使用 inout 方式传递的参数便与其他 OOP 语言中的引用传递类似,参数可读写,函数内对参数的修改会影响到传入参数本身。 eg:
1 | vec4 getPosition(out vec4 p){ |
内置变量和函数
内置变量
内置变量可以与固定函数功能进行交互。在使用前不需要声明。
顶点着色器可用的内置变量
名称 | 类型 | 描述 |
---|---|---|
gl_Color | vec4 | 输入属性-表示顶点的主颜色 |
gl_SecondaryColor | vec4 | 输入属性-表示顶点的辅助颜色 |
gl_Normal | vec3 | 输入属性-表示顶点的法线值 |
gl_Vertex | vec4 | 输入属性-表示物体空间的顶点位置 |
gl_MultiTexCoordn | vec4 | 输入属性-表示顶点的第n个纹理的坐标 |
gl_FogCoord | float | 输入属性-表示顶点的雾坐标 |
gl_Position | vec4 | 输出属性-变换后的顶点的位置,用于后面的固定的裁剪等操作。所有的顶点着色器都必须写这个值。 |
gl_ClipVertex | vec4 | 输出坐标,用于用户裁剪平面的裁剪 |
gl_PointSize | float | 点的大小 |
gl_FrontColor | vec4 | 正面的主颜色的varying输出 |
gl_BackColor | vec4 | 背面主颜色的varying输出 |
gl_FrontSecondaryColor | vec4 | 正面的辅助颜色的varying输出 |
gl_BackSecondaryColor | vec4 | 背面的辅助颜色的varying输出 |
gl_TexCoord[] | vec4 | 纹理坐标的数组varying输出 |
gl_FogFragCoord | float | 雾坐标的varying输出 |
片段着色器的内置变量
名称 | 类型 | 描述 |
---|---|---|
gl_Color | vec4 | 包含主颜色的插值只读输入 |
gl_SecondaryColor | vec4 | 包含辅助颜色的插值只读输入 |
gl_TexCoord[] | vec4 | 包含纹理坐标数组的插值只读输入 |
gl_FogFragCoord | float | 包含雾坐标的插值只读输入 |
gl_FragCoord | vec4 | 只读输入,窗口的x,y,z和1/w |
gl_FrontFacing | bool | 只读输入,如果是窗口正面图元的一部分,则这个值为true |
gl_PointCoord | vec2 | 点精灵的二维空间坐标范围在(0.0, 0.0)到(1.0, 1.0)之间,仅用于点图元和点精灵开启的情况下。 |
gl_FragData[] | vec4 | 使用glDrawBuffers输出的数据数组。不能与gl_FragColor结合使用。 |
gl_FragColor | vec4 | 输出的颜色用于随后的像素操作 |
gl_FragDepth | float | 输出的深度用于随后的像素操作,如果这个值没有被写,则使用固定功能管线的深度值代替 |
内置函数
glsl提供了非常丰富的函数库,供我们使用,这些功能都是非常有用且会经常用到的. 这些函数按功能区分大改可以分成7类:
通用函数:
下文中的 类型 T可以是 float, vec2, vec3, vec4,且可以逐分量操作.
方法 | 说明 |
---|---|
T abs(T x) | 返回x的绝对值 |
T sign(T x) | 比较x与0的值,大于,等于,小于 分别返回 1.0 ,0.0,-1.0 |
T floor(T x) | 返回<=x的最大整数 |
T ceil(T x) | 返回>=等于x的最小整数 |
T fract(T x) | 获取x的小数部分 |
T mod(T x, T y) T mod(T x, float y) | 取x,y的余数 |
T min(T x, T y) T min(T x, float y) | 取x,y的最小值 |
T max(T x, T y) T max(T x, float y) | 取x,y的最大值 |
T clamp(T x, T minVal, T maxVal) T clamp(T x, float minVal,float maxVal) | min(max(x, minVal), maxVal),返回值被限定在 minVal,maxVal之间 |
T mix(T x, T y, T a) T mix(T x, T y, float a) | 取x,y的线性混合,x(1-a)+ya |
T step(T edge, T x) T step(float edge, T x) | 如果 x<edge 返回 0.0 否则返回1.0 |
T smoothstep(T edge0, T edge1, T x) T smoothstep(float edge0,float edge1, T x) | 如果x<edge0 返回 0.0 如果x>edge1返回1.0, 否则返回Hermite插值 |
角度&三角函数:
下文中的 类型 T可以是 float, vec2, vec3, vec4,且可以逐分量操作.
方法 | 说明 |
---|---|
T radians(T degrees) | 角度转弧度 |
T degrees(T radians) | 弧度转角度 |
T sin(T angle) | 正弦函数,角度是弧度 |
T cos(T angle) | 余弦函数,角度是弧度 |
T tan(T angle) | 正切函数,角度是弧度 |
T asin(T x) | 反正弦函数,返回值是弧度 |
T acos(T x) | 反余弦函数,返回值是弧度 |
T atan(T y, T x) T atan(T y_over_x) | 反正切函数,返回值是弧度 |
指数函数:
下文中的 类型 T可以是 float, vec2, vec3, vec4,且可以逐分量操作.
方法 | 说明 |
---|---|
T pow(T x, T y) | 返回x的y次幂 xy |
T exp(T x) | 返回x的自然指数幂 ex |
T log(T x) | 返回x的自然对数 ln |
T exp2(T x) | 返回2的x次幂 2x |
T log2(T x) | 返回2为底的对数 log2 |
T sqrt(T x) | 开根号 √x |
T inversesqrt(T x) | 先开根号,在取倒数,就是 1/√x |
几何函数:
下文中的 类型 T可以是 float, vec2, vec3, vec4,且可以逐分量操作.
方法 | 说明 |
---|---|
float length(T x) | 返回矢量x的长度 |
float distance(T p0, T p1) | 返回p0 p1两点的距离 |
float dot(T x, T y) | 返回x y的点积 |
vec3 cross(vec3 x, vec3 y) | 返回x y的叉积 |
T normalize(T x) | 对x进行归一化,保持向量方向不变但长度变为1 |
T faceforward(T N, T I, T Nref) | 根据 矢量 N 与Nref 调整法向量 |
T reflect(T I, T N) | 返回 I - 2 * dot(N,I) * N, 结果是入射矢量 I 关于法向量N的 镜面反射矢量 |
T refract(T I, T N, float eta) | 返回入射矢量I关于法向量N的折射矢量,折射率为eta |
矩阵函数:
mat可以为任意类型矩阵.
方法 | 说明 |
---|---|
mat matrixCompMult(mat x, mat y) | 将矩阵 x 和 y的元素逐分量相乘 |
向量函数:
下文中的 类型 T可以是 vec2, vec3, vec4, 且可以逐分量操作.
bvec指的是由bool类型组成的一个向量:
1 | vec3 v3= vec3(0.,0.,0.); |
方法 | 说明 |
---|---|
bvec lessThan(T x, T y) | 逐分量比较x < y,将结果写入bvec对应位置 |
bvec lessThanEqual(T x, T y) | 逐分量比较 x <= y,将结果写入bvec对应位置 |
bvec greaterThan(T x, T y) | 逐分量比较 x > y,将结果写入bvec对应位置 |
bvec greaterThanEqual(T x, T y) | 逐分量比较 x >= y,将结果写入bvec对应位置 |
bvec equal(T x, T y) bvec equal(bvec x, bvec y) | 逐分量比较 x == y,将结果写入bvec对应位置 |
bvec notEqual(T x, T y) bvec notEqual(bvec x, bvec y) | 逐分量比较 x!= y,将结果写入bvec对应位置 |
bool any(bvec x) | 如果x的任意一个分量是true,则结果为true |
bool all(bvec x) | 如果x的所有分量是true,则结果为true |
bvec not(bvec x) | bool矢量的逐分量取反 |
纹理查询函数:
图像纹理有两种 一种是平面2d纹理,另一种是盒纹理,针对不同的纹理类型有不同访问方法.
纹理查询的最终目的是从sampler中提取指定坐标的颜色信息. 函数中带有Cube字样的是指 需要传入盒状纹理. 带有Proj字样的是指带投影的版本.
以下函数只在vertex shader中可用:
1 | vec4 texture2DLod(sampler2D sampler, vec2 coord, float lod); |
以下函数只在fragment shader中可用:
1 | vec4 texture2D(sampler2D sampler, vec2 coord, float bias); |
在 vertex shader 与 fragment shader 中都可用:
1 | vec4 texture2D(sampler2D sampler, vec2 coord); |
相关链接
https://www.khronos.org/registry/OpenGL/specs/gl/GLSLangSpec.1.20.pdf
https://www.khronos.org/registry/OpenGL-Refpages/gl4/
[3、作者吃代码的兔子窝的《初探 GLSL 着色器(二)》](