webgl 的 attribute、 uniform 、 vary 变量

webgl 的 attribute、 uniform 、 varying变量

webgl 中可以使用 attribute、 uniform 、 varying给 Shader 传参 。

关键字(变量类型) 数据传递 声明变量
attribute javascript——>顶点着色器 声明顶点数据变量
uniform javascript——>顶点、片元着色器 声明非顶点数据变量
varying 顶点着色器——>片元着色器 声明需要插值计算的顶点变量

attribute

在着色器中声明了attribute变量∶


1
2
3
4
<script id="vertexShader" type="x-shader/x-vertex">
attribute vec4 a_Position;

</script>

image-20210923174316194

通过 js 获取 attribute 变量的存储位置


1
2
3
4
5
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
if (a_Position < 0) {
console.log('Failed to get the storage location of a_Position');
return;
}

js 给 attribute 变量赋值

1
2
3
4
5
6
7
8
9
void gl.vertexAttrib1f(location, v0);
void gl.vertexAttrib2f(location, v0, v1);
void gl.vertexAttrib3f(location, v0, v1, v2);
void gl.vertexAttrib4f(location, v0, v1, v2, v3);

void gl.vertexAttrib1fv(location, value);
void gl.vertexAttrib2fv(location, value);
void gl.vertexAttrib3fv(location, value);
void gl.vertexAttrib4fv(location, value);
  • **location ** 要修改的uniform 属性位置

  • value v0, v1, v2, v3 指定传输给uniform 变量各个分量的值


  • 类型:

    • 浮点值 Number(方法名跟”f”).

    • 浮点数组 ( 例如 Float32Array 或 Array 的数组) 用于浮点型向量方法 ( 方法名跟 “fv” ).

通过缓存 给 attribute 变量赋值

1
2
3
4
5
6
7
8
9
10
11
12
var vertices = new Float32Array([
0.0, 0.5, -0.5, -0.5, 0.5, -0.5
]);

var vertex_buffer = gl.createBuffer(); // 创建一个空的缓冲区对象来存储顶点缓冲区
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer); // 绑定缓冲区对象
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW); // 将顶点数据传递到缓冲区

//绑定 a_position
var a_position = gl.getAttribLocation(shaderProgram, "a_position");
gl.vertexAttribPointer(a_position, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(a_position);

uniform

uniform变量一般用于从 JavaScript程序向顶点着色器和片元着色器传输 (静态)不变的 数据 。

在着色器中声明了 uniform 变量∶


1
2
3
4
5
6
<script id="fragmentShader" type="x-shader/x-fragment">
uniform vec4 u_FragColor;
void main(){
gl_FragColor = u_FragColor;
}
</script>

通过 js 获取 Uniform 变量的存储位置


1
2
3
4
5
6
var u_FragColor = gl.getUniformLocation(gl.program, 'u_FragColor');
if (!u_FragColor) {
console.log('Failed to get the storage location of u_FragColor');
return;
}

通过 js 给 Uniform 变量赋值

1
gl.uniform4f(u_FragColor, 0.0, 0.8, 0.0, 1.0);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void gl.uniform1f(location, v0);
void gl.uniform2f(location, v0, v1);
void gl.uniform3f(location, v0, v1, v2);
void gl.uniform4f(location, v0, v1, v2, v3);

void gl.uniform1fv(location, value);
void gl.uniform2fv(location, value);
void gl.uniform3fv(location, value);
void gl.uniform4fv(location, value);

void gl.uniform1i(location, v0);
void gl.uniform2i(location, v0, v1);
void gl.uniform3i(location, v0, v1, v2);
void gl.uniform4i(location, v0, v1, v2, v3);

void gl.uniform1iv(location, value);
void gl.uniform2iv(location, value);
void gl.uniform3iv(location, value);
void gl.uniform4iv(location, value);
  • **location ** 要修改的uniform 属性位置

  • value v0, v1, v2, v3 指定传输给uniform 变量各个分量的值


  • 类型:

    • 浮点值 Number(方法名跟”f”).
    • 浮点数组 ( 例如 Float32Array 或 Array 的数组) 用于浮点型向量方法 ( 方法名跟 “fv” ).
    • 整型值 Number (方法名跟”i”).
    • 整型数组 Int32Array 用于整型向量方法 (方法名跟 “iv”).

varying

uniform 变量可以向片元着色器传递静态的值 ,varying 却可以向片元着色器传递动态的值 (插值) ,varying 变量的只能从顶点着色器向片元着色器传输数据,不能直接通过js 向片元着色器传递。

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
<html>
<head>
<meta charset="utf-8">
<title></title>


<script id="vertexShader" type="x-shader/x-vertex">
attribute vec4 a_Position;
attribute vec4 a_Color;
varying vec4 v_Color;
void main() {
gl_Position = a_Position;
v_Color = a_Color;
}
</script>

<script id="fragmentShader" type="x-shader/x-fragment">

#ifdef GL_ES
precision mediump float;
#endif

varying vec4 v_Color;
void main(){
gl_FragColor = v_Color;
}
</script>

</head>
<body>

<canvas id='glcanvas' width='600' height='600'></canvas>


<script>
var canvas = document.getElementById('glcanvas');
var gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');


//顶点着色器源码
var vertexShaderSource = document.getElementById('vertexShader').innerText;

//片元着色器源码
var fragShaderSource = document.getElementById('fragmentShader').innerText;


//创建顶点着色器对象
var vShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vShader, vertexShaderSource); //引入顶点着色器源代码
gl.compileShader(vShader); ////编译顶点着色器

//创建片元着色器对象
var fShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fShader, fragShaderSource); //引入片元着色器源代码
gl.compileShader(fShader); //编译片元着色器

var shaderProgram = gl.createProgram(); //创建程序对象program

//附着顶点着色器和片元着色器到program
gl.attachShader(shaderProgram, vShader);
gl.attachShader(shaderProgram, fShader);

gl.linkProgram(shaderProgram); // 链接program
gl.useProgram(shaderProgram); // 使用program

//清空画板
gl.clearColor(0.0, 0.0, 0.0, 1.0); //设置清空颜色缓冲时的颜色
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

var verticesColors = new Float32Array([
// Vertex coordinates and color
0.0, 0.5, 1.0, 0.0, 0.0,
-0.5, -0.5, 0.0, 1.0, 0.0,
0.5, -0.5, 0.0, 0.0, 1.0,
]);

var FSIZE = verticesColors.BYTES_PER_ELEMENT;

var vertexColorBuffer = gl.createBuffer(); // 创建一个空的缓冲区对象来存储顶点缓冲区
gl.bindBuffer(gl.ARRAY_BUFFER, vertexColorBuffer); // 绑定缓冲区对象
gl.bufferData(gl.ARRAY_BUFFER, verticesColors, gl.STATIC_DRAW);

//绑定 a_position
var a_Position = gl.getAttribLocation(shaderProgram, "a_Position");
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, FSIZE * 5, 0);
gl.enableVertexAttribArray(a_Position); // Enable the assignment of the buffer object

//绑定 a_Color
var a_Color = gl.getAttribLocation(shaderProgram, 'a_Color');
gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, FSIZE * 5, FSIZE * 2);
gl.enableVertexAttribArray(a_Color); // Enable the assignment of the buffer object

gl.drawArrays(gl.TRIANGLES, 0, 3);
</script>

</body>
</html>

image-20210924185901753

上述代码中,我们在 varying 变量中为三角形的3个不同顶点指定了3种不同颜色,而三角形表面上这些片元的颜色值都是WebGL 系统用这3个顶点的颜色内插出来的。

什么是内插

例如,考虑一条两个端点的颜色不同的线段。一个端点的颜色为红色(1.0,0.0,0.0),而另一个端点的颜色为蓝色(0.0,0.0.1.0)。我们在顶点着色器中向 varying 变量y color 赋上这两个颜色(红色和蓝色),那么 WebGL 就会自动地计算出线段上的所有点(片元)的颜色,并赋值给片元着色器中的 varying 变量v_color(如图所示)。


image-20210924190313499

在这个例子中 RGBA中的R值从1.0降低为0.0,而 B值则从0.0上升至1.0,线段上的所有片元的颜色值都会被恰当地计算出来——这个过程就被称为内插过程。一旦两点之间每个片元的新颜色都通过这种方式被计算出来后,它们就会被传给片元着色器中的 v_color变量。


webgl 的 attribute、 uniform 、 vary 变量
http://example.com/2024/05/23/webgl/webgl 的 attribute、 uniform 、 vary 变量/
Author
John Doe
Posted on
May 23, 2024
Licensed under