OpenGL之GLSL

GLSL是OpenGL Shader的编程语言,为了更好的进行视频编辑和特效开发,抽空学习了其语法和特性,并作此记录,留做备忘查询。编程

类型

类型概述

变量类别 变量类型 备注
void 用于标识无参函数或者无返回值函数:void main(void);
标量 bool/int/float 布尔类型、整型、浮点型
布尔型向量 bvec2/bvec3/bvec4 其中b表示向量类型,数字表示向量的份量数
整型向量 ivec2/ivec3/ivec4 其中i表示向量类型,数字表示向量的份量数
浮点型向量 vec2/vec3/vec4 默认状况下是float类型,数字表示向量的份量数
浮点型矩阵 mat2/mat3/mat4 数字表示矩阵的列数,行数和列数相同
2D texture sampler2D 2D纹理,仅能做为uniform变量
Cubemap(立方体) texture samplerCube 立方体纹理,仅能做为uniform变量
结构体 struct 相似于C语言结构体,把多个变量聚合在一块儿
数组 array GLSL只支持1维数组,数据类型能够是标量类型、向量类型、矩阵类型、结构体类型

向量构造器有两种参数构造方式:数组

  1. 单标量参数:向量中的全部份量都会初始化为该标量值。
  2. 多标量参数、向量参数、或者标量和向量混合参数:按照参数顺序初始化向量的全部份量,须要保证参数个数(向量参数的份量拆分开)很多于向量份量个数。
vec4 aVec4 = vec4(1.0, 1.0, 1.0, 1.0);
// 所有份量都为1.0
vec4 bVec4 = vec4(1.0);

vec3 aVec3 = vec3(1.0);
// 经过向量和标量初始化4维向量
vec4 cVec4 = vec4(aVec3, 1.0);
复制代码

类型转换:GLSL不支持隐式类型转换,必须进行显示类型转换,向量也支持直接类型转换。即只有类型一致时,变量才能完成赋值或其它操做。less

float floatParam = 1.0;
// float -> bool
bool boolParam = bool(floatParam);

vec4 fVec4 = vec4(1.0, 1.0, 1.0, 1.0);
// 4维float向量 -> 4维int向量
ivec4 iVec4 = ivec4(fVec4);
// 4维float向量 -> 3维int向量
ivec3 iVec3 = ivec3(fVec4);
复制代码

矩阵构造器也有两种参数构造方式:编程语言

  1. 单标量参数:用于主对角线上份量的初始化,其余份量皆为0.0。
  2. 多标量参数、向量参数、或者标量和向量混合参数:按照参数顺序初始化矩阵的全部份量(列优先),须要保证参数个数(向量参数的份量拆分开)很多于矩阵份量个数。
// 经过多个标量为矩阵的各个份量赋值
mat3 aMat3 = mat3(1.0, 0.0, 0.0,  // 第一列
                  0.0, 1.0, 0.0,  // 第二列
                  0.0, 0.0, 1.0); // 第三列
// 单个标量用于主对角线上份量的初始化,其余份量皆为0.0 
mat3 bMat3 = mat3(1.0);

vec3 aVec3 = vec3(1.0,0.0,0.0);
vec3 bVec3 = vec3(0.0,1.0,0.0);
mat3 cMat3 = mat3(aVec3,  // 经过向量初始化第一列
                  bVec3,  // 经过向量初始化第二列
                  0.0, 0.0, 1.0); // 经过多个标量初始化第三列
复制代码

向量和矩阵操做

向量和矩阵都是由份量构成的,咱们能够经过多种方式访问份量。 针对向量,能够经过.和数组下标访问,也能够经过xyzwrgba或者strq来访问,其中,xyzw一般用于位置相关向量,rgba一般用于颜色相关向量,strq一般用于纹理坐标相关向量。xrs分别表示向量的第一个份量。上述三种方式不能混用,好比:xgr是不容许的。ide

针对矩阵,能够认为是向量的组合,一个mat3能够当作三个vec3,因此能够经过数组下标获取某一列的向量,而后再经过上述方法访问向量份量。函数

// 向量访问
vec3 aVec3 = vec3(0.0, 1.0, 2.0); 
vec3 temp;
temp = aVec3.xyz; // temp = {0.0, 1.0, 2.0}
temp = aVec3.xxx; // temp = {0.0, 0.0, 0.0}
temp = aVec3.zyx; // temp = {2.0, 1.0, 0.0}

// 矩阵访问
mat4 aMat4 = mat4(1.0); 
vec4 column0 = aMat4[0];	        // column0 = {1.0, 0.0, 0.0,0.0}
float column1_row1 = aMat4[1][1];   // column1_row1 = 1.0
float column2_row2 = myMat4[2].z;   // column2_row2 = 1.0
复制代码

结构体

与C语言相似,glsl支持定义结构体,同时会自动为结构体建立构造器(与结构体同名),用于生成结构体实例。学习

// Leon是新的结构体类型,leon是结构体变量,是可选的。
struct Leon {
    vec4 aVec4; 
    mat4 bMat4;
    float cF;
} leon;
// 经过结构体构造器初始化结构体参数,构造器的参数和结构体的元素必须有精确的对应关系 
leon = Leon(vec4(1.0),mat4(1.0),1.0); 
// 经过.操做符访问成员变量
vec4 dVec4 = leon.aVec4;
mat4 eMat4 = leon.bMat4;
复制代码

数组

与C语言相似,glsl支持定义数组,数组类型能够是任意基本类型和结构体类型。glsl有两点特殊之处:测试

  1. 除了uniform变量以外,数组的索引必须是编译期常量。
  2. 数组的定义和初始化是分开的,即数组中的元素必须在数组定义以后逐个初始化,且数组不能使用const限定符。
// 定义数组
float fArray[2];
vec2 vec2Array[2];
mat2 mat2Array[2];
Leon leonArray[2];

// 数组元素必须逐一被初始化 
fArray[0] = 0.0;
fArray[1] = 1.0;
    
vec2Array[0] = vec2(0.0);
vec2Array[1] = vec2(1.0);
    
mat2Array[0] = mat2(0.0);
mat2Array[1] = mat2(1.0);
    
leonArray[0] = Leon(vec4(1.0),mat4(1.0),1.0);
leonArray[1] = Leon(vec4(1.0),mat4(1.0),1.0);
复制代码

语句

流程控制语句

流程控制语句与C语言很是类似。ui

循环语句

GLSL支持经过continue跳过单次循环,break退出整个循环。spa

// 经过计数器控制的循环
for(int i = 0; i <= 99; i++) {
    function(); 
}

// 经过前置(循环)条件控制的循环
int i = 0;
while(i <= 99) { 
    function();
    i++;
}

// 经过后置(循环)条件控制的循环
do { 
    function();  
    i++;
} while(i <= 99);
复制代码

条件语句

与C语言相似

if(condition){
    functionA();
} else {
    functionB();
}
复制代码

discard语句

discard关键字通常用于片元着色器中,用于丢弃当前片元,即:当即退出当前片元的着色程序,当前片元最终是默认色。

Start语句

// main函数是顶点和片元着色器入口,至关于C语言的主函数
void main(void) {
    function();  
}
复制代码

运算符

GLSL运算符与C语言相似,此处再也不赘述,只说不一样点:

  • GLSL要求运算符两侧的变量必须具备相同的数据类型。
  • 对于二目运算符(*,/,+,-),操做数必须为浮点型或者整型。
  • 比较运算符只能用于标量,有专门的内置函数用于向量比较,后续内置函数会介绍。

限定符

存储限定符

声明变量时,可使用存储限定符进行修饰,相似C语言中的说明符。

const

const用于修饰编译时常量(声明时必须赋初值),或者只读的函数参数。结构体成员不能被声明为常量,可是结构体变量能够被声明为常量,而且须要在初始化时使用构造器初始化其值。

attribute

attribute变量是应用程序传输给顶点着色器的逐顶点数据,即每一个顶点都须要一份数据,一般用于表示顶点坐标、顶点颜色、纹理坐标等数据。attribute变量在shader中是只读的,不能在顶点着色器中进行修改。此外,attribute变量必须由执行着色器的应用程序传输数据进行赋值。

可以使用的最大attribute数量是有上限的,可使用内置函数glGetIntegerv来查询GL_MAX_VERTEX_ATTRIBS。OpenGL ES 2.0至少支持8个attribute变量。

uniform

uniform可用在顶点和片元着色器中,用于修饰全局变量,即它们不限于某个顶点或者某个像素。一般用于表示变换矩阵、纹理等数据。uniform变量在shader中是只读的,不能在着色器中进行修改。此外,uniform变量必须由执行着色器的应用程序传输数据进行赋值。

着色器可使用的uniform个数是有限的,可使用内置函数glGetIntegerv来查询GL_MAX_VERTEX_UNIFORM_VECTORSGL_MAX_FRAGMENT_UNIFORM_VECTORS。OpenGL ES 2.0至少支持128个顶点uniform以及16个片元uniform。

varying

varying用于声明顶点着色器和片元着色器之间共享的变量。在顶点和片元着色器中,必须有相同的varying变量声明。首先,顶点着色器为每一个顶点的varying变量赋值,而后光栅化阶段会对varying变量进行插值计算(光栅化后的每一个片元都会获得一个对应的varying变量值),最后把插值结果交给片元着色器进行着色。varying只能用于修饰浮点标量、浮点向量、浮点矩阵以及包含这些类型的数组。

varying数量也存在限制,可使用glGetIntegerv来查询GL_MAX_VARYING_VECTORS。OpenGL ES 2.0至少支持8个varying变量。

本地变量和函数参数只能使用const限定符,函数返回值和结构体成员不能使用限定符。 attributeuniform变量不能在初始化时赋值,这些变量必须由应用程序主动进行赋值。

参数限定符

GLSL提供了参数限定符用于修饰函数参数,表示参数是否可读写。

in(只读参数)

in是默认修饰符,表示参数是值传递,而且在函数内不能修改该值。

out(只写参数)

out表示参数是引用传递,可是参数没有被初始化,因此在函数内不可读,只可写,而且函数结束后,修改依然生效。

inout(可读写参数)

inout表示参数是引用传递,在函数内能够对参数进行读写。而且函数结束后,修改依然生效(相似于C++中的引用)。

int newFunction(in bvec4 aBvec4,   // read-only 
                out vec3 aVec3,    // write-only
                inout int aInt);   // read-write

复制代码

精度限定符

精度限定符明确指定了着色器变量使用的精度范围,包括:lowpmediumphighp三种精度。当使用低精度时,OpenGL ES能够更快速和低功耗地运行着色器,效率的提升得益于精度的舍弃,若是精度选择不合理,着色器运行的结果会出现失真。因此须要测试不一样的精度才能肯定最合适的配置。

精度限定符 描述
highp 最高精度
lowp 最低精度
mediump 中间精度,介于二者之间

精度限定符能够修饰整型或者浮点型标量、向量和矩阵。在顶点着色器中,精度限定符是可选的,假如没有指定限定符,那么默认使用最高精度。在片元着色器中,精度限定符是必须的,要么在定义变量时直接指定精度,要么指定类型的默认精度。

// 为类型指定精度,若定义float变量时,没有指定精度限定符,那么默认是highp精度
precision highp float;
precision mediump int;

// 为变量指定精度
highp vec4 position;
varying lowp vec4 color;
复制代码

在OpenGL ES中,精度的定义及范围取决于具体的实现,不是彻底一致。精度限定符指定了存储这些变量时,必须知足的最小范围和精度。具体实现可能会使用比要求更大的范围和精度,但绝对不会比要求少。

不一样着色器支持的不一样精度限定符的范围与精度可使下面的函数查询:

void GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision);
复制代码

其中,shadertype必须是VERTEX_SHADERFRAGMENT_SHADER;precisiontype必须是GL_LOW_FLOATGL_MEDIUM_FLOATGL_HIGH_FLOATGL_LOW_INTGL_MEDIUM_INTGL_HIGH_INT;range是指向长度为2的整数数组的指针,这两个整数表示数值范围:

range[0] = log2(|min|)
range[1] = log2(|max|)
复制代码

precision是指向整数的指针,该整数是对应的精度位数(用log2取对数值)。

当表达式中出现多种精度时,选择精度最高的那个;当一个精度都没找到时,则使用默认或最大精度。

限定符的顺序

当出现多种限定度时,须要遵循必定的顺序:

  • 通常变量:存储限定符 -> 精度限定符
  • 函数参数:存储限定符 -> 参数限定符 -> 精度限定符
// 变量
varying highp float color; // storage -> precision
void fun(const in lowp float size){ // storage -> parameter -> precision
}
复制代码

预处理

GLSL中的预处理指令与C语言相似,都是以#开头,每一个指令独占一行。常见的预处理指令以下所示:

// 定义和取消定义
#define
#undef
// 条件判断
#if
#ifdef
#ifndef
#else
#elif
#endif

#pragma
#extension
#version
#line
复制代码

#pragma表示编译指示,用来控制编译器行为。

#pragma debug(on)
#pragma debug(off)
复制代码

开发和调试时能够打开debug选项,以便获取更多的调试信息,默认为off。

#version指定使用哪一个GLSL版本编译着色器,必须写在编译单元的最前面,其前面只能有注释或空白,不能有其余字符。

#extension用来启用某些扩展功能,每一个显卡驱动厂商均可以定义本身的OpenGL扩展,如:GL_OES_EGL_image_external。启用扩展的命令以下所示:

// 为某个扩展设置行为
#extension extension_name: behavior
// 为全部扩展设置行为
#extension all : behavior
// 启用OES纹理
#extension GL_OES_EGL_image_external : require
复制代码

extension_name表示具体某个扩展,all表示编译器支持的全部扩展,behavior表示对扩展的具体操做,好比启用、禁用等,以下所示:

behavior 描述
require 启用某扩展,若是不支持,则报错,若是扩展参数为all,则必定会出错
enable 启用某扩展,若是不支持,则会警告,若是扩展参数为all,则必定会出错
warn 除非由于该扩展被其它处于启用状态的扩展所须要,不然使用该扩展时会发出警告,若是扩展参数为all,则必定会抛出警告
disable 禁用某扩展,若是使用该扩展则会抛出错误,若是扩展参数为all(默认设置),则不容许使用任何扩展

对于每个被支持的扩展,都有一个对应的宏定义,咱们能够用它来判断编译器是否支持该扩展。

#ifdef OES_extension_name
#extension OES_extension_name : enable
    
#else
    
#endif
复制代码

除此以外,还有一些预约义的系统变量:

__LINE__ 	// int类型,当前源码中的行号.
__FILE__ 	// int类型,当前Source String的惟一ID标识
__VERSION__ // int类型,当前的glsl版本,好比100(100 = v1.00)
GL_ES 		// 若是当前是在OpenGL ES环境,为1,不然为0
复制代码

内置变量

OpenGL着色语言包含一些内置变量,这里主要介绍顶点和片元着色器的内置变量。

顶点着色器内置变量

gl_Position

gl_Position是输出变量,用来保存顶点位置的齐次坐标。该值用做图元装配、裁剪以及其余固定管道操做。若是顶点着色器中没有对gl_Position赋值,那么在后续阶段它的值是不肯定的。gl_Position能够被写入屡次,后续步骤以最后一次写入值为准。

gl_PointSize

gl_PointSize是输出变量,是着色器用来控制被栅格化点的大小,以像素为单位。若是顶点着色器中没有对gl_PointSize赋值,那么在后续阶段它的值是不肯定的。

片元着色器内置变量

gl_FragColor

gl_FragColor是输出变量,定义了后续管线中片元的颜色值。gl_FragColor能够被写入屡次,后续步骤以最后一次写入值为准。若是执行了discard操做,则片元会被丢弃,gl_FragColor将再也不有意义。

gl_FragCoord

gl_FragCoord是只读变量,保存当前片元的窗口坐标(x, y, z, 1/w),该值是图元装配阶段对图元插值计算所得,z份量表示当前片元的深度值。

gl_FragDepth

gl_FragDepth是输出变量,用于改变片元的深度值(替代gl_FragCoord.z深度值)。若是在任何地方写入了它的值,那么务必在全部执行路径中都写入它的值,不然未写入的路径上它的值有可能不明确。

gl_FrontFacing

gl_FrontFacing是只读变量,若是片元属于面朝前的图元,那么它的值为true。该变量能够选取顶点着色器计算出的两个颜色之一以模拟双面光照。

gl_PointCoord

gl_PointCoord是只读变量,表示当前片元在点图元中的二维坐标,范围是0.0到1.0。若是当前图元不是点,那么gl_PointCoord读取的值将是不明确的。

函数

自定义函数

GLSL支持自定义函数,可是函数不能嵌套,不支持递归调用,必须声明函数返回值类型(无返回值时声明为void)。若是一个函数在定义前被调用,则须要先声明其函数原型。

vec4 getPosition(){ 
    vec4 v4 = vec4(0.,0.,0.,1.);
    return v4;
}
复制代码

内嵌函数

三角形函数

ParamType能够是floatvec2vec3vec4,参数类型和返回类型是一致的。

函数原型 描述
ParamType radians(ParamType degrees) 把角度转换为弧度
ParamType degrees(ParamType radians) 把弧度转换为角度
ParamType sin(ParamType radians) 以弧度为单位,计算正弦值
ParamType cos(ParamType radians) 以弧度为单位,计算余弦值
ParamType tan(ParamType radians) 以弧度为单位,计算正切值
ParamType asin(ParamType value) sin的反函数,计算给定值的弧度,value的绝对值 <= 1,返回的弧度范围是[-π/2,π/2]
ParamType acos(ParamType value) cos的反函数,计算给定值的弧度,value的绝对值 <= 1,返回的弧度范围是[0,π]
ParamType atan(ParamType y_over_x) tan的反函数,计算给定值的弧度,返回的弧度范围是[-π/2,π/2]
ParamType atan(ParamType y, ParamType x) tan的反函数,也能够称做atan2,返回一个正切值为y/x的弧度,x和y的符号用来肯定角在哪一个象限。返回的弧度范围是(−π,π)。若是x和y都为0,则结果是未定义的

指数函数

ParamType能够是floatvec2vec3vec4,参数类型和返回类型是一致的。

函数原型 描述
ParamType pow(ParamType x, ParamType y) 幂函数返回x的y次方
ParamType exp(ParamType x) exp函数返回常数e的x次方
ParamType exp2(ParamType x) exp2函数返回常数2的x次方
ParamType log(ParamType x) 以常数e为底x的对数函数
ParamType log2(ParamType x) 以常数2为底x的对数函数
ParamType sqrt(ParamType x) 返回X的平方根
ParamType inversesqrt(ParamType x) 返回x的平方根的倒数

通用函数

ParamType能够是floatvec2vec3vec4,参数类型和返回类型是一致的。

函数原型 描述
ParamType abs(ParamType x) 返回x的绝对值
ParamType sign(ParamType x) x为正时返回1.0,x为零时返回0.0,x为负时返回-1.0
ParamType floor(ParamType x) 返回小于或等于x的最大整数
ParamType ceil(ParamType x) 返回大于或等于x的最小值
ParamType fract(ParamType x) 返回x的小数部分,即: x - floor(x)。
ParamType mod(ParamType x, ParamType y) x – y * floor(x / y),若是x和y是整数,返回值是x除以y的余数
ParamType mod(ParamType x, float y) 上面mod的变体:y老是float,对于浮点向量,向量的每一个份量除以y
ParamType min(ParamType x, ParamType y) 返回两个参数的较小值。对于浮点向量,操做是按份量进行比较的
ParamType min(ParamType x, float y) 上面min的变体:y老是float,对于浮点向量,向量的每一个份量与y进行比较
ParamType max(ParamType x, ParamType y) 返回两个参数的较大值。对于浮点向量,操做是按份量进行比较的
ParamType max(ParamType x, float y) 上面max的变体:y老是float,对于浮点向量,向量的每一个份量与y进行比较
ParamType clamp(ParamType x, ParamType minVal, ParamType maxVal) 若是x大于minVal,小于maxVal,则返回x。若是x小于minVal,则返回minVal。若是x大于maxVal,则返回maxVal
ParamType clamp(ParamType x, float minVal, float maxVal) 上面clamp的变体,minVal和maxVal老是float,对于浮点向量,向量的每一个份量与minVal和maxVal进行比较
ParamType mix(ParamType x, ParamType y, ParamType a) 返回x和y的线性混合,即x * (1 - a) + y * a
ParamType mix(ParamType x, ParamType y, float a) 上面mix的变体,a老是float,对于浮点向量,向量的每一个份量与a计算
ParamType step(ParamType edge, ParamType x) 若是x比edge小,则返回0.0,不然返回1.0
ParamType step(float edge, ParamType x) 上面step的变体,edge老是float,对于浮点向量,向量的每一个份量与edge计算
ParamType smoothstep(ParamType edge0, ParamType edge1, ParamType x) 若是x小于edge0,则返回0.0;若是x大于edge1,则返回1.0。不然,返回值将使用Hermite多项式在0.0到1.0之间进行插值
ParamType smoothstep(float edge0, float edge1, ParamType x) 上面smoothstep的变体,edge0和edge1老是float,对于浮点向量,向量的每一个份量与edge0和edge1比较

几何函数

ParamType能够是floatvec2vec3vec4

函数原型 描述
float length(ParamType x) 返回向量长度,即各份量平方和的平方根,对于浮点标量则返回其绝对值
float distance(ParamType p0, ParamType p1) 返回两点之间的距离,两点的距离就是向量d(p0 - p1, 从p1开始,指向p0)的长度,对于浮点标量则返回其绝对值
float distance(ParamType p0, ParamType p1) 返回两点之间的距离,两点的距离就是向量d(p0 - p1, 从p1开始,指向p0)的长度,对于浮点标量则返回其绝对值
float dot(ParamType x, ParamType y) 返回两个向量的点积,即两个向量各个份量乘积的和,对于浮点标量则返回x和y的乘积
vec3 cross(vec3 x, vec3 y) 返回两个向量的叉乘向量,更为熟知的叫法是法向量,该向量垂直于x和y向量构成的平面,其长度等于x和y构成的平行四边形的面积。输入参数只能是三份量浮点向量
ParamType normalize(ParamType x) 返回向量x的单位向量,即x / \|x\|,对于浮点标量直接返回1.0
ParamType faceforward(ParamType N, ParamType I, ParamType Nref) 若是dot(Nref, I) < 0那么返回N向量,不然返回–N向量
ParamType reflect(ParamType I, ParamType N) I:the incident vector(入射向量), N:the normal vector of the reflecting surface(反射面的法向量),返回反射方向: I – 2 * dot(N,I) * N,N通常是单位向量
ParamType refract(ParamType I, ParamType N, float eta) I:the incident vector(入射向量), N:the normal vector of the refracting surface(折射面法向量),eta:折射率。返回入射向量I关于法向量N的折射向量,折射率为eta,I和N通常是单位向量

矩阵函数

不一样于传统的向量相乘,这里matrixCompMult返回一个向量,该向量的各份量等于x和y向量各个份量的乘积。

mat2 matrixCompMult(mat2 x, mat2 y)  
mat3 matrixCompMult(mat3 x, mat3 y)  
mat4 matrixCompMult(mat4 x, mat4 y)

// 结果向量z
z[i][j] = x[i][j] * y[i][j]
复制代码

矢量(向量)关系函数

矢量(向量)关系函数主要包含:<, <=, >, >=, ==, !=),函数参数是整型或者浮点型向量,函数返回值是参数向量各个份量比较产生的一个布尔型向量。 下面用bvec表示bvec二、bvec三、bvec4;ivec表示ivec二、ivec三、ivec4;vec表示 vec二、vec三、vec4。参数向量和返回值向量的大小必须一致。

函数原型 描述
bvec lessThan(vec x, vec y)
bvec lessThan(ivec x, ivec y)
结果向量result[i] = x[i] < y[i]
bvec lessThanEqual(vec x, vec y)
bvec lessThanEqual(ivec x, ivec y)
结果向量result[i] = x[i] <= y[i]
bvec greaterThan(vec x, vec y)
bvec greaterThan(ivec x, ivec y)
结果向量result[i] = x[i] > y[i]
bvec greaterThanEqual(vec x, vec y)
bvec greaterThanEqual(ivec x, ivec y)
结果向量result[i] = x[i] >= y[i]
bvec equal(vec x, vec y)
bvec equal(ivec x, ivec y)
结果向量result[i] = x[i] == y[i]
bvec notEqual(vec x, vec y)
bvec notEqual(ivec x, ivec y)
结果向量result[i] = x[i] != y[i]
bool any(bvec x) 假如参数向量的任意一个份量为true,那么返回true
bool all(bvec x) 假如参数向量的全部份量为true,那么返回true
bvec not(bvec x) 对布尔向量取反

纹理查找函数

纹理查询的目的是从纹理中提取指定坐标的颜色信息。OpenGL中纹理有两种:

  • 2D纹理(sampler2D)
  • 3D纹理(samplerCube)

顶点着色器和片元着色器中均可以使用纹理查找函数。可是顶点着色器中不会计算细节级别(level of detail),因此两者的纹理查找函数略有不一样。

如下函数只在顶点着色器中可用:

vec4 texture2DLod(sampler2D sampler, vec2 coord, float lod);
vec4 texture2DProjLod(sampler2D sampler, vec3 coord, float lod);
vec4 texture2DProjLod(sampler2D sampler, vec4 coord, float lod);
vec4 textureCubeLod(samplerCube sampler, vec3 coord, float lod);
复制代码

如下函数只在片元着色器中可用:

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 textureCube(samplerCube sampler, vec3 coord, float bias);
复制代码

float类型参数bias表示:使用mipmaps计算纹理的适当细节级别以后,在执行实际的纹理查找操做以前添加的误差。

如下函数在顶点着色器和片元着色器中均可用:

vec4 texture2D(sampler2D sampler, vec2 coord);
vec4 texture2DProj(sampler2D sampler, vec3 coord);
vec4 texture2DProj(sampler2D sampler, vec4 coord);
vec4 textureCube(samplerCube sampler, vec3 coord);
复制代码
相关文章
相关标签/搜索