掌握这些概念,不用担心看不懂OpenGL ES着色语言了

文字转自:掌握这些概念,不用担心看不懂OpenGL ES着色语言了_precision mediump float;_徐福记456的博客-CSDN博客

在OpenGL ES图形学中,着色语言(Shading Language)是一门必修课。在看openGL代码时,都会有着色语言的身影,它有自己的一套语法和格式。提供给我们进行编程的包括顶点着色器和片元着色器,它们都遵循着色语言语法,核心概念包括:向量、矩阵、变量、常量、运算符、采样器、布局限定符、精度限定符、插值限定符、输入输出限定符等。

在顶点着色器中,我们一般看到attribute修饰符,称为属性变量;还有varying修饰符,称为易变变量,连接顶点着色器与片元着色器的桥梁。在片元着色器中,我们会看到uniform修饰符,称为统一变量,也可以在顶点着色器使用uniform。

目录

1、向量

2、矩阵

3、变量

4、常量

5、运算符

6、采样器

7、精度限定符

8、插值限定符

9、输入输出限定符

10、扩展库

11、不变性

1、向量
向量vec,分为浮点向量、整数向量、无符号向量、布尔向量四种,默认为浮点向量。向量又分为二维向量vec2、三维向量vec3、四维向量vec4。向量的单独分量可以用两种方式访问:使用“.”运算符或者通过数组下标。根据组成向量的分量数量,每个分量可以通过使用向量坐标{x, y, z, w}、颜色分量{r, g, b, a}、纹理坐标{s, t, p, q}三种方式访问。如下表格是常见的向量类型:

浮点向量    vec2    vec3    vec4
整数向量    ivec2    ivec3    ivec4
无符号向量    uvec2    uvec3    uvec4
布尔向量    bvec2    bvec3    bvec4
下面是几个例子,分别通过向量坐标、颜色分量、纹理坐标进行向量的访问:

vec4 mVec = vec(1.0, 1.0, 1.0, 1.0);
vec4 cVec = mVec.rgba;
vec4 tVec = mVec.stpq;
vec4 nVec = mVec.xyzw;
2、矩阵
矩阵mat,和向量的维度类似,分为二维矩阵mat2、三维矩阵mat3、四维矩阵mat4。不同的是,矩阵有多行多列,用m*n表示,而向量只有一列或者一行。矩阵可以进行平移、旋转、缩放等操作。

3、变量
上面提及的向量和矩阵一般声明为变量,而且变量前面加上attribute、varying、uniform等修饰符。其中attribute是属性变量,varying是易变变量,uniform是统一变量。openGL提供对应的API去加载attribute变量和uniform变量:

glGetAttribLocation(int program, String name);//加载attribute变量
glGetUniformLocation(int program, String name);//加载uniform变量
4、常量
在openGL定义常量需要加上const修饰符,必须在声明时进行初始化。例如:

const float pi = 3.1415926;
5、运算符
openGL着色语言的运算符与C语言一样。但是,着色语言对运算符有着严格的类型规则。运算符只能出现在有相同基本类型的变量之间,对于二元运算符加减乘除,变量的类型必须是float或者int。除了==和!=之外,比较运算符(<, <=, >, >=)只能用于标量。下面列举着色语言常用的运算符:

openGL ES着色语言运算符
*    乘    ++,--    递增/递减
/    除    >,==,<    比较运算符
+    加    &&    逻辑与
-    减    ||    逻辑或
=    赋值    <<,>>    移位
+=,-=,/=,*=    算术赋值    &,^,|    按位运算
6、采样器
采样器一般分为二维sampler2D和三维sampler3D,用于片元着色器中:

uniform sampler2D uTexture;
void main() {
    gl_FragColor = texture2D(uTexture, fCoord);
}
7、精度限定符
精度限定符是用来指定着色器变量的计算精度。它可以用于指定任何基于float或int变量的精度。精度分为三种:低精度、中等精度和高精度,分别使用lowp、mediump、highp修饰符,并且前面要加上precision。示例代码如下:

precision mediump float;//中等精度
precision highp float;//高精度
precision lowp int;//低精度
8、插值限定符
在没有限定符时,openGL默认的插值 行为是执行平滑着色。也就是说,来自顶点着色器的输出变量在图元中线性插值,片元着色器接收线性插值后的数值作为输入。我们也可以明确地请求平滑着色,如下所示:

//Vertex shader output
smooth out vec3 v_color;
 
//Input form vertex shader
smooth in vec3 v_color;
openGL ES 3.0还引入另一种插值——平面着色。在平面着色中,图元中的值没有进行插值,而是将其中一个顶点视为驱动顶点,该顶点的值被用于图元的所有片段。平面着色输出/输入如下:

//Vertex shader output
flat out vec3 v_color;
 
//Input form vertex shader
flat in vec3 v_color;
9、输入输出限定符
输入输出限定符是用于限定函数是否可以修改可变参数,类似Android的AIDL输入输出修饰符。限定符分为三种:in、out、inout。如下表格所示:

openGL ES着色语言输入输出限定符
限定符    描述
in    指定参数按值传递,函数不能修改
out    该变量不被传入函数,但在函数返回时被修改
inout    该变量按引用传入,可以被函数修改
10、扩展库
openGL着色语言允许使用扩展库,使用extension关键字进行声明。比如,使用SurfaceTexture进行渲染需要用到GL_OES_EGL_image_external库,示例代码如下:

#extension GL_OES_EGL_image_external : require
 
//using externalOES sampler
uniform samplerExternalOES vTexture;
11、不变性
openGL ES着色语言引入invariant关键字修饰顶点着色器变量,也就是不变性。与java的volatile关键字类似,禁止编译器指令重排序。因为编译器在编译期间可能对指令进行重排序优化,导致指令执行顺序发生改变。如果用于计算输出位置的数值精度不一样,精度差异会导致伪像,表现为“深度冲突”(Z fighting),每个像素的Z(深度)精度差异导致多遍着色互相之间的微小偏移。

结合上面概念,我们就容易编写出顶点着色器和片元着色器了。示例代码如下:

//Vertex shader
attribute vec4 vPosition;
attribute vec2 vCoord;
varying   vec2 fCoord;
 
void main() {
    gl_Position = vPosition;
    fCoord = vCoord;
}
 
 
//Fragment shader
precision mediump float;
 
varying vec2 fCoord;
uniform sampler2D vTexture;
 
void main() {
    gl_FragColor = texture2D(vTexture, fCoord);
}
参考书本:
————————————————
版权声明:本文为CSDN博主「徐福记456」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u011686167/article/details/104643835

你可能感兴趣的:(webGL,webgl)