📜  WebGL-着色器

📅  最后修改于: 2020-10-17 05:28:18             🧑  作者: Mango


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

资料类型

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

Sr.No. Type & Description
1

void

Represents an empty value.

2

bool

Accepts true or false.

3

int

This is a signed integer data type.

4

float

This is a floating scalar data type.

5

vec2, vec3, vec4

n-component floating point vector

6

bvec2, bvec3, bvec4

Boolean vector

7

ivec2, ivec3, ivec4

signed integer vector

8

mat2, mat3, mat4

2×2, 3×3, 4×4 float matrix

9

sampler2D

Access a 2D texture

10

samplerCube

Access cube mapped texture

资格赛

OpenGL ES SL中有三个主要限定词-

Sr.No. Qualifier & Description
1

attribute

This qualifier acts as a link between a vertex shader and OpenGL ES for per-vertex data. The value of this attribute changes for every execution of the vertex shader.

2

uniform

This qualifier links shader programs and the WebGL application. Unlike attribute qualifier, the values of uniforms do not change. Uniforms are read-only; you can use them with any basic data types, to declare a variable.

Example − uniform vec4 lightPosition;

3

varying

This qualifier forms a link between a vertex shader and fragment shader for interpolated data. It can be used with the following data types − float, vec2, vec3, vec4, mat2, mat3, mat4, or arrays.

Example − varying vec3 normal;

顶点着色器

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

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

  • 顶点变换
  • 正态变换和归一化
  • 纹理坐标生成
  • 纹理坐标变换
  • 灯光
  • 色料应用

预定义变量

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

Sr.No. Variables & Description
1

highp vec4 gl_Position;

Holds the position of the vertex.

2

mediump float gl_PointSize;

Holds the transformed point size. The units for this variable are pixels.

样例代码

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

attribute vec2 coordinates;

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

如果您仔细观察上面的代码,我们已经声明了一个名称为坐标的属性变量。 (此变量将使用getAttribLocation()方法与“顶点缓冲区对象”相关联。属性坐标作为参数与着色器程序对象一起传递给此方法。)

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

gl_Position

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

稍后,在顶点处理结束后,gl_position值将由图元组装,裁剪,剔除和其他对图元进行操作的固定功能操作使用。

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

片段着色器

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

  • 插值运算
  • 纹理访问
  • 纹理应用
  • 多雾路段
  • 颜色总和

预定义变量

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

Sr.No. Variables & Description
1

mediump vec4 gl_FragCoord;

Holds the fragment position within the frame buffer.

2

bool gl_FrontFacing;

Holds the fragment that belongs to a front-facing primitive.

3

mediump vec2 gl_PointCoord;

Holds the fragment position within a point (point rasterization only).

4

mediump vec4 gl_FragColor;

Holds the output fragment color value of the shader

5

mediump vec4 gl_FragData[n]

Holds the fragment color for color attachment n.

样例代码

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

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

在上面的代码中,颜色值存储在变量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-您必须将创建的shader对象作为一个参数传递。

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

编译程序

要编译程序,必须使用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);

此方法接受两个参数-

  • 程序-将创建的空程序对象作为一个参数传递。

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

注意-您需要使用此方法连接两个着色器。

链接着色器

使用方法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);