@gjsify/webgl 0.3.12 → 0.3.14

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.
Files changed (55) hide show
  1. package/lib/esm/conformance/attribs.spec.js +312 -293
  2. package/lib/esm/conformance/buffers.spec.js +217 -200
  3. package/lib/esm/conformance/context.spec.js +295 -295
  4. package/lib/esm/conformance/programs.spec.js +458 -445
  5. package/lib/esm/conformance/rendering-basic.spec.js +134 -128
  6. package/lib/esm/conformance/rendering.spec.js +502 -400
  7. package/lib/esm/conformance/setup.js +42 -31
  8. package/lib/esm/conformance/state.spec.js +360 -343
  9. package/lib/esm/conformance/textures.spec.js +330 -338
  10. package/lib/esm/conformance/uniforms.spec.js +465 -309
  11. package/lib/esm/conformance-test.js +24 -22
  12. package/lib/esm/extensions/ext-blend-minmax.js +16 -16
  13. package/lib/esm/extensions/ext-color-buffer-float.js +10 -11
  14. package/lib/esm/extensions/ext-color-buffer-half-float.js +10 -11
  15. package/lib/esm/extensions/ext-texture-filter-anisotropic.js +16 -16
  16. package/lib/esm/extensions/oes-element-index-unit.js +11 -12
  17. package/lib/esm/extensions/oes-standard-derivatives.js +15 -15
  18. package/lib/esm/extensions/oes-texture-float-linear.js +11 -12
  19. package/lib/esm/extensions/oes-texture-float.js +11 -12
  20. package/lib/esm/extensions/oes-texture-half-float.js +17 -17
  21. package/lib/esm/extensions/stackgl-destroy-context.js +10 -10
  22. package/lib/esm/extensions/stackgl-resize-drawing-buffer.js +10 -10
  23. package/lib/esm/html-canvas-element.js +64 -64
  24. package/lib/esm/index.js +29 -26
  25. package/lib/esm/linkable.js +49 -49
  26. package/lib/esm/test-utils.js +158 -107
  27. package/lib/esm/test.js +8 -4
  28. package/lib/esm/types/index.js +5 -5
  29. package/lib/esm/utils.js +164 -187
  30. package/lib/esm/webgl-active-info.js +10 -9
  31. package/lib/esm/webgl-bridge.js +162 -147
  32. package/lib/esm/webgl-buffer.js +17 -15
  33. package/lib/esm/webgl-context-attributes.js +23 -22
  34. package/lib/esm/webgl-context-base.js +3039 -3351
  35. package/lib/esm/webgl-drawing-buffer-wrapper.js +10 -9
  36. package/lib/esm/webgl-framebuffer.js +108 -106
  37. package/lib/esm/webgl-program.js +25 -23
  38. package/lib/esm/webgl-query.js +15 -13
  39. package/lib/esm/webgl-renderbuffer.js +23 -21
  40. package/lib/esm/webgl-rendering-context.js +173 -187
  41. package/lib/esm/webgl-sampler.js +15 -13
  42. package/lib/esm/webgl-shader-precision-format.js +10 -9
  43. package/lib/esm/webgl-shader.js +23 -21
  44. package/lib/esm/webgl-sync.js +15 -13
  45. package/lib/esm/webgl-texture-unit.js +12 -11
  46. package/lib/esm/webgl-texture.js +21 -19
  47. package/lib/esm/webgl-transform-feedback.js +15 -13
  48. package/lib/esm/webgl-uniform-location.js +14 -13
  49. package/lib/esm/webgl-vertex-array-object.js +20 -18
  50. package/lib/esm/webgl-vertex-attribute.js +149 -145
  51. package/lib/esm/webgl1.spec.js +1039 -650
  52. package/lib/esm/webgl2-rendering-context.js +1210 -1273
  53. package/lib/esm/webgl2.spec.js +1284 -1252
  54. package/package.json +9 -9
  55. package/lib/esm/@types/glsl-tokenizer/index.d.js +0 -0
@@ -1,14 +1,8 @@
1
- import { describe, it, expect, beforeEach, on } from "@gjsify/unit";
2
- import {
3
- makeProgram,
4
- drawTriangle,
5
- makeTestFBO,
6
- destroyTestFBO,
7
- makeTestFBOWithDepth,
8
- destroyTestFBOWithDepth,
9
- pixelClose
10
- } from "../test-utils.js";
1
+ import { destroyTestFBO, destroyTestFBOWithDepth, drawTriangle, makeProgram, makeTestFBO, makeTestFBOWithDepth, pixelClose } from "../test-utils.js";
11
2
  import { createGLSetup } from "./setup.js";
3
+ import { beforeEach, describe, expect, it, on } from "@gjsify/unit";
4
+
5
+ //#region src/ts/conformance/rendering.spec.ts
12
6
  const VS = `
13
7
  precision mediump float;
14
8
  attribute vec2 position;
@@ -22,403 +16,511 @@ const FS_COLOR = `
22
16
  uniform vec4 color;
23
17
  void main() { gl_FragColor = color; }`;
24
18
  var rendering_spec_default = async () => {
25
- await on("Display", async () => {
26
- const setup = createGLSetup();
27
- if (!setup) {
28
- console.warn("WebGL context not available \u2014 skipping conformance/rendering tests");
29
- return;
30
- }
31
- const { gl, glArea } = setup;
32
- glArea.make_current();
33
- await describe("rendering/blending", async () => {
34
- beforeEach(async () => {
35
- glArea.make_current();
36
- });
37
- const W = 2, H = 2;
38
- function runBlendTest(t) {
39
- const fbo = makeTestFBO(gl, W, H);
40
- const fsSrc = `
19
+ await on("Display", async () => {
20
+ const setup = createGLSetup();
21
+ if (!setup) {
22
+ console.warn("WebGL context not available skipping conformance/rendering tests");
23
+ return;
24
+ }
25
+ const { gl, glArea } = setup;
26
+ glArea.make_current();
27
+ await describe("rendering/blending", async () => {
28
+ beforeEach(async () => {
29
+ glArea.make_current();
30
+ });
31
+ const W = 2, H = 2;
32
+ function runBlendTest(t) {
33
+ const fbo = makeTestFBO(gl, W, H);
34
+ const fsSrc = `
41
35
  precision mediump float;
42
36
  void main() { gl_FragColor = vec4(${t.srcColor[0]},${t.srcColor[1]},${t.srcColor[2]},${t.srcColor[3]}); }`;
43
- gl.clearColor(t.dstColor[0], t.dstColor[1], t.dstColor[2], t.dstColor[3]);
44
- gl.clear(gl.COLOR_BUFFER_BIT);
45
- const prog = makeProgram(gl, VS, fsSrc);
46
- gl.useProgram(prog);
47
- gl.enable(gl.BLEND);
48
- gl.blendEquation(t.equation);
49
- gl.blendFunc(t.srcFactor, t.dstFactor);
50
- drawTriangle(gl);
51
- gl.disable(gl.BLEND);
52
- const pixels = new Uint8Array(W * H * 4);
53
- gl.readPixels(0, 0, W, H, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
54
- destroyTestFBO(gl, fbo);
55
- const expected255 = t.expected.map((v) => Math.round(v * 255));
56
- for (let i = 0; i < W * H * 4; i += 4) {
57
- if (!pixelClose(pixels.subarray(i, i + 4), expected255, 4)) {
58
- return false;
59
- }
60
- }
61
- return true;
62
- }
63
- await it("FUNC_ADD ONE ONE: dst=[0.5,0.5,0.5,1] + src=[0.5,0.5,0.5,1] = [1,1,1,1]", async () => {
64
- expect(runBlendTest({
65
- name: "ADD ONE ONE",
66
- equation: gl.FUNC_ADD,
67
- srcFactor: gl.ONE,
68
- dstFactor: gl.ONE,
69
- dstColor: [0.5, 0.5, 0.5, 1],
70
- srcColor: [0.5, 0.5, 0.5, 1],
71
- expected: [1, 1, 1, 1]
72
- })).toBe(true);
73
- expect(gl.getError()).toBe(gl.NO_ERROR);
74
- });
75
- await it("FUNC_ADD ONE ZERO: dst=[0.5,0.5,0.5,0.5] + src=[0.2,0.2,0.2,1] = [0.2,0.2,0.2,1]", async () => {
76
- expect(runBlendTest({
77
- name: "ADD ONE ZERO",
78
- equation: gl.FUNC_ADD,
79
- srcFactor: gl.ONE,
80
- dstFactor: gl.ZERO,
81
- dstColor: [0.5, 0.5, 0.5, 0.5],
82
- srcColor: [0.2, 0.2, 0.2, 1],
83
- expected: [0.2, 0.2, 0.2, 1]
84
- })).toBe(true);
85
- expect(gl.getError()).toBe(gl.NO_ERROR);
86
- });
87
- await it("FUNC_ADD ZERO SRC_COLOR: dst=[0.8,0.8,0.8,1] * src=[0.5,0.5,0.5,0.5] = [0.4,0.4,0.4,0.5]", async () => {
88
- expect(runBlendTest({
89
- name: "ADD ZERO SRC_COLOR",
90
- equation: gl.FUNC_ADD,
91
- srcFactor: gl.ZERO,
92
- dstFactor: gl.SRC_COLOR,
93
- dstColor: [0.8, 0.8, 0.8, 1],
94
- srcColor: [0.5, 0.5, 0.5, 0.5],
95
- expected: [0.4, 0.4, 0.4, 0.5]
96
- })).toBe(true);
97
- expect(gl.getError()).toBe(gl.NO_ERROR);
98
- });
99
- await it("FUNC_ADD DST_COLOR ZERO: dst=[0.8,0.8,0.8,1] src=[0.5,0.5,0.5,0.5] = [0.4,0.4,0.4,0.5]", async () => {
100
- expect(runBlendTest({
101
- name: "ADD DST_COLOR ZERO",
102
- equation: gl.FUNC_ADD,
103
- srcFactor: gl.DST_COLOR,
104
- dstFactor: gl.ZERO,
105
- dstColor: [0.8, 0.8, 0.8, 1],
106
- srcColor: [0.5, 0.5, 0.5, 0.5],
107
- expected: [0.4, 0.4, 0.4, 0.5]
108
- })).toBe(true);
109
- expect(gl.getError()).toBe(gl.NO_ERROR);
110
- });
111
- await it("FUNC_ADD SRC_ALPHA ONE_MINUS_SRC_ALPHA: alpha=0.5 blend", async () => {
112
- expect(runBlendTest({
113
- name: "ADD SRC_ALPHA ONE_MINUS_SRC_ALPHA",
114
- equation: gl.FUNC_ADD,
115
- srcFactor: gl.SRC_ALPHA,
116
- dstFactor: gl.ONE_MINUS_SRC_ALPHA,
117
- dstColor: [0.5, 0, 0.5, 1],
118
- srcColor: [0.5, 1, 0, 0.5],
119
- expected: [0.5, 0.5, 0.25, 0.75]
120
- })).toBe(true);
121
- expect(gl.getError()).toBe(gl.NO_ERROR);
122
- });
123
- });
124
- await describe("rendering/depth-buffer", async () => {
125
- beforeEach(async () => {
126
- glArea.make_current();
127
- });
128
- await it("DEPTH_TEST NOTEQUAL: both passes render because depths differ", async () => {
129
- const W = 50, H = 50;
130
- const fbo = makeTestFBOWithDepth(gl, W, H);
131
- gl.clearColor(0, 0, 0, 0);
132
- gl.clearDepth(1);
133
- gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
134
- gl.enable(gl.DEPTH_TEST);
135
- gl.depthFunc(gl.NOTEQUAL);
136
- const prog = makeProgram(gl, VS_DEPTH, FS_COLOR);
137
- gl.useProgram(prog);
138
- gl.uniform1f(gl.getUniformLocation(prog, "depth"), 0);
139
- gl.uniform4f(gl.getUniformLocation(prog, "color"), 1, 0, 0, 1);
140
- drawTriangle(gl);
141
- gl.uniform1f(gl.getUniformLocation(prog, "depth"), 1);
142
- gl.uniform4f(gl.getUniformLocation(prog, "color"), 0, 1, 0, 1);
143
- drawTriangle(gl);
144
- gl.disable(gl.DEPTH_TEST);
145
- const pixels = new Uint8Array(W * H * 4);
146
- gl.readPixels(0, 0, W, H, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
147
- destroyTestFBOWithDepth(gl, fbo);
148
- let allGreen = true;
149
- for (let i = 0; i < W * H * 4; i += 4) {
150
- if (!pixelClose(
151
- pixels.subarray(i, i + 4),
152
- [0, 255, 0, 255],
153
- 3
154
- )) {
155
- allGreen = false;
156
- break;
157
- }
158
- }
159
- expect(allGreen).toBe(true);
160
- expect(gl.getError()).toBe(gl.NO_ERROR);
161
- });
162
- await it("DEPTH_TEST LESS: closer triangle overwrites farther", async () => {
163
- const W = 20, H = 20;
164
- const fbo = makeTestFBOWithDepth(gl, W, H);
165
- gl.clearColor(0, 0, 0, 0);
166
- gl.clearDepth(1);
167
- gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
168
- gl.enable(gl.DEPTH_TEST);
169
- gl.depthFunc(gl.LESS);
170
- const prog = makeProgram(gl, VS_DEPTH, FS_COLOR);
171
- gl.useProgram(prog);
172
- gl.uniform1f(gl.getUniformLocation(prog, "depth"), 0.5);
173
- gl.uniform4f(gl.getUniformLocation(prog, "color"), 0, 0, 1, 1);
174
- drawTriangle(gl);
175
- gl.uniform1f(gl.getUniformLocation(prog, "depth"), 0.25);
176
- gl.uniform4f(gl.getUniformLocation(prog, "color"), 0, 1, 0, 1);
177
- drawTriangle(gl);
178
- gl.uniform1f(gl.getUniformLocation(prog, "depth"), 0.75);
179
- gl.uniform4f(gl.getUniformLocation(prog, "color"), 1, 0, 0, 1);
180
- drawTriangle(gl);
181
- gl.disable(gl.DEPTH_TEST);
182
- const pixels = new Uint8Array(W * H * 4);
183
- gl.readPixels(0, 0, W, H, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
184
- destroyTestFBOWithDepth(gl, fbo);
185
- let allGreen = true;
186
- for (let i = 0; i < W * H * 4; i += 4) {
187
- if (!pixelClose(
188
- pixels.subarray(i, i + 4),
189
- [0, 255, 0, 255],
190
- 3
191
- )) {
192
- allGreen = false;
193
- break;
194
- }
195
- }
196
- expect(allGreen).toBe(true);
197
- expect(gl.getError()).toBe(gl.NO_ERROR);
198
- });
199
- await it("depthMask(false) prevents depth writes", async () => {
200
- const W = 10, H = 10;
201
- const fbo = makeTestFBOWithDepth(gl, W, H);
202
- gl.clearColor(0, 0, 0, 0);
203
- gl.clearDepth(1);
204
- gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
205
- gl.enable(gl.DEPTH_TEST);
206
- gl.depthFunc(gl.LESS);
207
- const prog = makeProgram(gl, VS_DEPTH, FS_COLOR);
208
- gl.useProgram(prog);
209
- gl.depthMask(false);
210
- gl.uniform1f(gl.getUniformLocation(prog, "depth"), 0.5);
211
- gl.uniform4f(gl.getUniformLocation(prog, "color"), 1, 0, 0, 1);
212
- drawTriangle(gl);
213
- gl.depthMask(true);
214
- gl.uniform1f(gl.getUniformLocation(prog, "depth"), 0.75);
215
- gl.uniform4f(gl.getUniformLocation(prog, "color"), 0, 1, 0, 1);
216
- drawTriangle(gl);
217
- gl.disable(gl.DEPTH_TEST);
218
- const pixels = new Uint8Array(W * H * 4);
219
- gl.readPixels(0, 0, W, H, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
220
- destroyTestFBOWithDepth(gl, fbo);
221
- let allGreen = true;
222
- for (let i = 0; i < W * H * 4; i += 4) {
223
- if (!pixelClose(
224
- pixels.subarray(i, i + 4),
225
- [0, 255, 0, 255],
226
- 3
227
- )) {
228
- allGreen = false;
229
- break;
230
- }
231
- }
232
- expect(allGreen).toBe(true);
233
- expect(gl.getError()).toBe(gl.NO_ERROR);
234
- });
235
- });
236
- await describe("rendering/scissor", async () => {
237
- beforeEach(async () => {
238
- glArea.make_current();
239
- });
240
- await it("scissor test clips rendering to specified rectangle", async () => {
241
- const W = 20, H = 20;
242
- const fbo = makeTestFBO(gl, W, H);
243
- gl.clearColor(1, 0, 0, 1);
244
- gl.clear(gl.COLOR_BUFFER_BIT);
245
- gl.enable(gl.SCISSOR_TEST);
246
- gl.scissor(0, 0, W / 2, H);
247
- gl.clearColor(0, 1, 0, 1);
248
- gl.clear(gl.COLOR_BUFFER_BIT);
249
- gl.disable(gl.SCISSOR_TEST);
250
- const pixels = new Uint8Array(W * H * 4);
251
- gl.readPixels(0, 0, W, H, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
252
- destroyTestFBO(gl, fbo);
253
- let ok = true;
254
- for (let y = 0; y < H; y++) {
255
- for (let x = 0; x < W; x++) {
256
- const i = (y * W + x) * 4;
257
- const pix = pixels.subarray(i, i + 4);
258
- if (x < W / 2) {
259
- if (!pixelClose(pix, [0, 255, 0, 255])) {
260
- ok = false;
261
- break;
262
- }
263
- } else {
264
- if (!pixelClose(pix, [255, 0, 0, 255])) {
265
- ok = false;
266
- break;
267
- }
268
- }
269
- }
270
- if (!ok) break;
271
- }
272
- expect(ok).toBe(true);
273
- expect(gl.getError()).toBe(gl.NO_ERROR);
274
- });
275
- });
276
- await describe("rendering/mapbox-ansis", async () => {
277
- beforeEach(async () => {
278
- glArea.make_current();
279
- });
280
- await it("depthRange: green at range(0,0.1) survives blue at range(0.9,1) with LEQUAL", async () => {
281
- const W = 4, H = 4;
282
- const vsSrc = `
37
+ gl.clearColor(t.dstColor[0], t.dstColor[1], t.dstColor[2], t.dstColor[3]);
38
+ gl.clear(gl.COLOR_BUFFER_BIT);
39
+ const prog = makeProgram(gl, VS, fsSrc);
40
+ gl.useProgram(prog);
41
+ gl.enable(gl.BLEND);
42
+ gl.blendEquation(t.equation);
43
+ gl.blendFunc(t.srcFactor, t.dstFactor);
44
+ drawTriangle(gl);
45
+ gl.disable(gl.BLEND);
46
+ const pixels = new Uint8Array(W * H * 4);
47
+ gl.readPixels(0, 0, W, H, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
48
+ destroyTestFBO(gl, fbo);
49
+ const expected255 = t.expected.map((v) => Math.round(v * 255));
50
+ for (let i = 0; i < W * H * 4; i += 4) {
51
+ if (!pixelClose(pixels.subarray(i, i + 4), expected255, 4)) {
52
+ return false;
53
+ }
54
+ }
55
+ return true;
56
+ }
57
+ await it("FUNC_ADD ONE ONE: dst=[0.5,0.5,0.5,1] + src=[0.5,0.5,0.5,1] = [1,1,1,1]", async () => {
58
+ expect(runBlendTest({
59
+ name: "ADD ONE ONE",
60
+ equation: gl.FUNC_ADD,
61
+ srcFactor: gl.ONE,
62
+ dstFactor: gl.ONE,
63
+ dstColor: [
64
+ .5,
65
+ .5,
66
+ .5,
67
+ 1
68
+ ],
69
+ srcColor: [
70
+ .5,
71
+ .5,
72
+ .5,
73
+ 1
74
+ ],
75
+ expected: [
76
+ 1,
77
+ 1,
78
+ 1,
79
+ 1
80
+ ]
81
+ })).toBe(true);
82
+ expect(gl.getError()).toBe(gl.NO_ERROR);
83
+ });
84
+ await it("FUNC_ADD ONE ZERO: dst=[0.5,0.5,0.5,0.5] + src=[0.2,0.2,0.2,1] = [0.2,0.2,0.2,1]", async () => {
85
+ expect(runBlendTest({
86
+ name: "ADD ONE ZERO",
87
+ equation: gl.FUNC_ADD,
88
+ srcFactor: gl.ONE,
89
+ dstFactor: gl.ZERO,
90
+ dstColor: [
91
+ .5,
92
+ .5,
93
+ .5,
94
+ .5
95
+ ],
96
+ srcColor: [
97
+ .2,
98
+ .2,
99
+ .2,
100
+ 1
101
+ ],
102
+ expected: [
103
+ .2,
104
+ .2,
105
+ .2,
106
+ 1
107
+ ]
108
+ })).toBe(true);
109
+ expect(gl.getError()).toBe(gl.NO_ERROR);
110
+ });
111
+ await it("FUNC_ADD ZERO SRC_COLOR: dst=[0.8,0.8,0.8,1] * src=[0.5,0.5,0.5,0.5] = [0.4,0.4,0.4,0.5]", async () => {
112
+ expect(runBlendTest({
113
+ name: "ADD ZERO SRC_COLOR",
114
+ equation: gl.FUNC_ADD,
115
+ srcFactor: gl.ZERO,
116
+ dstFactor: gl.SRC_COLOR,
117
+ dstColor: [
118
+ .8,
119
+ .8,
120
+ .8,
121
+ 1
122
+ ],
123
+ srcColor: [
124
+ .5,
125
+ .5,
126
+ .5,
127
+ .5
128
+ ],
129
+ expected: [
130
+ .4,
131
+ .4,
132
+ .4,
133
+ .5
134
+ ]
135
+ })).toBe(true);
136
+ expect(gl.getError()).toBe(gl.NO_ERROR);
137
+ });
138
+ await it("FUNC_ADD DST_COLOR ZERO: dst=[0.8,0.8,0.8,1] src=[0.5,0.5,0.5,0.5] = [0.4,0.4,0.4,0.5]", async () => {
139
+ expect(runBlendTest({
140
+ name: "ADD DST_COLOR ZERO",
141
+ equation: gl.FUNC_ADD,
142
+ srcFactor: gl.DST_COLOR,
143
+ dstFactor: gl.ZERO,
144
+ dstColor: [
145
+ .8,
146
+ .8,
147
+ .8,
148
+ 1
149
+ ],
150
+ srcColor: [
151
+ .5,
152
+ .5,
153
+ .5,
154
+ .5
155
+ ],
156
+ expected: [
157
+ .4,
158
+ .4,
159
+ .4,
160
+ .5
161
+ ]
162
+ })).toBe(true);
163
+ expect(gl.getError()).toBe(gl.NO_ERROR);
164
+ });
165
+ await it("FUNC_ADD SRC_ALPHA ONE_MINUS_SRC_ALPHA: alpha=0.5 blend", async () => {
166
+ expect(runBlendTest({
167
+ name: "ADD SRC_ALPHA ONE_MINUS_SRC_ALPHA",
168
+ equation: gl.FUNC_ADD,
169
+ srcFactor: gl.SRC_ALPHA,
170
+ dstFactor: gl.ONE_MINUS_SRC_ALPHA,
171
+ dstColor: [
172
+ .5,
173
+ 0,
174
+ .5,
175
+ 1
176
+ ],
177
+ srcColor: [
178
+ .5,
179
+ 1,
180
+ 0,
181
+ .5
182
+ ],
183
+ expected: [
184
+ .5,
185
+ .5,
186
+ .25,
187
+ .75
188
+ ]
189
+ })).toBe(true);
190
+ expect(gl.getError()).toBe(gl.NO_ERROR);
191
+ });
192
+ });
193
+ await describe("rendering/depth-buffer", async () => {
194
+ beforeEach(async () => {
195
+ glArea.make_current();
196
+ });
197
+ await it("DEPTH_TEST NOTEQUAL: both passes render because depths differ", async () => {
198
+ const W = 50, H = 50;
199
+ const fbo = makeTestFBOWithDepth(gl, W, H);
200
+ gl.clearColor(0, 0, 0, 0);
201
+ gl.clearDepth(1);
202
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
203
+ gl.enable(gl.DEPTH_TEST);
204
+ gl.depthFunc(gl.NOTEQUAL);
205
+ const prog = makeProgram(gl, VS_DEPTH, FS_COLOR);
206
+ gl.useProgram(prog);
207
+ gl.uniform1f(gl.getUniformLocation(prog, "depth"), 0);
208
+ gl.uniform4f(gl.getUniformLocation(prog, "color"), 1, 0, 0, 1);
209
+ drawTriangle(gl);
210
+ gl.uniform1f(gl.getUniformLocation(prog, "depth"), 1);
211
+ gl.uniform4f(gl.getUniformLocation(prog, "color"), 0, 1, 0, 1);
212
+ drawTriangle(gl);
213
+ gl.disable(gl.DEPTH_TEST);
214
+ const pixels = new Uint8Array(W * H * 4);
215
+ gl.readPixels(0, 0, W, H, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
216
+ destroyTestFBOWithDepth(gl, fbo);
217
+ let allGreen = true;
218
+ for (let i = 0; i < W * H * 4; i += 4) {
219
+ if (!pixelClose(pixels.subarray(i, i + 4), [
220
+ 0,
221
+ 255,
222
+ 0,
223
+ 255
224
+ ], 3)) {
225
+ allGreen = false;
226
+ break;
227
+ }
228
+ }
229
+ expect(allGreen).toBe(true);
230
+ expect(gl.getError()).toBe(gl.NO_ERROR);
231
+ });
232
+ await it("DEPTH_TEST LESS: closer triangle overwrites farther", async () => {
233
+ const W = 20, H = 20;
234
+ const fbo = makeTestFBOWithDepth(gl, W, H);
235
+ gl.clearColor(0, 0, 0, 0);
236
+ gl.clearDepth(1);
237
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
238
+ gl.enable(gl.DEPTH_TEST);
239
+ gl.depthFunc(gl.LESS);
240
+ const prog = makeProgram(gl, VS_DEPTH, FS_COLOR);
241
+ gl.useProgram(prog);
242
+ gl.uniform1f(gl.getUniformLocation(prog, "depth"), .5);
243
+ gl.uniform4f(gl.getUniformLocation(prog, "color"), 0, 0, 1, 1);
244
+ drawTriangle(gl);
245
+ gl.uniform1f(gl.getUniformLocation(prog, "depth"), .25);
246
+ gl.uniform4f(gl.getUniformLocation(prog, "color"), 0, 1, 0, 1);
247
+ drawTriangle(gl);
248
+ gl.uniform1f(gl.getUniformLocation(prog, "depth"), .75);
249
+ gl.uniform4f(gl.getUniformLocation(prog, "color"), 1, 0, 0, 1);
250
+ drawTriangle(gl);
251
+ gl.disable(gl.DEPTH_TEST);
252
+ const pixels = new Uint8Array(W * H * 4);
253
+ gl.readPixels(0, 0, W, H, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
254
+ destroyTestFBOWithDepth(gl, fbo);
255
+ let allGreen = true;
256
+ for (let i = 0; i < W * H * 4; i += 4) {
257
+ if (!pixelClose(pixels.subarray(i, i + 4), [
258
+ 0,
259
+ 255,
260
+ 0,
261
+ 255
262
+ ], 3)) {
263
+ allGreen = false;
264
+ break;
265
+ }
266
+ }
267
+ expect(allGreen).toBe(true);
268
+ expect(gl.getError()).toBe(gl.NO_ERROR);
269
+ });
270
+ await it("depthMask(false) prevents depth writes", async () => {
271
+ const W = 10, H = 10;
272
+ const fbo = makeTestFBOWithDepth(gl, W, H);
273
+ gl.clearColor(0, 0, 0, 0);
274
+ gl.clearDepth(1);
275
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
276
+ gl.enable(gl.DEPTH_TEST);
277
+ gl.depthFunc(gl.LESS);
278
+ const prog = makeProgram(gl, VS_DEPTH, FS_COLOR);
279
+ gl.useProgram(prog);
280
+ gl.depthMask(false);
281
+ gl.uniform1f(gl.getUniformLocation(prog, "depth"), .5);
282
+ gl.uniform4f(gl.getUniformLocation(prog, "color"), 1, 0, 0, 1);
283
+ drawTriangle(gl);
284
+ gl.depthMask(true);
285
+ gl.uniform1f(gl.getUniformLocation(prog, "depth"), .75);
286
+ gl.uniform4f(gl.getUniformLocation(prog, "color"), 0, 1, 0, 1);
287
+ drawTriangle(gl);
288
+ gl.disable(gl.DEPTH_TEST);
289
+ const pixels = new Uint8Array(W * H * 4);
290
+ gl.readPixels(0, 0, W, H, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
291
+ destroyTestFBOWithDepth(gl, fbo);
292
+ let allGreen = true;
293
+ for (let i = 0; i < W * H * 4; i += 4) {
294
+ if (!pixelClose(pixels.subarray(i, i + 4), [
295
+ 0,
296
+ 255,
297
+ 0,
298
+ 255
299
+ ], 3)) {
300
+ allGreen = false;
301
+ break;
302
+ }
303
+ }
304
+ expect(allGreen).toBe(true);
305
+ expect(gl.getError()).toBe(gl.NO_ERROR);
306
+ });
307
+ });
308
+ await describe("rendering/scissor", async () => {
309
+ beforeEach(async () => {
310
+ glArea.make_current();
311
+ });
312
+ await it("scissor test clips rendering to specified rectangle", async () => {
313
+ const W = 20, H = 20;
314
+ const fbo = makeTestFBO(gl, W, H);
315
+ gl.clearColor(1, 0, 0, 1);
316
+ gl.clear(gl.COLOR_BUFFER_BIT);
317
+ gl.enable(gl.SCISSOR_TEST);
318
+ gl.scissor(0, 0, W / 2, H);
319
+ gl.clearColor(0, 1, 0, 1);
320
+ gl.clear(gl.COLOR_BUFFER_BIT);
321
+ gl.disable(gl.SCISSOR_TEST);
322
+ const pixels = new Uint8Array(W * H * 4);
323
+ gl.readPixels(0, 0, W, H, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
324
+ destroyTestFBO(gl, fbo);
325
+ let ok = true;
326
+ for (let y = 0; y < H; y++) {
327
+ for (let x = 0; x < W; x++) {
328
+ const i = (y * W + x) * 4;
329
+ const pix = pixels.subarray(i, i + 4);
330
+ if (x < W / 2) {
331
+ if (!pixelClose(pix, [
332
+ 0,
333
+ 255,
334
+ 0,
335
+ 255
336
+ ])) {
337
+ ok = false;
338
+ break;
339
+ }
340
+ } else {
341
+ if (!pixelClose(pix, [
342
+ 255,
343
+ 0,
344
+ 0,
345
+ 255
346
+ ])) {
347
+ ok = false;
348
+ break;
349
+ }
350
+ }
351
+ }
352
+ if (!ok) break;
353
+ }
354
+ expect(ok).toBe(true);
355
+ expect(gl.getError()).toBe(gl.NO_ERROR);
356
+ });
357
+ });
358
+ await describe("rendering/mapbox-ansis", async () => {
359
+ beforeEach(async () => {
360
+ glArea.make_current();
361
+ });
362
+ await it("depthRange: green at range(0,0.1) survives blue at range(0.9,1) with LEQUAL", async () => {
363
+ const W = 4, H = 4;
364
+ const vsSrc = `
283
365
  precision mediump float;
284
366
  uniform float u_z;
285
367
  attribute vec2 a_position;
286
368
  void main() { gl_Position = vec4(a_position, u_z, 1.0); }`;
287
- const fsSrc = `
369
+ const fsSrc = `
288
370
  precision mediump float;
289
371
  uniform vec4 u_color;
290
372
  void main() { gl_FragColor = u_color; }`;
291
- const fb = gl.createFramebuffer();
292
- const colorTex = gl.createTexture();
293
- gl.bindTexture(gl.TEXTURE_2D, colorTex);
294
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, W, H, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
295
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
296
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
297
- gl.bindTexture(gl.TEXTURE_2D, null);
298
- const depthRb = gl.createRenderbuffer();
299
- gl.bindRenderbuffer(gl.RENDERBUFFER, depthRb);
300
- gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, W, H);
301
- gl.bindRenderbuffer(gl.RENDERBUFFER, null);
302
- gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
303
- gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, colorTex, 0);
304
- gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthRb);
305
- gl.viewport(0, 0, W, H);
306
- gl.clearColor(1, 0, 0, 1);
307
- gl.clearDepth(1);
308
- gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
309
- gl.enable(gl.DEPTH_TEST);
310
- gl.depthFunc(gl.LEQUAL);
311
- const prog = makeProgram(gl, vsSrc, fsSrc);
312
- gl.useProgram(prog);
313
- const buf = gl.createBuffer();
314
- gl.bindBuffer(gl.ARRAY_BUFFER, buf);
315
- gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
316
- -1,
317
- -1,
318
- 1,
319
- -1,
320
- -1,
321
- 1,
322
- -1,
323
- 1,
324
- 1,
325
- -1,
326
- 1,
327
- 1
328
- ]), gl.STATIC_DRAW);
329
- const aPos = gl.getAttribLocation(prog, "a_position");
330
- gl.enableVertexAttribArray(aPos);
331
- gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 0, 0);
332
- const uColor = gl.getUniformLocation(prog, "u_color");
333
- const uZ = gl.getUniformLocation(prog, "u_z");
334
- gl.uniform1f(uZ, 0.5);
335
- gl.uniform4fv(uColor, [0, 1, 0, 1]);
336
- gl.depthRange(0, 0.1);
337
- gl.drawArrays(gl.TRIANGLES, 0, 6);
338
- gl.uniform1f(uZ, 0.5);
339
- gl.uniform4fv(uColor, [0, 0, 1, 1]);
340
- gl.depthRange(0.9, 1);
341
- gl.drawArrays(gl.TRIANGLES, 0, 6);
342
- gl.depthRange(0, 1);
343
- gl.disable(gl.DEPTH_TEST);
344
- const pixels = new Uint8Array(W * H * 4);
345
- gl.readPixels(0, 0, W, H, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
346
- gl.bindBuffer(gl.ARRAY_BUFFER, null);
347
- gl.deleteBuffer(buf);
348
- gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
349
- gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, null, 0);
350
- gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, null);
351
- gl.bindFramebuffer(gl.FRAMEBUFFER, null);
352
- gl.deleteTexture(colorTex);
353
- gl.deleteRenderbuffer(depthRb);
354
- gl.deleteFramebuffer(fb);
355
- expect(gl.getError()).toBe(gl.NO_ERROR);
356
- let allGreen = true;
357
- for (let i = 0; i < W * H * 4; i += 4) {
358
- if (pixels[i] !== 0 || pixels[i + 1] !== 255 || pixels[i + 2] !== 0 || pixels[i + 3] !== 255) {
359
- allGreen = false;
360
- break;
361
- }
362
- }
363
- expect(allGreen).toBe(true);
364
- });
365
- });
366
- await describe("rendering/viewport", async () => {
367
- beforeEach(async () => {
368
- glArea.make_current();
369
- });
370
- await it("viewport restricts rendering region", async () => {
371
- const W = 20, H = 20;
372
- const fbo = makeTestFBO(gl, W, H);
373
- gl.clearColor(1, 0, 0, 1);
374
- gl.clear(gl.COLOR_BUFFER_BIT);
375
- const HW = W / 2;
376
- gl.viewport(0, 0, HW, H / 2);
377
- const fsGreen = `precision mediump float; void main() { gl_FragColor = vec4(0,1,0,1); }`;
378
- const prog = makeProgram(gl, VS, fsGreen);
379
- gl.useProgram(prog);
380
- drawTriangle(gl);
381
- gl.viewport(0, 0, W, H);
382
- const pixels = new Uint8Array(W * H * 4);
383
- gl.readPixels(0, 0, W, H, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
384
- destroyTestFBO(gl, fbo);
385
- let ok = true;
386
- for (let y = 0; y < H; y++) {
387
- for (let x = 0; x < W; x++) {
388
- const i = (y * W + x) * 4;
389
- const pix = pixels.subarray(i, i + 4);
390
- if (x < HW && y < H / 2) {
391
- if (!pixelClose(pix, [0, 255, 0, 255])) {
392
- ok = false;
393
- break;
394
- }
395
- } else {
396
- if (!pixelClose(pix, [255, 0, 0, 255])) {
397
- ok = false;
398
- break;
399
- }
400
- }
401
- }
402
- if (!ok) break;
403
- }
404
- expect(ok).toBe(true);
405
- expect(gl.getError()).toBe(gl.NO_ERROR);
406
- });
407
- await it("getParameter(VIEWPORT) returns current viewport", async () => {
408
- const fbo = makeTestFBO(gl, 16, 16);
409
- gl.viewport(2, 3, 10, 12);
410
- const v = gl.getParameter(gl.VIEWPORT);
411
- expect(v[0]).toBe(2);
412
- expect(v[1]).toBe(3);
413
- expect(v[2]).toBe(10);
414
- expect(v[3]).toBe(12);
415
- gl.viewport(0, 0, 16, 16);
416
- destroyTestFBO(gl, fbo);
417
- expect(gl.getError()).toBe(gl.NO_ERROR);
418
- });
419
- });
420
- });
421
- };
422
- export {
423
- rendering_spec_default as default
373
+ const fb = gl.createFramebuffer();
374
+ const colorTex = gl.createTexture();
375
+ gl.bindTexture(gl.TEXTURE_2D, colorTex);
376
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, W, H, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
377
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
378
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
379
+ gl.bindTexture(gl.TEXTURE_2D, null);
380
+ const depthRb = gl.createRenderbuffer();
381
+ gl.bindRenderbuffer(gl.RENDERBUFFER, depthRb);
382
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, W, H);
383
+ gl.bindRenderbuffer(gl.RENDERBUFFER, null);
384
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
385
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, colorTex, 0);
386
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthRb);
387
+ gl.viewport(0, 0, W, H);
388
+ gl.clearColor(1, 0, 0, 1);
389
+ gl.clearDepth(1);
390
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
391
+ gl.enable(gl.DEPTH_TEST);
392
+ gl.depthFunc(gl.LEQUAL);
393
+ const prog = makeProgram(gl, vsSrc, fsSrc);
394
+ gl.useProgram(prog);
395
+ const buf = gl.createBuffer();
396
+ gl.bindBuffer(gl.ARRAY_BUFFER, buf);
397
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
398
+ -1,
399
+ -1,
400
+ 1,
401
+ -1,
402
+ -1,
403
+ 1,
404
+ -1,
405
+ 1,
406
+ 1,
407
+ -1,
408
+ 1,
409
+ 1
410
+ ]), gl.STATIC_DRAW);
411
+ const aPos = gl.getAttribLocation(prog, "a_position");
412
+ gl.enableVertexAttribArray(aPos);
413
+ gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 0, 0);
414
+ const uColor = gl.getUniformLocation(prog, "u_color");
415
+ const uZ = gl.getUniformLocation(prog, "u_z");
416
+ gl.uniform1f(uZ, .5);
417
+ gl.uniform4fv(uColor, [
418
+ 0,
419
+ 1,
420
+ 0,
421
+ 1
422
+ ]);
423
+ gl.depthRange(0, .1);
424
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
425
+ gl.uniform1f(uZ, .5);
426
+ gl.uniform4fv(uColor, [
427
+ 0,
428
+ 0,
429
+ 1,
430
+ 1
431
+ ]);
432
+ gl.depthRange(.9, 1);
433
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
434
+ gl.depthRange(0, 1);
435
+ gl.disable(gl.DEPTH_TEST);
436
+ const pixels = new Uint8Array(W * H * 4);
437
+ gl.readPixels(0, 0, W, H, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
438
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
439
+ gl.deleteBuffer(buf);
440
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
441
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, null, 0);
442
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, null);
443
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
444
+ gl.deleteTexture(colorTex);
445
+ gl.deleteRenderbuffer(depthRb);
446
+ gl.deleteFramebuffer(fb);
447
+ expect(gl.getError()).toBe(gl.NO_ERROR);
448
+ let allGreen = true;
449
+ for (let i = 0; i < W * H * 4; i += 4) {
450
+ if (pixels[i] !== 0 || pixels[i + 1] !== 255 || pixels[i + 2] !== 0 || pixels[i + 3] !== 255) {
451
+ allGreen = false;
452
+ break;
453
+ }
454
+ }
455
+ expect(allGreen).toBe(true);
456
+ });
457
+ });
458
+ await describe("rendering/viewport", async () => {
459
+ beforeEach(async () => {
460
+ glArea.make_current();
461
+ });
462
+ await it("viewport restricts rendering region", async () => {
463
+ const W = 20, H = 20;
464
+ const fbo = makeTestFBO(gl, W, H);
465
+ gl.clearColor(1, 0, 0, 1);
466
+ gl.clear(gl.COLOR_BUFFER_BIT);
467
+ const HW = W / 2;
468
+ gl.viewport(0, 0, HW, H / 2);
469
+ const fsGreen = `precision mediump float; void main() { gl_FragColor = vec4(0,1,0,1); }`;
470
+ const prog = makeProgram(gl, VS, fsGreen);
471
+ gl.useProgram(prog);
472
+ drawTriangle(gl);
473
+ gl.viewport(0, 0, W, H);
474
+ const pixels = new Uint8Array(W * H * 4);
475
+ gl.readPixels(0, 0, W, H, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
476
+ destroyTestFBO(gl, fbo);
477
+ let ok = true;
478
+ for (let y = 0; y < H; y++) {
479
+ for (let x = 0; x < W; x++) {
480
+ const i = (y * W + x) * 4;
481
+ const pix = pixels.subarray(i, i + 4);
482
+ if (x < HW && y < H / 2) {
483
+ if (!pixelClose(pix, [
484
+ 0,
485
+ 255,
486
+ 0,
487
+ 255
488
+ ])) {
489
+ ok = false;
490
+ break;
491
+ }
492
+ } else {
493
+ if (!pixelClose(pix, [
494
+ 255,
495
+ 0,
496
+ 0,
497
+ 255
498
+ ])) {
499
+ ok = false;
500
+ break;
501
+ }
502
+ }
503
+ }
504
+ if (!ok) break;
505
+ }
506
+ expect(ok).toBe(true);
507
+ expect(gl.getError()).toBe(gl.NO_ERROR);
508
+ });
509
+ await it("getParameter(VIEWPORT) returns current viewport", async () => {
510
+ const fbo = makeTestFBO(gl, 16, 16);
511
+ gl.viewport(2, 3, 10, 12);
512
+ const v = gl.getParameter(gl.VIEWPORT);
513
+ expect(v[0]).toBe(2);
514
+ expect(v[1]).toBe(3);
515
+ expect(v[2]).toBe(10);
516
+ expect(v[3]).toBe(12);
517
+ gl.viewport(0, 0, 16, 16);
518
+ destroyTestFBO(gl, fbo);
519
+ expect(gl.getError()).toBe(gl.NO_ERROR);
520
+ });
521
+ });
522
+ });
424
523
  };
524
+
525
+ //#endregion
526
+ export { rendering_spec_default as default };