jmgraph 3.2.2 → 3.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/jmgraph.core.min.js +1 -1
- package/dist/jmgraph.core.min.js.map +1 -1
- package/dist/jmgraph.js +3064 -351
- package/dist/jmgraph.min.js +1 -1
- package/index.js +4 -0
- package/package.json +4 -4
- package/src/core/jmControl.js +97 -57
- package/src/core/jmGradient.js +29 -14
- package/src/core/jmGraph.js +70 -26
- package/src/core/jmObject.js +2 -3
- package/src/core/jmPath.js +19 -3
- package/src/core/jmProperty.js +29 -14
- package/src/core/jmUtils.js +218 -31
- package/src/lib/earcut.js +680 -0
- package/src/lib/earcut.md +73 -0
- package/src/lib/webgl/base.js +201 -0
- package/src/lib/webgl/core/buffer.js +48 -0
- package/src/lib/webgl/core/mapSize.js +40 -0
- package/src/lib/webgl/core/mapType.js +43 -0
- package/src/lib/webgl/core/program.js +139 -0
- package/src/lib/webgl/core/shader.js +14 -0
- package/src/lib/webgl/core/texture.js +61 -0
- package/src/lib/webgl/gradient.js +196 -0
- package/src/lib/webgl/index.js +11 -0
- package/src/lib/webgl/path.js +679 -0
- package/src/shapes/jmArc.js +15 -11
- package/src/shapes/jmArrow.js +10 -10
- package/src/shapes/jmBezier.js +2 -2
- package/src/shapes/jmCircle.js +8 -1
- package/src/shapes/jmHArc.js +17 -15
- package/src/shapes/jmImage.js +68 -38
- package/src/shapes/jmLabel.js +11 -10
- package/src/shapes/jmLine.js +20 -12
- package/src/shapes/jmPrismatic.js +4 -2
- package/src/shapes/jmRect.js +5 -4
- package/src/shapes/jmResize.js +6 -4
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
在前端开发中,很多时候需要对复杂的多边形进行分割,以便更好地进行渲染和处理。这时候,我们可以使用一些工具来进行分割操作。其中,一个非常实用的工具就是 npm 包 earcut。
|
|
2
|
+
|
|
3
|
+
本文将详细介绍 npm 包 earcut 的使用方法,包括安装、基本用法和示例代码等方面。
|
|
4
|
+
|
|
5
|
+
安装
|
|
6
|
+
要使用 npm 包 earcut,我们首先需要进行安装。在命令行中执行以下命令即可完成安装:
|
|
7
|
+
|
|
8
|
+
`npm install earcut`
|
|
9
|
+
|
|
10
|
+
基本用法
|
|
11
|
+
安装完成后,我们就可以在项目代码中使用 earcut 了。下面是一个基本示例:
|
|
12
|
+
|
|
13
|
+
```js
|
|
14
|
+
const earcut = require('earcut');
|
|
15
|
+
|
|
16
|
+
// 定义多边形坐标点数组
|
|
17
|
+
const coords = [
|
|
18
|
+
100, 100,
|
|
19
|
+
200, 150,
|
|
20
|
+
150, 200,
|
|
21
|
+
50, 150
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
// 进行多边形分割
|
|
25
|
+
const triangles = earcut(coords);
|
|
26
|
+
|
|
27
|
+
console.log(triangles); // [1, 0, 3, 3, 2, 1]
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
在这个示例中,我们使用 earcut 对一个四边形多边形进行了分割,并将分割结果输出到控制台。
|
|
32
|
+
|
|
33
|
+
earcut 在进行分割时,需要我们将多边形的坐标点以一定的格式传入。具体格式如下:
|
|
34
|
+
|
|
35
|
+
坐标点数组中,每两项表示一个坐标点的 x、y 值。
|
|
36
|
+
坐标点数组中的所有坐标点按顺序构成了一个多边形。
|
|
37
|
+
如果多边形包含内部空洞,需要将空洞内部的坐标按顺序插入到坐标点数组中。
|
|
38
|
+
使用 earcut 进行多边形分割后,分割结果将会是一个数字数组。其中,每三个数字表示一个三角形的三个顶点在坐标点数组中的索引。
|
|
39
|
+
|
|
40
|
+
示例代码
|
|
41
|
+
下面是一个更为复杂的示例,展示了如何使用 earcut 进行多个带空洞的多边形的分割:
|
|
42
|
+
```js
|
|
43
|
+
const earcut = require('earcut');
|
|
44
|
+
|
|
45
|
+
// 定义多边形坐标点数组(按照序号连接即组成完整图形,后两组为同一空洞)
|
|
46
|
+
const coords = [
|
|
47
|
+
100, 0,
|
|
48
|
+
0, 100,
|
|
49
|
+
100, 200,
|
|
50
|
+
200, 100,
|
|
51
|
+
|
|
52
|
+
50, 50,
|
|
53
|
+
100, 100,
|
|
54
|
+
150, 50
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
// 定义多边形顶点索引数组,每个多边形用三个数字表示
|
|
58
|
+
const polygonIndices = [
|
|
59
|
+
0, 1, 2,
|
|
60
|
+
0, 2, 3,
|
|
61
|
+
|
|
62
|
+
4, 5, 6
|
|
63
|
+
];
|
|
64
|
+
|
|
65
|
+
// 进行多边形分割
|
|
66
|
+
const triangles = earcut(coords, polygonIndices);
|
|
67
|
+
|
|
68
|
+
console.log(triangles); // [2, 0, 3, 6, 4, 5, 1, 0, 8, 7, 6, 5]
|
|
69
|
+
```
|
|
70
|
+
在这个示例中,我们定义了两个多边形。第一个多边形是一个正方形,带有一个内部的小正方形空洞。第二个多边形是一个三角形,没有空洞。通过传入多边形坐标点数组和多边形顶点索引数组到 earcut 函数,我们将多个多边形同时进行了分割。程序输出的结果则是所有分割后的三角形的顶点在坐标点数组中的索引。
|
|
71
|
+
|
|
72
|
+
结语
|
|
73
|
+
本文介绍了 npm 包 earcut 的基本使用方法和示例代码。通过本文的学习,相信读者已经了解了 earcut 的基本功能和用法,并可以在自己的项目中灵活运用它进行多边形分割操作。
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
|
|
2
|
+
import earcut from '../earcut.js';
|
|
3
|
+
import webglGradient from './gradient.js';
|
|
4
|
+
import {
|
|
5
|
+
createProgram,
|
|
6
|
+
useProgram,
|
|
7
|
+
writeVertexAttrib,
|
|
8
|
+
disableVertexAttribArray
|
|
9
|
+
} from './core/program.js';
|
|
10
|
+
|
|
11
|
+
import {
|
|
12
|
+
createFloat32Buffer,
|
|
13
|
+
createUint16Buffer,
|
|
14
|
+
deleteBuffer,
|
|
15
|
+
} from './core/buffer.js';
|
|
16
|
+
|
|
17
|
+
import {
|
|
18
|
+
create2DTexture,
|
|
19
|
+
createImgTexture,
|
|
20
|
+
createDataTexture,
|
|
21
|
+
deleteTexture
|
|
22
|
+
} from './core/texture.js';
|
|
23
|
+
|
|
24
|
+
class WeblBase {
|
|
25
|
+
constructor(graph, option) {
|
|
26
|
+
this.graph = graph;
|
|
27
|
+
this.option = option || {};
|
|
28
|
+
this.style = {
|
|
29
|
+
globalAlpha: 1
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
get context() {
|
|
34
|
+
if(this.graph) return this.graph.context;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// 创建程序
|
|
38
|
+
createProgram(vertexSrc, fragmentSrc) {
|
|
39
|
+
return createProgram(this.context, vertexSrc, fragmentSrc);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// 指定使用某个程序
|
|
43
|
+
useProgram(program=this.program) {
|
|
44
|
+
program = program.program || program;
|
|
45
|
+
if(this.context.__curent_program === program) return program;
|
|
46
|
+
useProgram(this.context, program.program || program);
|
|
47
|
+
this.context.__curent_program = program;
|
|
48
|
+
return program;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
getAttribLocation(name) {
|
|
52
|
+
return this.context.getAttribLocation(this.program.program, name);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
getUniformLocation(name) {
|
|
56
|
+
return this.context.getUniformLocation(this.program.program, name);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// 把缓冲区的值写入变量
|
|
60
|
+
// buffer: 缓冲区
|
|
61
|
+
// size: 组成数量,必须是1,2,3或4. 每个单元由多少个数组成
|
|
62
|
+
// strip: 步长 数组中一行长度,0 表示数据是紧密的没有空隙,让OpenGL决定具体步长
|
|
63
|
+
// offset: 字节偏移量,必须是类型的字节长度的倍数。
|
|
64
|
+
// dataType: 每个元素的数据类型
|
|
65
|
+
writeVertexAttrib(buffer, attr, size=2, strip=0, offset=0, dataType=this.context.FLOAT) {
|
|
66
|
+
buffer.attr = attr;
|
|
67
|
+
return writeVertexAttrib(this.context, buffer, attr, size, strip, offset, dataType);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// 禁用attri
|
|
71
|
+
disableVertexAttribArray(attr) {
|
|
72
|
+
try{
|
|
73
|
+
if(!attr) return attr;
|
|
74
|
+
return disableVertexAttribArray(this.context, attr);
|
|
75
|
+
}
|
|
76
|
+
catch(e) {
|
|
77
|
+
console.error(e);
|
|
78
|
+
}
|
|
79
|
+
return attr;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// 创建float32的buffer
|
|
83
|
+
createFloat32Buffer(data, type=this.context.ARRAY_BUFFER, drawType=this.context.STATIC_DRAW) {
|
|
84
|
+
const buffer = createFloat32Buffer(this.context, data, type, drawType);
|
|
85
|
+
return {
|
|
86
|
+
data,
|
|
87
|
+
...buffer
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
createUint16Buffer(data, type=this.context.ARRAY_BUFFER, drawType=this.context.STATIC_DRAW) {
|
|
92
|
+
const buffer = createUint16Buffer(this.context, data, type, drawType);
|
|
93
|
+
return {
|
|
94
|
+
data,
|
|
95
|
+
...buffer
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// 释放
|
|
100
|
+
deleteBuffer(buffer) {
|
|
101
|
+
try {
|
|
102
|
+
if(!buffer) return;
|
|
103
|
+
const bufferHandler = buffer.buffer || buffer;
|
|
104
|
+
if(bufferHandler) return deleteBuffer(this.context, bufferHandler);
|
|
105
|
+
}
|
|
106
|
+
catch(e) {
|
|
107
|
+
console.log(buffer);
|
|
108
|
+
console.error(e);
|
|
109
|
+
}
|
|
110
|
+
return buffer;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// 生成纹理
|
|
114
|
+
create2DTexture() {
|
|
115
|
+
return create2DTexture(this.context);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// 创建图片纹理
|
|
119
|
+
createImgTexture(img) {
|
|
120
|
+
return createImgTexture(this.context, img);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// 根根像素值生成纹理
|
|
124
|
+
createDataTexture(data) {
|
|
125
|
+
return createDataTexture(this.context, data);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// 删除纹理
|
|
129
|
+
deleteTexture(texture) {
|
|
130
|
+
try {
|
|
131
|
+
return deleteTexture(this.context, texture.texture || texture);
|
|
132
|
+
}
|
|
133
|
+
catch(e) {
|
|
134
|
+
console.error(e);
|
|
135
|
+
}
|
|
136
|
+
return texture;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// 多边切割, 得到三角形顶点索引数组
|
|
140
|
+
// polygonIndices 顶点索引,
|
|
141
|
+
earCutPoints(points) {
|
|
142
|
+
const arr = this.pointsToArray(points);
|
|
143
|
+
const ps = earcut(arr);// 切割得到3角色顶点索引,
|
|
144
|
+
return ps;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// 多边切割, 得到三角形顶点
|
|
148
|
+
// polygonIndices 顶点索引,
|
|
149
|
+
earCutPointsToTriangles(points) {
|
|
150
|
+
const ps = this.earCutPoints(points);// 切割得到3角色顶点索引,
|
|
151
|
+
const triangles = [];
|
|
152
|
+
// 用顶点索引再组合成坐标数组
|
|
153
|
+
for(let i=0;i<ps.length; i+=3) {
|
|
154
|
+
const p1 = points[ps[i]];
|
|
155
|
+
const p2 = points[ps[i+1]];
|
|
156
|
+
const p3 = points[ps[i+2]];
|
|
157
|
+
|
|
158
|
+
triangles.push([p1, p2, p3]);// 每三个顶点构成一个三角
|
|
159
|
+
}
|
|
160
|
+
return triangles;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// 点坐标数组转为一维数组
|
|
164
|
+
pointsToArray(points) {
|
|
165
|
+
return [].concat(...points.map(p=>[p.x,p.y]));// 把x,y转为数组元素
|
|
166
|
+
}
|
|
167
|
+
// 每2位表示坐标x,y转为坐标点对象
|
|
168
|
+
arrayToPoints(arr) {
|
|
169
|
+
const points = [];
|
|
170
|
+
for(let i=0;i<arr.length; i+=2) {
|
|
171
|
+
points.push({
|
|
172
|
+
x: arr[i],
|
|
173
|
+
y: arr[i+1]
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
return points;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// 创建线性渐变
|
|
180
|
+
createLinearGradient(x1, y1, x2, y2, bounds) {
|
|
181
|
+
return new webglGradient('linear', {
|
|
182
|
+
x1, y1, x2, y2, bounds,
|
|
183
|
+
control: this
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
// 创建放射性渐变
|
|
187
|
+
createRadialGradient(x1, y1, r1, x2, y2, r2, bounds) {
|
|
188
|
+
return new webglGradient('radial', {
|
|
189
|
+
x1, y1, r1,
|
|
190
|
+
x2, y2, r2,
|
|
191
|
+
bounds,
|
|
192
|
+
control: this
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
// 判断是否是一个渐变对象
|
|
196
|
+
isGradient(obj) {
|
|
197
|
+
return obj && obj instanceof webglGradient;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export default WeblBase;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
|
|
2
|
+
// 创建缓冲区
|
|
3
|
+
function createBuffer(gl, data, type=gl.ARRAY_BUFFER, drawType=gl.STATIC_DRAW) {
|
|
4
|
+
//先创建一个缓存对象
|
|
5
|
+
const buffer = gl.createBuffer();
|
|
6
|
+
if(!buffer) {
|
|
7
|
+
throw Error('创建缓冲区对象失败');
|
|
8
|
+
}
|
|
9
|
+
//说明缓存对象保存的类型
|
|
10
|
+
gl.bindBuffer(type, buffer);
|
|
11
|
+
//写入坐标数据
|
|
12
|
+
// 因为会将数据发送到 GPU,为了省去数据解析,这里使用 Float32Array 直接传送数据
|
|
13
|
+
gl.bufferData(type, data, drawType); // 表示缓冲区的内容不会经常更改
|
|
14
|
+
return {
|
|
15
|
+
type,
|
|
16
|
+
drawType,
|
|
17
|
+
buffer,
|
|
18
|
+
// 获取到数组中单个元素的字节数
|
|
19
|
+
unitSize: data.BYTES_PER_ELEMENT
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// 创建float32的buffer
|
|
24
|
+
function createFloat32Buffer(gl, data, type=gl.ARRAY_BUFFER, drawType=gl.STATIC_DRAW) {
|
|
25
|
+
const vertices = new Float32Array(data);
|
|
26
|
+
const buffer = createBuffer(gl, vertices, type, drawType);
|
|
27
|
+
return buffer;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// 创建uint16的bugger
|
|
31
|
+
function createUint16Buffer(gl, data, type=gl.ARRAY_BUFFER, drawType=gl.STATIC_DRAW) {
|
|
32
|
+
const vertices = new Uint16Array(data);
|
|
33
|
+
const buffer = createBuffer(gl, vertices, type, drawType);
|
|
34
|
+
return buffer;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// 释放
|
|
38
|
+
function deleteBuffer(gl, buffer) {
|
|
39
|
+
gl.deleteBuffer(buffer.buffer || buffer);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
export {
|
|
44
|
+
createBuffer,
|
|
45
|
+
createUint16Buffer,
|
|
46
|
+
createFloat32Buffer,
|
|
47
|
+
deleteBuffer,
|
|
48
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
|
|
2
|
+
const GLSL_TO_SIZE = {
|
|
3
|
+
'float': 1,
|
|
4
|
+
'vec2': 2,
|
|
5
|
+
'vec3': 3,
|
|
6
|
+
'vec4': 4,
|
|
7
|
+
|
|
8
|
+
'int': 1,
|
|
9
|
+
'ivec2': 2,
|
|
10
|
+
'ivec3': 3,
|
|
11
|
+
'ivec4': 4,
|
|
12
|
+
|
|
13
|
+
'bool': 1,
|
|
14
|
+
'bvec2': 2,
|
|
15
|
+
'bvec3': 3,
|
|
16
|
+
'bvec4': 4,
|
|
17
|
+
|
|
18
|
+
'mat2': 4,
|
|
19
|
+
'mat3': 9,
|
|
20
|
+
'mat4': 16,
|
|
21
|
+
|
|
22
|
+
'sampler2D': 1
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @class
|
|
27
|
+
* @memberof PIXI.glCore.shader
|
|
28
|
+
* @param type {String}
|
|
29
|
+
* @return {Number}
|
|
30
|
+
*/
|
|
31
|
+
const mapSize = function(type) {
|
|
32
|
+
return GLSL_TO_SIZE[type];
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
export {
|
|
39
|
+
mapSize
|
|
40
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
|
|
2
|
+
var GL_TABLE = null;
|
|
3
|
+
|
|
4
|
+
const GL_TO_GLSL_TYPES = {
|
|
5
|
+
'FLOAT': 'float',
|
|
6
|
+
'FLOAT_VEC2': 'vec2',
|
|
7
|
+
'FLOAT_VEC3': 'vec3',
|
|
8
|
+
'FLOAT_VEC4': 'vec4',
|
|
9
|
+
|
|
10
|
+
'INT': 'int',
|
|
11
|
+
'INT_VEC2': 'ivec2',
|
|
12
|
+
'INT_VEC3': 'ivec3',
|
|
13
|
+
'INT_VEC4': 'ivec4',
|
|
14
|
+
|
|
15
|
+
'BOOL': 'bool',
|
|
16
|
+
'BOOL_VEC2': 'bvec2',
|
|
17
|
+
'BOOL_VEC3': 'bvec3',
|
|
18
|
+
'BOOL_VEC4': 'bvec4',
|
|
19
|
+
|
|
20
|
+
'FLOAT_MAT2': 'mat2',
|
|
21
|
+
'FLOAT_MAT3': 'mat3',
|
|
22
|
+
'FLOAT_MAT4': 'mat4',
|
|
23
|
+
|
|
24
|
+
'SAMPLER_2D': 'sampler2D'
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const mapType = function(gl, type) {
|
|
28
|
+
if(!GL_TABLE) {
|
|
29
|
+
const typeNames = Object.keys(GL_TO_GLSL_TYPES);
|
|
30
|
+
GL_TABLE = {};
|
|
31
|
+
for(let i = 0; i < typeNames.length; ++i) {
|
|
32
|
+
const tn = typeNames[i];
|
|
33
|
+
GL_TABLE[ gl[tn] ] = GL_TO_GLSL_TYPES[tn];
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return GL_TABLE[type];
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
export {
|
|
42
|
+
mapType
|
|
43
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createShader
|
|
3
|
+
} from './shader.js';
|
|
4
|
+
import {
|
|
5
|
+
mapSize
|
|
6
|
+
} from './mapSize.js';
|
|
7
|
+
import {
|
|
8
|
+
mapType
|
|
9
|
+
} from './mapType.js';
|
|
10
|
+
|
|
11
|
+
// 创建程序
|
|
12
|
+
function createProgram(gl, vertexSrc, fragmentSrc) {
|
|
13
|
+
// 创建顶点着色器
|
|
14
|
+
const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexSrc);
|
|
15
|
+
// 创建片段着色器
|
|
16
|
+
const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentSrc);
|
|
17
|
+
|
|
18
|
+
const program = gl.createProgram() // 创建一个程序
|
|
19
|
+
gl.attachShader(program, vertexShader) // 添加顶点着色器
|
|
20
|
+
gl.attachShader(program, fragmentShader) // 添加片元着色器
|
|
21
|
+
gl.linkProgram(program) // 连接 program 中的着色器
|
|
22
|
+
|
|
23
|
+
// 检查程序链接状态
|
|
24
|
+
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
25
|
+
console.error('PError: Could not initialize shader.');
|
|
26
|
+
console.error('gl.VALIDATE_STATUS', gl.getProgramParameter(program, gl.VALIDATE_STATUS));
|
|
27
|
+
console.error('gl.getError()', gl.getError());
|
|
28
|
+
|
|
29
|
+
// if there is a program info log, log it
|
|
30
|
+
if (gl.getProgramInfoLog(program) !== '') {
|
|
31
|
+
console.warn('Warning: gl.getProgramInfoLog()', gl.getProgramInfoLog(program));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
gl.deleteProgram(program);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
useProgram(gl, program);
|
|
38
|
+
|
|
39
|
+
// clean up some shaders
|
|
40
|
+
gl.deleteShader(vertexShader);
|
|
41
|
+
gl.deleteShader(fragmentShader);
|
|
42
|
+
|
|
43
|
+
const attrs = extractAttributes(gl, program);
|
|
44
|
+
const uniforms = extractUniforms(gl, program);
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
program,
|
|
48
|
+
attrs,
|
|
49
|
+
uniforms
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// 采用program
|
|
54
|
+
function useProgram(gl, program) {
|
|
55
|
+
return gl.useProgram(program); // 告诉 webgl 用这个 program 进行渲染
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function extractAttributes(gl, program) {
|
|
59
|
+
const attributes = {};
|
|
60
|
+
|
|
61
|
+
const count = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
|
|
62
|
+
|
|
63
|
+
for (let i = 0; i < count; i++){
|
|
64
|
+
const attribData = gl.getActiveAttrib(program, i);
|
|
65
|
+
const type = mapType(gl, attribData.type);
|
|
66
|
+
attributes[attribData.name] = {
|
|
67
|
+
attribData,
|
|
68
|
+
size: mapSize(type),
|
|
69
|
+
type,
|
|
70
|
+
location: gl.getAttribLocation(program, attribData.name),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return attributes;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function extractUniforms(gl, program) {
|
|
78
|
+
const uniforms = {};
|
|
79
|
+
|
|
80
|
+
const count = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
|
|
81
|
+
|
|
82
|
+
for (let i = 0; i < count; i++) {
|
|
83
|
+
const uniformData = gl.getActiveUniform(program, i);
|
|
84
|
+
const name = uniformData.name.replace(/\[.*?\]/, "");
|
|
85
|
+
const type = mapType(gl, uniformData.type );
|
|
86
|
+
|
|
87
|
+
uniforms[name] = {
|
|
88
|
+
uniformData,
|
|
89
|
+
type: type,
|
|
90
|
+
size: uniformData.size,
|
|
91
|
+
location: gl.getUniformLocation(program, name),
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return uniforms;
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
// 把缓冲区的值写入变量
|
|
100
|
+
// size: 组成数量,必须是1,2,3或4. 每个单元由多少个数组成
|
|
101
|
+
// strip: 步长 数组中一行长度,0 表示数据是紧密的没有空隙,让OpenGL决定具体步长
|
|
102
|
+
// offset: 字节偏移量,必须是类型的字节长度的倍数。
|
|
103
|
+
// dataType: 每个元素的数据类型
|
|
104
|
+
function writeVertexAttrib(gl, buffer, attr, size=2,strip=0,offset=0,dataType=gl.FLOAT) {
|
|
105
|
+
gl.bindBuffer(buffer.type, buffer.buffer);
|
|
106
|
+
gl.vertexAttribPointer( // 告诉 OpenGL 如何从 Buffer 中获取数据
|
|
107
|
+
attr.location, // 顶点属性的索引
|
|
108
|
+
size, // 组成数量,必须是1,2,3或4。我们只提供了 x 和 y
|
|
109
|
+
dataType,
|
|
110
|
+
false, // 是否归一化到特定的范围,对 FLOAT 类型数据设置无效
|
|
111
|
+
strip * buffer.unitSize,
|
|
112
|
+
offset
|
|
113
|
+
)
|
|
114
|
+
gl.enableVertexAttribArray(attr.location);
|
|
115
|
+
return buffer;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function disableVertexAttribArray(gl, attr) {
|
|
119
|
+
return gl.disableVertexAttribArray(attr.location);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function getAttribLocation(gl, program, name) {
|
|
123
|
+
return gl.getAttribLocation(program, name);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function getUniformLocation(gl, program, name) {
|
|
127
|
+
return gl.getUniformLocation(program, name);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export {
|
|
131
|
+
createProgram,
|
|
132
|
+
useProgram,
|
|
133
|
+
getAttribLocation,
|
|
134
|
+
getUniformLocation,
|
|
135
|
+
extractAttributes,
|
|
136
|
+
extractUniforms,
|
|
137
|
+
writeVertexAttrib,
|
|
138
|
+
disableVertexAttribArray
|
|
139
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// 生成着色器
|
|
2
|
+
// type: gl.VERTEX_SHADER 顶点着色器 , gl.FRAGMENT_SHADER 片段着色器
|
|
3
|
+
// src: 着色器代码
|
|
4
|
+
function createShader(gl, type, src) {
|
|
5
|
+
const shader = gl.createShader(type) // 创建一个顶点着色器
|
|
6
|
+
gl.shaderSource(shader, src); // 编写顶点着色器代码
|
|
7
|
+
gl.compileShader(shader); // 编译着色器
|
|
8
|
+
|
|
9
|
+
return shader;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export {
|
|
13
|
+
createShader
|
|
14
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
|
|
2
|
+
// 生成纹理
|
|
3
|
+
function create2DTexture(gl) {
|
|
4
|
+
const texture = gl.createTexture();
|
|
5
|
+
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1) // 图像反转Y轴
|
|
6
|
+
gl.activeTexture(gl.TEXTURE0) // 激活纹理单元
|
|
7
|
+
gl.bindTexture(gl.TEXTURE_2D, texture) // 绑定纹理对象
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) // 放大处理方式
|
|
11
|
+
gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) // 缩小处理方式
|
|
12
|
+
gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) // 水平平铺方式
|
|
13
|
+
gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) // 竖直平铺方式
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
return texture;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// 创建图片纹理
|
|
20
|
+
function createImgTexture(gl, img) {
|
|
21
|
+
const texture = create2DTexture(gl);
|
|
22
|
+
|
|
23
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img) // 配置纹理图像
|
|
24
|
+
return {
|
|
25
|
+
texture
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// 用像素值来绘制纹理
|
|
30
|
+
function createDataTexture(gl, pixels) {
|
|
31
|
+
const data = new Uint8Array(pixels.data || pixels);
|
|
32
|
+
|
|
33
|
+
const texture = create2DTexture(gl);
|
|
34
|
+
|
|
35
|
+
gl.texImage2D(
|
|
36
|
+
gl.TEXTURE_2D, // 纹理目标
|
|
37
|
+
0, // 细节级别,指定详细级别。0 级是基本图像等级,n 级是第 n 个金字塔简化级。
|
|
38
|
+
gl.RGBA, // 纹理内部格式
|
|
39
|
+
pixels.width || 1, // 指定纹理的宽度
|
|
40
|
+
pixels.height || 1, // 指定纹理的高度
|
|
41
|
+
0, // 指定纹理的边框宽度。必须为 0。
|
|
42
|
+
gl.RGBA, // 源图像数据格式
|
|
43
|
+
gl.UNSIGNED_BYTE, // 纹理数据类型
|
|
44
|
+
data // 数据
|
|
45
|
+
);
|
|
46
|
+
return {
|
|
47
|
+
texture
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// 删除纹理
|
|
52
|
+
function deleteTexture(gl, texture) {
|
|
53
|
+
return gl.deleteTexture(texture);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export {
|
|
57
|
+
create2DTexture,
|
|
58
|
+
createImgTexture,
|
|
59
|
+
createDataTexture,
|
|
60
|
+
deleteTexture
|
|
61
|
+
}
|