@thi.ng/webgl 6.6.10 → 6.6.12

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/buffer.js CHANGED
@@ -1,143 +1,161 @@
1
- import { BIT_SHIFTS, asGLType, typedArrayType, } from "@thi.ng/api/typedarray";
2
- import { DrawMode, } from "./api/model.js";
1
+ import {
2
+ BIT_SHIFTS,
3
+ asGLType,
4
+ typedArrayType
5
+ } from "@thi.ng/api/typedarray";
6
+ import {
7
+ DrawMode
8
+ } from "./api/model.js";
3
9
  import { isGL2Context } from "./checks.js";
4
10
  import { error } from "./error.js";
5
- export class WebGLArrayBuffer {
6
- gl;
7
- buffer;
8
- target;
9
- mode;
10
- data;
11
- constructor(gl, data, target = gl.ARRAY_BUFFER, mode = gl.STATIC_DRAW, retain = false) {
12
- this.gl = gl;
13
- this.buffer = gl.createBuffer() || error("error creating WebGL buffer");
14
- this.target = target;
15
- this.mode = mode;
16
- if (data) {
17
- this.set(data);
18
- if (retain)
19
- this.data = data;
20
- }
11
+ class WebGLArrayBuffer {
12
+ gl;
13
+ buffer;
14
+ target;
15
+ mode;
16
+ data;
17
+ constructor(gl, data, target = gl.ARRAY_BUFFER, mode = gl.STATIC_DRAW, retain = false) {
18
+ this.gl = gl;
19
+ this.buffer = gl.createBuffer() || error("error creating WebGL buffer");
20
+ this.target = target;
21
+ this.mode = mode;
22
+ if (data) {
23
+ this.set(data);
24
+ if (retain)
25
+ this.data = data;
21
26
  }
22
- bind() {
23
- this.gl.bindBuffer(this.target, this.buffer);
24
- return true;
27
+ }
28
+ bind() {
29
+ this.gl.bindBuffer(this.target, this.buffer);
30
+ return true;
31
+ }
32
+ unbind() {
33
+ this.gl.bindBuffer(this.target, null);
34
+ return true;
35
+ }
36
+ release() {
37
+ if (this.buffer) {
38
+ this.gl.deleteBuffer(this.buffer);
39
+ delete this.buffer;
25
40
  }
26
- unbind() {
27
- this.gl.bindBuffer(this.target, null);
28
- return true;
29
- }
30
- release() {
31
- if (this.buffer) {
32
- this.gl.deleteBuffer(this.buffer);
33
- delete this.buffer;
34
- }
35
- return true;
36
- }
37
- /**
38
- * Re-applies retained data (from ctor arg) using
39
- * {@link WebGLArrayBuffer.set}. Presumably the underlying data has been
40
- * updated elsewhere, but needs to be reflected to WebGL.
41
- *
42
- * @remarks
43
- * If no data is retained, this method is a no-op.
44
- */
45
- update() {
46
- if (this.data)
47
- this.set(this.data);
48
- }
49
- set(data, mode = this.mode) {
50
- this.bind();
51
- this.gl.bufferData(this.target, data, mode);
52
- if (this.data)
53
- this.data = data;
54
- }
55
- setChunk(data, byteOffset = 0) {
56
- this.bind();
57
- this.gl.bufferSubData(this.target, byteOffset, data);
58
- if (this.data) {
59
- this.data.set(data, byteOffset >>> BIT_SHIFTS[typedArrayType(data)]);
60
- }
41
+ return true;
42
+ }
43
+ /**
44
+ * Re-applies retained data (from ctor arg) using
45
+ * {@link WebGLArrayBuffer.set}. Presumably the underlying data has been
46
+ * updated elsewhere, but needs to be reflected to WebGL.
47
+ *
48
+ * @remarks
49
+ * If no data is retained, this method is a no-op.
50
+ */
51
+ update() {
52
+ if (this.data)
53
+ this.set(this.data);
54
+ }
55
+ set(data, mode = this.mode) {
56
+ this.bind();
57
+ this.gl.bufferData(this.target, data, mode);
58
+ if (this.data)
59
+ this.data = data;
60
+ }
61
+ setChunk(data, byteOffset = 0) {
62
+ this.bind();
63
+ this.gl.bufferSubData(this.target, byteOffset, data);
64
+ if (this.data) {
65
+ this.data.set(
66
+ data,
67
+ byteOffset >>> BIT_SHIFTS[typedArrayType(data)]
68
+ );
61
69
  }
70
+ }
62
71
  }
63
- export const defBuffer = (gl, data, target = gl.ARRAY_BUFFER, mode = gl.STATIC_DRAW, retain = false) => new WebGLArrayBuffer(gl, data, target, mode, retain);
64
- export const compileModel = (gl, spec, mode = gl.STATIC_DRAW) => {
65
- if (spec.attribPool) {
66
- spec.attribs = compileAttribPool(gl, spec.attribPool, undefined, gl.ARRAY_BUFFER, mode);
67
- }
68
- else {
69
- compileAttribs(gl, spec.attribs, mode);
70
- }
71
- spec.instances && compileAttribs(gl, spec.instances.attribs, mode);
72
- compileIndices(gl, spec.indices, mode);
73
- spec.mode == null && (spec.mode = DrawMode.TRIANGLES);
74
- // TODO auto-create VAO & inject into model spec?
75
- return spec;
72
+ const defBuffer = (gl, data, target = gl.ARRAY_BUFFER, mode = gl.STATIC_DRAW, retain = false) => new WebGLArrayBuffer(gl, data, target, mode, retain);
73
+ const compileModel = (gl, spec, mode = gl.STATIC_DRAW) => {
74
+ if (spec.attribPool) {
75
+ spec.attribs = compileAttribPool(
76
+ gl,
77
+ spec.attribPool,
78
+ void 0,
79
+ gl.ARRAY_BUFFER,
80
+ mode
81
+ );
82
+ } else {
83
+ compileAttribs(gl, spec.attribs, mode);
84
+ }
85
+ spec.instances && compileAttribs(gl, spec.instances.attribs, mode);
86
+ compileIndices(gl, spec.indices, mode);
87
+ spec.mode == null && (spec.mode = DrawMode.TRIANGLES);
88
+ return spec;
76
89
  };
77
90
  const initBuffer = (gl, src, type, mode) => {
78
- if (src.buffer) {
79
- src.data && src.buffer.set(src.data);
80
- }
81
- else {
82
- src.buffer = new WebGLArrayBuffer(gl, src.data, type, mode, src.retain);
83
- }
91
+ if (src.buffer) {
92
+ src.data && src.buffer.set(src.data);
93
+ } else {
94
+ src.buffer = new WebGLArrayBuffer(gl, src.data, type, mode, src.retain);
95
+ }
84
96
  };
85
97
  const compileAttribs = (gl, attribs, mode) => {
86
- if (attribs) {
87
- for (let id in attribs) {
88
- initBuffer(gl, attribs[id], gl.ARRAY_BUFFER, mode);
89
- }
98
+ if (attribs) {
99
+ for (let id in attribs) {
100
+ initBuffer(gl, attribs[id], gl.ARRAY_BUFFER, mode);
90
101
  }
91
- return attribs;
102
+ }
103
+ return attribs;
92
104
  };
93
- export const compileIndices = (gl, index, mode = gl.STATIC_DRAW) => {
94
- if (index) {
95
- initBuffer(gl, index, gl.ELEMENT_ARRAY_BUFFER, mode);
96
- }
97
- return index;
105
+ const compileIndices = (gl, index, mode = gl.STATIC_DRAW) => {
106
+ if (index) {
107
+ initBuffer(gl, index, gl.ELEMENT_ARRAY_BUFFER, mode);
108
+ }
109
+ return index;
98
110
  };
99
- export const compileVAO = (gl, spec) => {
100
- if (spec.shader) {
101
- const isGL2 = isGL2Context(gl);
102
- const ext = !isGL2 ? gl.getExtension("OES_vertex_array_object") : null;
103
- if (isGL2 || ext) {
104
- let vao;
105
- if (isGL2) {
106
- vao = gl.createVertexArray();
107
- gl.bindVertexArray(vao);
108
- }
109
- else {
110
- vao = ext.createVertexArrayOES();
111
- ext.bindVertexArrayOES(vao);
112
- }
113
- !!vao && error("error creating VAO");
114
- spec.shader.bindAttribs(spec.attribs);
115
- if (spec.indices) {
116
- spec.indices.buffer.bind();
117
- }
118
- spec.shader.unbind(null);
119
- if (isGL2) {
120
- gl.bindVertexArray(null);
121
- }
122
- else {
123
- ext.bindVertexArrayOES(null);
124
- }
125
- return vao;
126
- }
111
+ const compileVAO = (gl, spec) => {
112
+ if (spec.shader) {
113
+ const isGL2 = isGL2Context(gl);
114
+ const ext = !isGL2 ? gl.getExtension("OES_vertex_array_object") : null;
115
+ if (isGL2 || ext) {
116
+ let vao;
117
+ if (isGL2) {
118
+ vao = gl.createVertexArray();
119
+ gl.bindVertexArray(vao);
120
+ } else {
121
+ vao = ext.createVertexArrayOES();
122
+ ext.bindVertexArrayOES(vao);
123
+ }
124
+ !!vao && error("error creating VAO");
125
+ spec.shader.bindAttribs(spec.attribs);
126
+ if (spec.indices) {
127
+ spec.indices.buffer.bind();
128
+ }
129
+ spec.shader.unbind(null);
130
+ if (isGL2) {
131
+ gl.bindVertexArray(null);
132
+ } else {
133
+ ext.bindVertexArrayOES(null);
134
+ }
135
+ return vao;
127
136
  }
137
+ }
128
138
  };
129
- export const compileAttribPool = (gl, pool, ids, target = gl.ARRAY_BUFFER, mode = gl.STATIC_DRAW) => {
130
- const buf = defBuffer(gl, pool.bytes(), target, mode);
131
- const spec = {};
132
- for (let id of ids || Object.keys(pool.specs)) {
133
- const attr = pool.specs[id];
134
- spec[id] = {
135
- buffer: buf,
136
- size: attr.size,
137
- type: asGLType(attr.type),
138
- stride: pool.byteStride,
139
- offset: attr.byteOffset,
140
- };
141
- }
142
- return spec;
139
+ const compileAttribPool = (gl, pool, ids, target = gl.ARRAY_BUFFER, mode = gl.STATIC_DRAW) => {
140
+ const buf = defBuffer(gl, pool.bytes(), target, mode);
141
+ const spec = {};
142
+ for (let id of ids || Object.keys(pool.specs)) {
143
+ const attr = pool.specs[id];
144
+ spec[id] = {
145
+ buffer: buf,
146
+ size: attr.size,
147
+ type: asGLType(attr.type),
148
+ stride: pool.byteStride,
149
+ offset: attr.byteOffset
150
+ };
151
+ }
152
+ return spec;
153
+ };
154
+ export {
155
+ WebGLArrayBuffer,
156
+ compileAttribPool,
157
+ compileIndices,
158
+ compileModel,
159
+ compileVAO,
160
+ defBuffer
143
161
  };
package/canvas.js CHANGED
@@ -2,71 +2,63 @@ import { adaptDPI } from "@thi.ng/adapt-dpi";
2
2
  import { isString } from "@thi.ng/checks/is-string";
3
3
  import { error } from "./error.js";
4
4
  const defaultOpts = {
5
- alpha: true,
6
- antialias: true,
7
- depth: true,
8
- premultipliedAlpha: true,
9
- preserveDrawingBuffer: false,
10
- stencil: false,
5
+ alpha: true,
6
+ antialias: true,
7
+ depth: true,
8
+ premultipliedAlpha: true,
9
+ preserveDrawingBuffer: false,
10
+ stencil: false
11
11
  };
12
- export const glCanvas = (opts = {}) => {
13
- const canvas = opts.canvas
14
- ? isString(opts.canvas)
15
- ? document.getElementById(opts.canvas)
16
- : opts.canvas
17
- : document.createElement("canvas");
18
- opts.width && (canvas.width = opts.width);
19
- opts.height && (canvas.height = opts.height);
20
- opts.autoScale !== false && adaptDPI(canvas, canvas.width, canvas.height);
21
- opts.parent && opts.parent.appendChild(canvas);
22
- const gl = canvas.getContext(opts.version === 2 ? "webgl2" : "webgl", {
23
- ...defaultOpts,
24
- ...opts.opts,
25
- });
26
- if (!gl) {
27
- error("WebGL unavailable");
12
+ const glCanvas = (opts = {}) => {
13
+ const canvas = opts.canvas ? isString(opts.canvas) ? document.getElementById(opts.canvas) : opts.canvas : document.createElement("canvas");
14
+ opts.width && (canvas.width = opts.width);
15
+ opts.height && (canvas.height = opts.height);
16
+ opts.autoScale !== false && adaptDPI(canvas, canvas.width, canvas.height);
17
+ opts.parent && opts.parent.appendChild(canvas);
18
+ const gl = canvas.getContext(
19
+ opts.version === 2 ? "webgl2" : "webgl",
20
+ {
21
+ ...defaultOpts,
22
+ ...opts.opts
28
23
  }
29
- opts.onContextLost &&
30
- canvas.addEventListener("webglcontextlost", opts.onContextLost);
31
- return {
24
+ );
25
+ if (!gl) {
26
+ error("WebGL unavailable");
27
+ }
28
+ opts.onContextLost && canvas.addEventListener("webglcontextlost", opts.onContextLost);
29
+ return {
30
+ canvas,
31
+ gl,
32
+ ext: getExtensions(gl, opts.ext),
33
+ resize: (width, height) => {
34
+ adaptDPI(
32
35
  canvas,
33
- gl,
34
- ext: getExtensions(gl, opts.ext),
35
- resize: (width, height) => {
36
- adaptDPI(canvas, width, height, opts.autoScale !== false ? window.devicePixelRatio : 1);
37
- gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
38
- },
39
- };
36
+ width,
37
+ height,
38
+ opts.autoScale !== false ? window.devicePixelRatio : 1
39
+ );
40
+ gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
41
+ }
42
+ };
40
43
  };
41
- export const getExtensions = (gl, ids, required = true) => {
42
- const ext = {};
43
- if (ids) {
44
- for (let id of ids) {
45
- ext[id] = gl.getExtension(id);
46
- required && !ext[id] && error(`extension ${id} not available`);
47
- }
44
+ const getExtensions = (gl, ids, required = true) => {
45
+ const ext = {};
46
+ if (ids) {
47
+ for (let id of ids) {
48
+ ext[id] = gl.getExtension(id);
49
+ required && !ext[id] && error(`extension ${id} not available`);
48
50
  }
49
- return ext;
51
+ }
52
+ return ext;
53
+ };
54
+ const clearCanvas = (gl, [r, g, b, a], depth = true) => {
55
+ gl.clearColor(r, g, b, a != null ? a : 1);
56
+ gl.clear(gl.COLOR_BUFFER_BIT | (depth ? gl.DEPTH_BUFFER_BIT : 0));
50
57
  };
51
- /**
52
- * Sets clear color to given RGB(A) `color` and clears viewport's
53
- * `COLOR_BUFFER_BIT` and (by default) also `DEPTH_BUFFER_BIT`.
54
- *
55
- * @remarks
56
- * If the given color vector only contains RGB values, alpha will default to
57
- * 1.0.
58
- *
59
- * @param gl
60
- * @param color
61
- * @param depth
62
- */
63
- export const clearCanvas = (gl, [r, g, b, a], depth = true) => {
64
- gl.clearColor(r, g, b, a != null ? a : 1);
65
- gl.clear(gl.COLOR_BUFFER_BIT | (depth ? gl.DEPTH_BUFFER_BIT : 0));
58
+ const defaultViewport = (gl) => gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
59
+ export {
60
+ clearCanvas,
61
+ defaultViewport,
62
+ getExtensions,
63
+ glCanvas
66
64
  };
67
- /**
68
- * Resets viewport to full drawing buffer size.
69
- *
70
- * @param gl
71
- */
72
- export const defaultViewport = (gl) => gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
package/checks.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { TextureType } from "./api/texture.js";
2
- export const isGL2Context = (gl) => typeof WebGL2RenderingContext !== "undefined" &&
3
- gl instanceof WebGL2RenderingContext;
4
- export const isFloatTexture = (tex) => tex.type === TextureType.FLOAT ||
5
- tex.type === TextureType.HALF_FLOAT ||
6
- tex.type === TextureType.HALF_FLOAT_OES ||
7
- tex.type === TextureType.FLOAT_32_UNSIGNED_INT_24_8_REV;
2
+ const isGL2Context = (gl) => typeof WebGL2RenderingContext !== "undefined" && gl instanceof WebGL2RenderingContext;
3
+ const isFloatTexture = (tex) => tex.type === TextureType.FLOAT || tex.type === TextureType.HALF_FLOAT || tex.type === TextureType.HALF_FLOAT_OES || tex.type === TextureType.FLOAT_32_UNSIGNED_INT_24_8_REV;
4
+ export {
5
+ isFloatTexture,
6
+ isGL2Context
7
+ };
package/draw.js CHANGED
@@ -2,77 +2,92 @@ import { isArray } from "@thi.ng/checks/is-array";
2
2
  import { isGL2Context } from "./checks.js";
3
3
  import { error } from "./error.js";
4
4
  import { bindTextures, unbindTextures } from "./texture.js";
5
- export const draw = (specs, opts = {}) => {
6
- const _specs = isArray(specs) ? specs : [specs];
7
- for (let i = 0, n = _specs.length; i < n; i++) {
8
- const spec = _specs[i];
9
- const indices = spec.indices;
10
- const gl = spec.shader.gl;
11
- opts.bindTex !== false && bindTextures(spec.textures);
12
- opts.shaderState !== false && spec.shader.prepareState();
13
- opts.bindShader !== false && spec.shader.bind(spec);
14
- if (indices && indices.buffer) {
15
- indices.buffer.bind();
16
- if (spec.instances) {
17
- drawInstanced(gl, spec);
18
- }
19
- else {
20
- gl.drawElements(spec.mode, spec.num, indices.data instanceof Uint32Array
21
- ? gl.UNSIGNED_INT
22
- : gl.UNSIGNED_SHORT, 0);
23
- }
24
- }
25
- else {
26
- if (spec.instances) {
27
- drawInstanced(gl, spec);
28
- }
29
- else {
30
- gl.drawArrays(spec.mode, 0, spec.num);
31
- }
32
- }
33
- opts.unbindShader !== false && spec.shader.unbind(null);
34
- opts.unbindTex && unbindTextures(spec.textures);
5
+ const draw = (specs, opts = {}) => {
6
+ const _specs = isArray(specs) ? specs : [specs];
7
+ for (let i = 0, n = _specs.length; i < n; i++) {
8
+ const spec = _specs[i];
9
+ const indices = spec.indices;
10
+ const gl = spec.shader.gl;
11
+ opts.bindTex !== false && bindTextures(spec.textures);
12
+ opts.shaderState !== false && spec.shader.prepareState();
13
+ opts.bindShader !== false && spec.shader.bind(spec);
14
+ if (indices && indices.buffer) {
15
+ indices.buffer.bind();
16
+ if (spec.instances) {
17
+ drawInstanced(gl, spec);
18
+ } else {
19
+ gl.drawElements(
20
+ spec.mode,
21
+ spec.num,
22
+ indices.data instanceof Uint32Array ? gl.UNSIGNED_INT : gl.UNSIGNED_SHORT,
23
+ 0
24
+ );
25
+ }
26
+ } else {
27
+ if (spec.instances) {
28
+ drawInstanced(gl, spec);
29
+ } else {
30
+ gl.drawArrays(spec.mode, 0, spec.num);
31
+ }
35
32
  }
33
+ opts.unbindShader !== false && spec.shader.unbind(null);
34
+ opts.unbindTex && unbindTextures(spec.textures);
35
+ }
36
36
  };
37
37
  const drawInstanced = (gl, spec) => {
38
- const isGL2 = isGL2Context(gl);
39
- const ext = !isGL2 ? gl.getExtension("ANGLE_instanced_arrays") : undefined;
40
- if (!(isGL2 || ext)) {
41
- error("instancing not supported");
38
+ const isGL2 = isGL2Context(gl);
39
+ const ext = !isGL2 ? gl.getExtension("ANGLE_instanced_arrays") : void 0;
40
+ if (!(isGL2 || ext)) {
41
+ error("instancing not supported");
42
+ }
43
+ const sattribs = spec.shader.attribs;
44
+ const iattribs = spec.instances.attribs;
45
+ spec.shader.bindAttribs(iattribs);
46
+ for (let id in iattribs) {
47
+ const attr = sattribs[id];
48
+ if (attr) {
49
+ let div = iattribs[id].divisor;
50
+ div = div !== void 0 ? div : 1;
51
+ isGL2 ? gl.vertexAttribDivisor(
52
+ attr.loc,
53
+ div
54
+ ) : ext.vertexAttribDivisorANGLE(attr.loc, div);
42
55
  }
43
- const sattribs = spec.shader.attribs;
44
- const iattribs = spec.instances.attribs;
45
- spec.shader.bindAttribs(iattribs);
46
- for (let id in iattribs) {
47
- const attr = sattribs[id];
48
- if (attr) {
49
- let div = iattribs[id].divisor;
50
- div = div !== undefined ? div : 1;
51
- isGL2
52
- ? gl.vertexAttribDivisor(attr.loc, div)
53
- : ext.vertexAttribDivisorANGLE(attr.loc, div);
54
- }
55
- }
56
- if (spec.indices) {
57
- const type = spec.indices.data instanceof Uint32Array
58
- ? gl.UNSIGNED_INT
59
- : gl.UNSIGNED_SHORT;
60
- isGL2
61
- ? gl.drawElementsInstanced(spec.mode, spec.num, type, 0, spec.instances.num)
62
- : ext.drawElementsInstancedANGLE(spec.mode, spec.num, type, 0, spec.instances.num);
63
- }
64
- else {
65
- isGL2
66
- ? gl.drawArraysInstanced(spec.mode, 0, spec.num, spec.instances.num)
67
- : ext.drawArraysInstancedANGLE(spec.mode, 0, spec.num, spec.instances.num);
68
- }
69
- // reset attrib divisors to allow non-instanced draws later on
70
- for (let id in iattribs) {
71
- const attr = sattribs[id];
72
- attr &&
73
- (isGL2
74
- ? gl.vertexAttribDivisor(attr.loc, 0)
75
- : ext.vertexAttribDivisorANGLE(attr.loc, 0));
76
- }
77
- spec.shader.unbind(null);
56
+ }
57
+ if (spec.indices) {
58
+ const type = spec.indices.data instanceof Uint32Array ? gl.UNSIGNED_INT : gl.UNSIGNED_SHORT;
59
+ isGL2 ? gl.drawElementsInstanced(
60
+ spec.mode,
61
+ spec.num,
62
+ type,
63
+ 0,
64
+ spec.instances.num
65
+ ) : ext.drawElementsInstancedANGLE(
66
+ spec.mode,
67
+ spec.num,
68
+ type,
69
+ 0,
70
+ spec.instances.num
71
+ );
72
+ } else {
73
+ isGL2 ? gl.drawArraysInstanced(
74
+ spec.mode,
75
+ 0,
76
+ spec.num,
77
+ spec.instances.num
78
+ ) : ext.drawArraysInstancedANGLE(
79
+ spec.mode,
80
+ 0,
81
+ spec.num,
82
+ spec.instances.num
83
+ );
84
+ }
85
+ for (let id in iattribs) {
86
+ const attr = sattribs[id];
87
+ attr && (isGL2 ? gl.vertexAttribDivisor(attr.loc, 0) : ext.vertexAttribDivisorANGLE(attr.loc, 0));
88
+ }
89
+ spec.shader.unbind(null);
90
+ };
91
+ export {
92
+ draw
78
93
  };
package/error.js CHANGED
@@ -1,5 +1,9 @@
1
1
  import { defError } from "@thi.ng/errors/deferror";
2
- export const WebGLError = defError(() => "WebGL");
3
- export const error = (msg) => {
4
- throw new WebGLError(msg);
2
+ const WebGLError = defError(() => "WebGL");
3
+ const error = (msg) => {
4
+ throw new WebGLError(msg);
5
+ };
6
+ export {
7
+ WebGLError,
8
+ error
5
9
  };