着色器是在GPU上运行的程序。着色器以OpenGL ES着色器语言(称为ES SL)编写。ES SL具有自己的变量,数据类型,限定符,内置输入和输出。
资料类型
下表列出了OpenGL ES SL提供的基本数据类型。
序号 | 类型与说明 |
---|---|
1个 | void 表示一个空值。 |
2 | 布尔 接受true或false。 |
3 | int 这是一个带符号的整数数据类型。 |
4 | float 这是一个浮动标量数据类型。 |
5 | vec2,vec3,vec4n 分量浮点向量 |
6 | bvec2,bvec3,bvec4 布尔向量 |
7 | ivec2,ivec3,ivec4 有符号整数矢量 |
8 | mat2,mat3,mat4 2×2、3×3、4×4浮点矩阵 |
9 | sampler2D 访问2D纹理 |
10 | samplerCube 访问多维数据集映射的纹理 |
限定词
OpenGL ES SL中有三个主要限定词。
序号 | 限定词和说明 |
---|---|
1个 | 属性 此限定符充当顶点着色器和OpenGL ES之间针对每个顶点数据的链接。每次执行顶点着色器时,此属性的值都会更改。 |
2 | uniform 该限定符链接着色器程序和WebGL应用程序。与属性限定符不同,uniforms的值不会改变。uniforms是只读的;您可以将它们与任何基本数据类型一起使用以声明变量。 |
3 | 变化 此限定符在顶点着色器和片段着色器之间形成用于内插数据的链接。它可以与以下数据类型(float,vec2,vec3,vec4,mat2,mat3,mat4或数组)一起使用。 |
顶点着色器
顶点着色器是一个程序代码,在每个顶点上都会调用它。它将几何形状(例如:三角形)从一个位置转换(移动)到另一位置。它处理每个顶点的数据(每个顶点的数据),例如顶点坐标,法线,颜色和纹理坐标。
在顶点着色器的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); };
如果您仔细观察上面的代码,我们已经声明了一个名称为坐标的属性变量。(此变量将使用getAttribLocation()方法与“顶点缓冲区对象”关联。属性坐标作为参数与着色器程序对象一起传递给此方法。)
在给定顶点着色器程序的第二步中,定义了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); }
在上面的代码中,颜色值存储在变量中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);
作者:terry,如若转载,请注明出处:https://www.web176.com/webgl/822.html