WebGL - 着色器



着色器是在GPU上运行的程序。着色器是用OpenGL ES着色器语言(称为ES SL)编写的。ES SL有自己的变量、数据类型、限定符、内置输入和输出。

数据类型

下表列出了OpenGL ES SL提供的基本数据类型。

序号 类型和描述
1

void

表示空值。

2

bool

接受真或假。

3

int

这是一个有符号整数数据类型。

4

float

这是一个浮点标量数据类型。

5

vec2, vec3, vec4

n分量浮点向量

6

bvec2, bvec3, bvec4

布尔向量

7

ivec2, ivec3, ivec4

有符号整数向量

8

mat2, mat3, mat4

2x2、3x3、4x4浮点矩阵

9

sampler2D

访问二维纹理

10

samplerCube

访问立方体贴图纹理

限定符

OpenGL ES SL中有三个主要的限定符:

序号 限定符和描述
1

attribute

此限定符充当顶点着色器和OpenGL ES之间每个顶点数据的链接。此属性的值在每次执行顶点着色器时都会更改。

2

uniform

此限定符链接着色器程序和WebGL应用程序。与attribute限定符不同,uniform的值不会改变。Uniforms是只读的;您可以将它们与任何基本数据类型一起使用来声明变量。

示例 − uniform vec4 lightPosition;

3

varying

此限定符在顶点着色器和片段着色器之间形成插值数据的链接。它可以与以下数据类型一起使用:float、vec2、vec3、vec4、mat2、mat3、mat4或数组。

示例 − varying vec3 normal;

顶点着色器

顶点着色器是一个程序代码,它在每个顶点上都被调用。它转换(移动)几何体(例如:三角形)从一个位置到另一个位置。它处理每个顶点的数据(每个顶点数据),例如顶点坐标、法线、颜色和纹理坐标。

在顶点着色器的ES GL代码中,程序员必须定义属性来处理数据。这些属性指向用JavaScript编写的顶点缓冲区对象。可以使用顶点着色器以及顶点变换执行以下任务:

  • 顶点变换
  • 法线变换和归一化
  • 纹理坐标生成
  • 纹理坐标变换
  • 光照
  • 颜色材质应用

预定义变量

OpenGL ES SL为顶点着色器提供以下预定义变量:

序号 变量和描述
1

highp vec4 gl_Position;

保存顶点的位置。

2

mediump float gl_PointSize;

保存变换后的点大小。此变量的单位为像素。

示例代码

看一下以下顶点着色器的示例代码。它处理三角形的顶点。

attribute vec2 coordinates;

void main(void) {
   gl_Position = vec4(coordinates, 0.0, 1.0);
};

如果你仔细观察上面的代码,我们会声明一个名为coordinates的属性变量。(此变量将使用getAttribLocation()方法与顶点缓冲区对象关联。属性coordinates作为参数传递给此方法以及着色器程序对象。)

在给定顶点着色器程序的第二步中,定义了gl_position变量。

gl_Position

gl_Position是仅在顶点着色器程序中可用的预定义变量。它包含顶点位置。在上面的代码中,coordinates属性以向量的形式传递。由于顶点着色器是每个顶点的操作,因此为每个顶点计算gl_position值。

稍后,gl_position值将由图元装配、裁剪、剔除以及其他在顶点处理完成后对图元进行操作的固定功能操作使用。

我们可以为顶点着色器的所有可能操作编写顶点着色器程序,我们将在本教程中分别讨论这些操作。

片段着色器

一个网格由多个三角形组成,每个三角形的表面称为一个片段。片段着色器是在每个片段的每个像素上运行的代码。它是用来计算和填充单个像素的颜色。可以使用片段着色器执行以下任务:

  • 对插值值进行操作
  • 纹理访问
  • 纹理应用
  • 颜色相加

预定义变量

OpenGL ES SL为片段着色器提供以下预定义变量:

序号 变量和描述
1

mediump vec4 gl_FragCoord;

保存帧缓冲区内的片段位置。

2

bool gl_FrontFacing;

保存属于正面图元的片段。

3

mediump vec2 gl_PointCoord;

保存点内的片段位置(仅限点光栅化)。

4

mediump vec4 gl_FragColor;

保存着色器的输出片段颜色值

5

mediump vec4 gl_FragData[n]

保存颜色附件n的片段颜色。

示例代码

以下片段着色器的示例代码演示如何将颜色应用于三角形中的每个像素。

void main(void) {
   gl_FragColor = vec4(0, 0.8, 0, 1);
}

在上面的代码中,color值存储在变量gl.FragColor中。片段着色器程序使用固定函数变量将输出传递给流水线;FragColor是其中之一。此变量保存模型像素的颜色值。

存储和编译着色器程序

由于着色器是独立的程序,我们可以将其编写为单独的脚本并在应用程序中使用。或者,您可以像下面那样直接以字符串格式存储它们。

var vertCode =
   'attribute vec2 coordinates;' +
	
   'void main(void) {' +
      ' gl_Position = vec4(coordinates, 0.0, 1.0);' +
   '}';

编译着色器

编译包括以下三个步骤:

  • 创建着色器对象
  • 将源代码附加到已创建的着色器对象
  • 编译程序

创建顶点着色器

要创建一个空着色器,WebGL提供了一个名为createShader()的方法。它创建并返回着色器对象。其语法如下:

Object createShader (enum type)

正如语法中观察到的那样,此方法接受一个预定义的枚举值作为参数。我们有两个选择:

  • gl.VERTEX_SHADER 用于创建顶点着色器

  • gl.FRAGMENT_SHADER 用于创建片段着色器。

将源代码附加到着色器

您可以使用shaderSource()方法将源代码附加到已创建的着色器对象。其语法如下:

void shaderSource(Object shader, string source)

此方法接受两个参数:

  • shader − 您必须将创建的着色器对象作为参数传递。

  • Source − 您必须以字符串格式传递着色器程序代码。

编译程序

要编译程序,您必须使用compileShader()方法。其语法如下:

compileShader(Object shader)

此方法接受着色器程序对象作为参数。创建着色器程序对象后,将源代码附加到它并将该对象传递给此方法。

以下代码片段演示如何创建和编译顶点着色器以及片段着色器来创建三角形。

// Vertex Shader
var vertCode =
   'attribute vec3 coordinates;' +
	
   'void main(void) {' +
      ' gl_Position = vec4(coordinates, 1.0);' +
   '}';

var vertShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertShader, vertCode);
gl.compileShader(vertShader);
 
// Fragment Shader
var fragCode =
   'void main(void) {' +
      ' gl_FragColor = vec4(0, 0.8, 0, 1);' +
   '}';

var fragShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragShader, fragCode);
gl.compileShader(fragShader);

组合程序

创建和编译这两个着色器程序后,您需要创建一个包含这两个着色器(顶点和片段)的组合程序。需要遵循以下步骤:

  • 创建程序对象
  • 附加两个着色器
  • 链接两个着色器
  • 使用程序

创建程序对象

使用createProgram()方法创建一个程序对象。它将返回一个空程序对象。以下是其语法:

createProgram();

附加着色器

使用attachShader()方法将着色器附加到已创建的程序对象。其语法如下:

attachShader(Object program, Object shader);

此方法接受两个参数:

  • Program − 将创建的空程序对象作为参数传递。

  • Shader − 传递已编译的着色器程序之一(顶点着色器、片段着色器)

注意 − 您需要使用此方法附加两个着色器。

链接着色器

使用linkProgram()方法链接着色器,方法是将程序对象传递给已附加着色器的程序对象。其语法如下:

linkProgram(shaderProgram);

使用程序

WebGL提供了一个名为useProgram()的方法。您需要将链接的程序传递给它。其语法如下:

useProgram(shaderProgram);

以下代码片段演示如何创建、链接和使用组合着色器程序。

var shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertShader);
gl.attachShader(shaderProgram, fragShader);
gl.linkProgram(shaderProgram);
gl.useProgram(shaderProgram); 
广告