WebGL 着色器编程语言GLSL ES的全局变量和局部变量

就像JavaScript和C语言,GLSL ES中也有全局变量和局部变量的概念。全局变量可以在程序中的任意位置使用,而局部变量只能在优先的某一部分代码中使用。

在GLSL ES中,如果变量声明在函数的外面,那么它就是全局变量,如果声明在函数内部,那就是局部变量。这和JavaScript与C语言也是一样的。局部变量只能在函数内部使用,因此,由于需要在函数外部访问,attribute变量、varying变量和uniform变量都必须声明为全局变量。

存储限定字

在GLSL ES中,我们经常使用attribute、varying和uniform限定字来修饰变量。此外,我们优势也会使用const限定字,他表示着色器中的某个变量是恒定的常量。

const变量

JavaScript中没有const变量的概念(es6有了),但是GLSL ES中有。我们使用const限定字表示该变量的值不能被改变。

在声明const变量时,需要将const写在类型之前,就像声明attribute变量时将attribute写在前面一样。声明同事必须对它进行初始化,声明之后就不能再去改变它们的值了。比如:

const int lightspeed = 299792458; //光速(m/s)
const vec4 red = vec4(1.0,0.0,0.0,1.0); //红色
const mat4 identity = mat4(1.0); //单位矩阵

试图向const变量赋值会导致编译报错,比如:

const int lightspeed;
lightspeed = 299792458;

attribute 变量

你一定已经很熟悉attribute变量了。attribute变量只能出现在顶点着色器中,只能被声明为全局变量,被用来表示逐顶点的信息。你应该重点理解“逐顶点”的含义。比如,如果线段有两个顶点(4.0,3.0,6.0)和(8.0,3.0,0.0),这两个坐标就会传递给attribute变量。而线段上的其他点,比如中点(6.0,3.0,3.0),虽然也被画了出来,但它不是顶点,坐标未曾传递给attribute变量,也未曾被顶点着色器处理过。如果你想要让顶点着色器处理它,你就需要将它作为一个顶点添加到图形中来。attribute变量的类型只能是float、vec2、vec3、vec4、mat2、mat3和mat4。比如:

attribute vec4 a_Color;
attribute float a_Position;

顶点着色器中能容纳的attribute变量的最大数目与设备有关,你可以通过访问内置的全局常量来获取该值(最大数目)。但是,不管设备配置如何,支持WebGL的环境都支持至少8个attribute变量,如表所示:

uniform变量

uniform变量可以用在顶点着色器和片元着色器中,且必须是全局变量。uniform变量是只读的,它可以是除了数组或结构体之外的任意类型。如果顶点着色器和片元着色器中声明了同名的uniform变量,那么它就会被两种着色器共享。uniform变量包含了“一致”(非逐顶点/逐片元的,个顶点或个片元公用)的数据,JavaScript应该向其传递此类数据。比如,变换矩阵就不是逐顶点的,而是所有顶点共用的,所以它在着色器中是uniform变量。

uniform mat4 u_ViewMatrix;
uniform vec3 u_LightPosition;

顶点着色器和片元着色器对其中uniform变量的数量限制于设备有关,且各不相同。

varying变量 

最后一个限定字是varying。varying变量必须是全局变量,它的任务是从顶点着色器向片元着色器传输数据。我们必须在两种着色器中声明同名、同类型的varying变量。下面是声明varying变量的两个列子: 

varying vec2 v_TexCoord;
varying vec4 v_Color;

和attribute变量一样,varying变量只能是以下类型:float、vec2、vec3、vec4、mat2、mat3、和mat4。顶点着色器中赋给varying变量的值并不是直接传给了片元着色器的varying变量,这其中发生了光栅化的过程:根据绘制的图形,对前者(顶点着色器varying变量)进行内插,然后在传递给后者(片元着色器varying变量)。正是因为varying变量需要被内插,所以我们需要限制它的数据类型。

varying变量的数量限制也与设备有关,至少支持8个。

原文地址:https://www.cnblogs.com/bq-med/p/13959763.html