@gjsify/webgl 0.3.16 → 0.3.18
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/lib/esm/conformance/attribs.spec.js +3 -315
- package/lib/esm/conformance/buffers.spec.js +1 -220
- package/lib/esm/conformance/context.spec.js +3 -302
- package/lib/esm/conformance/programs.spec.js +3 -477
- package/lib/esm/conformance/rendering-basic.spec.js +3 -141
- package/lib/esm/conformance/rendering.spec.js +7 -514
- package/lib/esm/conformance/setup.js +1 -47
- package/lib/esm/conformance/state.spec.js +1 -365
- package/lib/esm/conformance/textures.spec.js +3 -337
- package/lib/esm/conformance/uniforms.spec.js +1 -484
- package/lib/esm/conformance-test.js +1 -25
- package/lib/esm/extensions/ext-blend-minmax.js +1 -18
- package/lib/esm/extensions/ext-color-buffer-float.js +1 -12
- package/lib/esm/extensions/ext-color-buffer-half-float.js +1 -12
- package/lib/esm/extensions/ext-texture-filter-anisotropic.js +1 -18
- package/lib/esm/extensions/oes-element-index-unit.js +1 -13
- package/lib/esm/extensions/oes-standard-derivatives.js +1 -17
- package/lib/esm/extensions/oes-texture-float-linear.js +1 -13
- package/lib/esm/extensions/oes-texture-float.js +1 -13
- package/lib/esm/extensions/oes-texture-half-float.js +1 -19
- package/lib/esm/extensions/stackgl-destroy-context.js +1 -12
- package/lib/esm/extensions/stackgl-resize-drawing-buffer.js +1 -12
- package/lib/esm/html-canvas-element.js +1 -65
- package/lib/esm/index.js +1 -33
- package/lib/esm/linkable.js +1 -50
- package/lib/esm/test-utils.js +4 -186
- package/lib/esm/test.js +1 -11
- package/lib/esm/types/index.js +1 -5
- package/lib/esm/utils.js +1 -201
- package/lib/esm/webgl-active-info.js +1 -11
- package/lib/esm/webgl-bridge.js +1 -167
- package/lib/esm/webgl-buffer.js +1 -19
- package/lib/esm/webgl-context-attributes.js +1 -24
- package/lib/esm/webgl-context-base.js +8 -3069
- package/lib/esm/webgl-drawing-buffer-wrapper.js +1 -11
- package/lib/esm/webgl-framebuffer.js +1 -110
- package/lib/esm/webgl-program.js +1 -27
- package/lib/esm/webgl-query.js +1 -17
- package/lib/esm/webgl-renderbuffer.js +1 -25
- package/lib/esm/webgl-rendering-context.js +1 -175
- package/lib/esm/webgl-sampler.js +1 -17
- package/lib/esm/webgl-shader-precision-format.js +1 -11
- package/lib/esm/webgl-shader.js +1 -25
- package/lib/esm/webgl-sync.js +1 -17
- package/lib/esm/webgl-texture-unit.js +1 -13
- package/lib/esm/webgl-texture.js +1 -23
- package/lib/esm/webgl-transform-feedback.js +1 -17
- package/lib/esm/webgl-uniform-location.js +1 -15
- package/lib/esm/webgl-vertex-array-object.js +1 -23
- package/lib/esm/webgl-vertex-attribute.js +1 -151
- package/lib/esm/webgl1.spec.js +10 -1044
- package/lib/esm/webgl2-rendering-context.js +1 -1218
- package/lib/esm/webgl2.spec.js +45 -1288
- package/lib/types/webgl-bridge.d.ts +9 -9
- package/package.json +9 -9
|
@@ -1,481 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { createGLSetup } from "./setup.js";
|
|
3
|
-
import { beforeEach, describe, expect, it, on } from "@gjsify/unit";
|
|
4
|
-
|
|
5
|
-
//#region src/ts/conformance/programs.spec.ts
|
|
6
|
-
const VS_POSITION = `attribute vec4 a_position; void main() { gl_Position = a_position; }`;
|
|
7
|
-
const VS_COLOR_ATTRIB = `attribute vec4 aVertex; attribute vec4 aColor; varying vec4 vColor; void main() { vColor = aColor; gl_Position = aVertex; }`;
|
|
8
|
-
const FS_VARYING_COLOR = `precision mediump float; varying vec4 vColor; void main() { gl_FragColor = vColor; }`;
|
|
9
|
-
const FS_RED = `void main() { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); }`;
|
|
10
|
-
const FS_GREEN = `void main() { gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); }`;
|
|
11
|
-
const FS_SETTABLE = `precision mediump float; uniform vec4 u_color; void main() { gl_FragColor = u_color; }`;
|
|
12
|
-
const VS_STANDARD = `
|
|
1
|
+
import{destroyTestFBO as e,makeTestFBO as t,pixelClose as n,readPixel as r}from"../test-utils.js";import{createGLSetup as i}from"./setup.js";import{beforeEach as a,describe as o,expect as s,it as c,on as l}from"@gjsify/unit";const u=`attribute vec4 a_position; void main() { gl_Position = a_position; }`,d=`attribute vec4 aVertex; attribute vec4 aColor; varying vec4 vColor; void main() { vColor = aColor; gl_Position = aVertex; }`,f=`precision mediump float; varying vec4 vColor; void main() { gl_FragColor = vColor; }`,p=`void main() { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); }`,m=`void main() { gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); }`,h=`
|
|
13
2
|
attribute vec4 a_vertex;
|
|
14
3
|
attribute vec3 a_normal;
|
|
15
4
|
uniform mat4 u_modelViewProjMatrix;
|
|
16
|
-
void main() { gl_Position = u_modelViewProjMatrix * (a_vertex + vec4(a_normal, 0.0)); }
|
|
17
|
-
const FS_STANDARD = `
|
|
5
|
+
void main() { gl_Position = u_modelViewProjMatrix * (a_vertex + vec4(a_normal, 0.0)); }`,g=`
|
|
18
6
|
precision mediump float;
|
|
19
|
-
void main() { gl_FragColor = vec4(1.0); }`;
|
|
20
|
-
function compileShader(gl, type, src) {
|
|
21
|
-
const s = gl.createShader(type);
|
|
22
|
-
gl.shaderSource(s, src);
|
|
23
|
-
gl.compileShader(s);
|
|
24
|
-
return s;
|
|
25
|
-
}
|
|
26
|
-
function linkProgram(gl, vsSrc, fsSrc, attribBindings) {
|
|
27
|
-
const vs = compileShader(gl, gl.VERTEX_SHADER, vsSrc);
|
|
28
|
-
const fs = compileShader(gl, gl.FRAGMENT_SHADER, fsSrc);
|
|
29
|
-
const prog = gl.createProgram();
|
|
30
|
-
gl.attachShader(prog, vs);
|
|
31
|
-
gl.attachShader(prog, fs);
|
|
32
|
-
if (attribBindings) {
|
|
33
|
-
for (const [name, loc] of attribBindings) gl.bindAttribLocation(prog, loc, name);
|
|
34
|
-
}
|
|
35
|
-
gl.linkProgram(prog);
|
|
36
|
-
return prog;
|
|
37
|
-
}
|
|
38
|
-
/** Fill the current FBO with a fullscreen triangle and return the center pixel. */
|
|
39
|
-
function drawFullscreenAndRead(gl, prog, posAttrib = "a_position") {
|
|
40
|
-
const loc = typeof posAttrib === "string" ? gl.getAttribLocation(prog, posAttrib) : posAttrib;
|
|
41
|
-
const buf = gl.createBuffer();
|
|
42
|
-
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
|
|
43
|
-
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
|
|
44
|
-
-4,
|
|
45
|
-
-4,
|
|
46
|
-
4,
|
|
47
|
-
-4,
|
|
48
|
-
0,
|
|
49
|
-
4
|
|
50
|
-
]), gl.STREAM_DRAW);
|
|
51
|
-
gl.enableVertexAttribArray(loc);
|
|
52
|
-
gl.vertexAttribPointer(loc, 2, gl.FLOAT, false, 0, 0);
|
|
53
|
-
gl.drawArrays(gl.TRIANGLES, 0, 3);
|
|
54
|
-
gl.disableVertexAttribArray(loc);
|
|
55
|
-
gl.deleteBuffer(buf);
|
|
56
|
-
return readPixel(gl, 0, 0);
|
|
57
|
-
}
|
|
58
|
-
var programs_spec_default = async () => {
|
|
59
|
-
await on("Display", async () => {
|
|
60
|
-
const setup = createGLSetup();
|
|
61
|
-
if (!setup) {
|
|
62
|
-
console.warn("WebGL context not available — skipping conformance/programs tests");
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
const { gl, glArea, win } = setup;
|
|
66
|
-
glArea.make_current();
|
|
67
|
-
await describe("conformance/programs/program-test: compileShader", async () => {
|
|
68
|
-
beforeEach(async () => {
|
|
69
|
-
glArea.make_current();
|
|
70
|
-
});
|
|
71
|
-
await it("good vertex shader should compile", async () => {
|
|
72
|
-
const vs = compileShader(gl, gl.VERTEX_SHADER, "attribute vec4 aVertex; void main() { gl_Position = aVertex; }");
|
|
73
|
-
expect(gl.getShaderParameter(vs, gl.COMPILE_STATUS)).toBeTruthy();
|
|
74
|
-
gl.deleteShader(vs);
|
|
75
|
-
});
|
|
76
|
-
await it("good fragment shader should compile", async () => {
|
|
77
|
-
const fs = compileShader(gl, gl.FRAGMENT_SHADER, "precision mediump float; void main() { gl_FragColor = vec4(1.0); }");
|
|
78
|
-
expect(gl.getShaderParameter(fs, gl.COMPILE_STATUS)).toBeTruthy();
|
|
79
|
-
gl.deleteShader(fs);
|
|
80
|
-
});
|
|
81
|
-
await it("getShaderParameter with desktop-only INFO_LOG_LENGTH returns null and INVALID_ENUM", async () => {
|
|
82
|
-
const vs = compileShader(gl, gl.VERTEX_SHADER, "attribute vec4 v; void main() { gl_Position = v; }");
|
|
83
|
-
const INFO_LOG_LENGTH = 35716;
|
|
84
|
-
const result = gl.getShaderParameter(vs, INFO_LOG_LENGTH);
|
|
85
|
-
expect(result).toBeNull();
|
|
86
|
-
expect(gl.getError()).toBe(gl.INVALID_ENUM);
|
|
87
|
-
gl.deleteShader(vs);
|
|
88
|
-
});
|
|
89
|
-
});
|
|
90
|
-
await describe("conformance/programs/program-test: attachShader / detachShader", async () => {
|
|
91
|
-
beforeEach(async () => {
|
|
92
|
-
glArea.make_current();
|
|
93
|
-
});
|
|
94
|
-
await it("attaching a vertex shader succeeds", async () => {
|
|
95
|
-
const vs = compileShader(gl, gl.VERTEX_SHADER, VS_COLOR_ATTRIB);
|
|
96
|
-
const prog = gl.createProgram();
|
|
97
|
-
gl.attachShader(prog, vs);
|
|
98
|
-
expect(gl.getError()).toBe(gl.NO_ERROR);
|
|
99
|
-
gl.deleteProgram(prog);
|
|
100
|
-
gl.deleteShader(vs);
|
|
101
|
-
});
|
|
102
|
-
await it("attaching the same shader twice generates INVALID_OPERATION", async () => {
|
|
103
|
-
const vs = compileShader(gl, gl.VERTEX_SHADER, VS_COLOR_ATTRIB);
|
|
104
|
-
const prog = gl.createProgram();
|
|
105
|
-
gl.attachShader(prog, vs);
|
|
106
|
-
gl.getError();
|
|
107
|
-
gl.attachShader(prog, vs);
|
|
108
|
-
expect(gl.getError()).toBe(gl.INVALID_OPERATION);
|
|
109
|
-
gl.deleteProgram(prog);
|
|
110
|
-
gl.deleteShader(vs);
|
|
111
|
-
});
|
|
112
|
-
await it("attaching two vertex shaders to same program generates INVALID_OPERATION", async () => {
|
|
113
|
-
const vs1 = compileShader(gl, gl.VERTEX_SHADER, VS_COLOR_ATTRIB);
|
|
114
|
-
const vs2 = compileShader(gl, gl.VERTEX_SHADER, "attribute vec4 v; void main() { gl_Position = v * 0.5; }");
|
|
115
|
-
const prog = gl.createProgram();
|
|
116
|
-
gl.attachShader(prog, vs1);
|
|
117
|
-
gl.getError();
|
|
118
|
-
gl.attachShader(prog, vs2);
|
|
119
|
-
expect(gl.getError()).toBe(gl.INVALID_OPERATION);
|
|
120
|
-
gl.deleteProgram(prog);
|
|
121
|
-
gl.deleteShader(vs1);
|
|
122
|
-
gl.deleteShader(vs2);
|
|
123
|
-
});
|
|
124
|
-
await it("detaching an attached shader succeeds", async () => {
|
|
125
|
-
const vs = compileShader(gl, gl.VERTEX_SHADER, VS_COLOR_ATTRIB);
|
|
126
|
-
const prog = gl.createProgram();
|
|
127
|
-
gl.attachShader(prog, vs);
|
|
128
|
-
gl.detachShader(prog, vs);
|
|
129
|
-
expect(gl.getError()).toBe(gl.NO_ERROR);
|
|
130
|
-
gl.deleteProgram(prog);
|
|
131
|
-
gl.deleteShader(vs);
|
|
132
|
-
});
|
|
133
|
-
await it("detaching a non-attached shader generates INVALID_OPERATION", async () => {
|
|
134
|
-
const vs = compileShader(gl, gl.VERTEX_SHADER, VS_COLOR_ATTRIB);
|
|
135
|
-
const fs = compileShader(gl, gl.FRAGMENT_SHADER, FS_VARYING_COLOR);
|
|
136
|
-
const prog = gl.createProgram();
|
|
137
|
-
gl.attachShader(prog, fs);
|
|
138
|
-
gl.getError();
|
|
139
|
-
gl.detachShader(prog, vs);
|
|
140
|
-
expect(gl.getError()).toBe(gl.INVALID_OPERATION);
|
|
141
|
-
gl.deleteProgram(prog);
|
|
142
|
-
gl.deleteShader(vs);
|
|
143
|
-
gl.deleteShader(fs);
|
|
144
|
-
});
|
|
145
|
-
});
|
|
146
|
-
await describe("conformance/programs/program-test: getAttachedShaders", async () => {
|
|
147
|
-
beforeEach(async () => {
|
|
148
|
-
glArea.make_current();
|
|
149
|
-
});
|
|
150
|
-
await it("empty program returns empty list", async () => {
|
|
151
|
-
const prog = gl.createProgram();
|
|
152
|
-
const shaders = gl.getAttachedShaders(prog);
|
|
153
|
-
expect(shaders?.length).toBe(0);
|
|
154
|
-
gl.deleteProgram(prog);
|
|
155
|
-
});
|
|
156
|
-
await it("attached shaders appear in getAttachedShaders", async () => {
|
|
157
|
-
const vs = compileShader(gl, gl.VERTEX_SHADER, VS_COLOR_ATTRIB);
|
|
158
|
-
const fs = compileShader(gl, gl.FRAGMENT_SHADER, FS_VARYING_COLOR);
|
|
159
|
-
const prog = gl.createProgram();
|
|
160
|
-
gl.attachShader(prog, vs);
|
|
161
|
-
gl.attachShader(prog, fs);
|
|
162
|
-
const shaders = gl.getAttachedShaders(prog);
|
|
163
|
-
expect(shaders.length).toBe(2);
|
|
164
|
-
expect(shaders.includes(vs)).toBeTruthy();
|
|
165
|
-
expect(shaders.includes(fs)).toBeTruthy();
|
|
166
|
-
gl.deleteProgram(prog);
|
|
167
|
-
gl.deleteShader(vs);
|
|
168
|
-
gl.deleteShader(fs);
|
|
169
|
-
});
|
|
170
|
-
await it("detached shaders are removed from getAttachedShaders", async () => {
|
|
171
|
-
const vs = compileShader(gl, gl.VERTEX_SHADER, VS_COLOR_ATTRIB);
|
|
172
|
-
const fs = compileShader(gl, gl.FRAGMENT_SHADER, FS_VARYING_COLOR);
|
|
173
|
-
const prog = gl.createProgram();
|
|
174
|
-
gl.attachShader(prog, vs);
|
|
175
|
-
gl.attachShader(prog, fs);
|
|
176
|
-
gl.detachShader(prog, vs);
|
|
177
|
-
const shaders = gl.getAttachedShaders(prog);
|
|
178
|
-
expect(shaders.length).toBe(1);
|
|
179
|
-
expect(shaders.includes(fs)).toBeTruthy();
|
|
180
|
-
gl.deleteProgram(prog);
|
|
181
|
-
gl.deleteShader(vs);
|
|
182
|
-
gl.deleteShader(fs);
|
|
183
|
-
});
|
|
184
|
-
});
|
|
185
|
-
await describe("conformance/programs/program-test: linkProgram / useProgram", async () => {
|
|
186
|
-
beforeEach(async () => {
|
|
187
|
-
glArea.make_current();
|
|
188
|
-
});
|
|
189
|
-
await it("valid program should link", async () => {
|
|
190
|
-
const prog = linkProgram(gl, VS_COLOR_ATTRIB, FS_VARYING_COLOR, [["aVertex", 0], ["aColor", 1]]);
|
|
191
|
-
expect(gl.getProgramParameter(prog, gl.LINK_STATUS)).toBeTruthy();
|
|
192
|
-
expect(typeof gl.getProgramInfoLog(prog)).toBe("string");
|
|
193
|
-
gl.deleteProgram(prog);
|
|
194
|
-
});
|
|
195
|
-
await it("program with no fragment shader should fail to link", async () => {
|
|
196
|
-
const vs = compileShader(gl, gl.VERTEX_SHADER, VS_COLOR_ATTRIB);
|
|
197
|
-
const prog = gl.createProgram();
|
|
198
|
-
gl.attachShader(prog, vs);
|
|
199
|
-
gl.linkProgram(prog);
|
|
200
|
-
expect(gl.getProgramParameter(prog, gl.LINK_STATUS)).toBeFalsy();
|
|
201
|
-
gl.deleteProgram(prog);
|
|
202
|
-
gl.deleteShader(vs);
|
|
203
|
-
});
|
|
204
|
-
await it("program with no vertex shader should fail to link", async () => {
|
|
205
|
-
const fs = compileShader(gl, gl.FRAGMENT_SHADER, FS_VARYING_COLOR);
|
|
206
|
-
const prog = gl.createProgram();
|
|
207
|
-
gl.attachShader(prog, fs);
|
|
208
|
-
gl.linkProgram(prog);
|
|
209
|
-
expect(gl.getProgramParameter(prog, gl.LINK_STATUS)).toBeFalsy();
|
|
210
|
-
gl.deleteProgram(prog);
|
|
211
|
-
gl.deleteShader(fs);
|
|
212
|
-
});
|
|
213
|
-
await it("using a valid program should succeed", async () => {
|
|
214
|
-
const prog = linkProgram(gl, VS_COLOR_ATTRIB, FS_VARYING_COLOR, [["aVertex", 0], ["aColor", 1]]);
|
|
215
|
-
gl.useProgram(prog);
|
|
216
|
-
expect(gl.getError()).toBe(gl.NO_ERROR);
|
|
217
|
-
gl.useProgram(null);
|
|
218
|
-
gl.deleteProgram(prog);
|
|
219
|
-
});
|
|
220
|
-
await it("using an invalid (unlinked) program should generate INVALID_OPERATION", async () => {
|
|
221
|
-
const vs = compileShader(gl, gl.VERTEX_SHADER, VS_COLOR_ATTRIB);
|
|
222
|
-
const prog = gl.createProgram();
|
|
223
|
-
gl.attachShader(prog, vs);
|
|
224
|
-
gl.linkProgram(prog);
|
|
225
|
-
gl.useProgram(prog);
|
|
226
|
-
expect(gl.getError()).toBe(gl.INVALID_OPERATION);
|
|
227
|
-
gl.deleteProgram(prog);
|
|
228
|
-
gl.deleteShader(vs);
|
|
229
|
-
});
|
|
230
|
-
await it("drawing with null program generates INVALID_OPERATION", async () => {
|
|
231
|
-
const prog = linkProgram(gl, VS_POSITION, FS_RED, [["a_position", 0]]);
|
|
232
|
-
const fbo = makeTestFBO(gl, 2, 2);
|
|
233
|
-
const buf = gl.createBuffer();
|
|
234
|
-
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
|
|
235
|
-
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
|
|
236
|
-
0,
|
|
237
|
-
0,
|
|
238
|
-
1,
|
|
239
|
-
0,
|
|
240
|
-
0,
|
|
241
|
-
1
|
|
242
|
-
]), gl.STATIC_DRAW);
|
|
243
|
-
gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
|
|
244
|
-
gl.enableVertexAttribArray(0);
|
|
245
|
-
gl.useProgram(null);
|
|
246
|
-
gl.drawArrays(gl.TRIANGLES, 0, 3);
|
|
247
|
-
expect(gl.getError()).toBe(gl.INVALID_OPERATION);
|
|
248
|
-
gl.disableVertexAttribArray(0);
|
|
249
|
-
gl.deleteBuffer(buf);
|
|
250
|
-
destroyTestFBO(gl, fbo);
|
|
251
|
-
gl.deleteProgram(prog);
|
|
252
|
-
});
|
|
253
|
-
});
|
|
254
|
-
await describe("conformance/programs/program-test: deleteProgram / deleteShader", async () => {
|
|
255
|
-
beforeEach(async () => {
|
|
256
|
-
glArea.make_current();
|
|
257
|
-
});
|
|
258
|
-
await it("deleting the current program does not affect the current rendering state", async () => {
|
|
259
|
-
const prog = linkProgram(gl, VS_POSITION, FS_RED, [["a_position", 0]]);
|
|
260
|
-
gl.useProgram(prog);
|
|
261
|
-
gl.deleteProgram(prog);
|
|
262
|
-
const fbo = makeTestFBO(gl, 2, 2);
|
|
263
|
-
const pixel = drawFullscreenAndRead(gl, prog, 0);
|
|
264
|
-
expect(gl.getError()).toBe(gl.NO_ERROR);
|
|
265
|
-
expect(pixelClose(pixel, [
|
|
266
|
-
255,
|
|
267
|
-
0,
|
|
268
|
-
0,
|
|
269
|
-
255
|
|
270
|
-
])).toBeTruthy();
|
|
271
|
-
destroyTestFBO(gl, fbo);
|
|
272
|
-
gl.useProgram(null);
|
|
273
|
-
});
|
|
274
|
-
await it("unattached deleted shader is invalid immediately", async () => {
|
|
275
|
-
const fs = compileShader(gl, gl.FRAGMENT_SHADER, FS_RED);
|
|
276
|
-
gl.deleteShader(fs);
|
|
277
|
-
gl.compileShader(fs);
|
|
278
|
-
expect(gl.getError()).toBe(gl.INVALID_VALUE);
|
|
279
|
-
});
|
|
280
|
-
await it("attached deleted shader is still valid while attached", async () => {
|
|
281
|
-
const vs = compileShader(gl, gl.VERTEX_SHADER, VS_POSITION);
|
|
282
|
-
const fs = compileShader(gl, gl.FRAGMENT_SHADER, FS_RED);
|
|
283
|
-
const prog = linkProgram(gl, VS_POSITION, FS_RED, [["a_position", 0]]);
|
|
284
|
-
gl.attachShader(prog, vs);
|
|
285
|
-
gl.getError();
|
|
286
|
-
const fs3 = compileShader(gl, gl.FRAGMENT_SHADER, FS_GREEN);
|
|
287
|
-
const prog2 = gl.createProgram();
|
|
288
|
-
gl.attachShader(prog2, vs);
|
|
289
|
-
gl.attachShader(prog2, fs3);
|
|
290
|
-
gl.deleteShader(fs3);
|
|
291
|
-
gl.compileShader(fs3);
|
|
292
|
-
expect(gl.getShaderParameter(fs3, gl.COMPILE_STATUS)).toBeTruthy();
|
|
293
|
-
gl.deleteProgram(prog);
|
|
294
|
-
gl.deleteProgram(prog2);
|
|
295
|
-
gl.deleteShader(vs);
|
|
296
|
-
gl.deleteShader(fs);
|
|
297
|
-
});
|
|
298
|
-
});
|
|
299
|
-
await describe("conformance/programs/program-test: relink updates rendering", async () => {
|
|
300
|
-
beforeEach(async () => {
|
|
301
|
-
glArea.make_current();
|
|
302
|
-
});
|
|
303
|
-
await it("relinking with a new fragment shader updates the program output", async () => {
|
|
304
|
-
const fbo = makeTestFBO(gl, 2, 2);
|
|
305
|
-
const vs = compileShader(gl, gl.VERTEX_SHADER, VS_POSITION);
|
|
306
|
-
const fs = compileShader(gl, gl.FRAGMENT_SHADER, FS_RED);
|
|
307
|
-
const prog = gl.createProgram();
|
|
308
|
-
gl.attachShader(prog, vs);
|
|
309
|
-
gl.attachShader(prog, fs);
|
|
310
|
-
gl.bindAttribLocation(prog, 0, "a_position");
|
|
311
|
-
gl.linkProgram(prog);
|
|
312
|
-
gl.useProgram(prog);
|
|
313
|
-
expect(gl.getProgramParameter(prog, gl.LINK_STATUS)).toBeTruthy();
|
|
314
|
-
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
315
|
-
let pixel = drawFullscreenAndRead(gl, prog, 0);
|
|
316
|
-
expect(pixelClose(pixel, [
|
|
317
|
-
255,
|
|
318
|
-
0,
|
|
319
|
-
0,
|
|
320
|
-
255
|
|
321
|
-
])).toBeTruthy();
|
|
322
|
-
gl.shaderSource(fs, FS_GREEN);
|
|
323
|
-
gl.compileShader(fs);
|
|
324
|
-
gl.linkProgram(prog);
|
|
325
|
-
expect(gl.getProgramParameter(prog, gl.LINK_STATUS)).toBeTruthy();
|
|
326
|
-
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
327
|
-
pixel = drawFullscreenAndRead(gl, prog, 0);
|
|
328
|
-
expect(pixelClose(pixel, [
|
|
329
|
-
0,
|
|
330
|
-
255,
|
|
331
|
-
0,
|
|
332
|
-
255
|
|
333
|
-
])).toBeTruthy();
|
|
334
|
-
destroyTestFBO(gl, fbo);
|
|
335
|
-
gl.deleteProgram(prog);
|
|
336
|
-
gl.deleteShader(vs);
|
|
337
|
-
gl.deleteShader(fs);
|
|
338
|
-
});
|
|
339
|
-
await it("relinking clears uniforms — output should be transparent black", async () => {
|
|
340
|
-
const fbo = makeTestFBO(gl, 2, 2);
|
|
341
|
-
const vs = compileShader(gl, gl.VERTEX_SHADER, VS_POSITION);
|
|
342
|
-
const fs = compileShader(gl, gl.FRAGMENT_SHADER, FS_SETTABLE);
|
|
343
|
-
const prog = gl.createProgram();
|
|
344
|
-
gl.attachShader(prog, vs);
|
|
345
|
-
gl.attachShader(prog, fs);
|
|
346
|
-
gl.bindAttribLocation(prog, 0, "a_position");
|
|
347
|
-
gl.linkProgram(prog);
|
|
348
|
-
gl.useProgram(prog);
|
|
349
|
-
const colorLoc = gl.getUniformLocation(prog, "u_color");
|
|
350
|
-
gl.uniform4f(colorLoc, 1, 0, 0, 1);
|
|
351
|
-
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
352
|
-
let pixel = drawFullscreenAndRead(gl, prog, 0);
|
|
353
|
-
expect(pixelClose(pixel, [
|
|
354
|
-
255,
|
|
355
|
-
0,
|
|
356
|
-
0,
|
|
357
|
-
255
|
|
358
|
-
])).toBeTruthy();
|
|
359
|
-
gl.linkProgram(prog);
|
|
360
|
-
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
361
|
-
pixel = drawFullscreenAndRead(gl, prog, 0);
|
|
362
|
-
expect(pixelClose(pixel, [
|
|
363
|
-
0,
|
|
364
|
-
0,
|
|
365
|
-
0,
|
|
366
|
-
0
|
|
367
|
-
])).toBeTruthy();
|
|
368
|
-
destroyTestFBO(gl, fbo);
|
|
369
|
-
gl.deleteProgram(prog);
|
|
370
|
-
gl.deleteShader(vs);
|
|
371
|
-
gl.deleteShader(fs);
|
|
372
|
-
});
|
|
373
|
-
});
|
|
374
|
-
await describe("conformance/programs/gl-shader-test", async () => {
|
|
375
|
-
beforeEach(async () => {
|
|
376
|
-
glArea.make_current();
|
|
377
|
-
});
|
|
378
|
-
await it("creating a GEOMETRY shader should return null", async () => {
|
|
379
|
-
const GEOMETRY_SHADER_ARB = 36313;
|
|
380
|
-
const shader = gl.createShader(GEOMETRY_SHADER_ARB);
|
|
381
|
-
expect(shader).toBeNull();
|
|
382
|
-
});
|
|
383
|
-
await it("deferred compilation: shader linked with source set after first compile", async () => {
|
|
384
|
-
const fbo = makeTestFBO(gl, 2, 2);
|
|
385
|
-
const vs = compileShader(gl, gl.VERTEX_SHADER, "attribute vec4 vPosition; void main() { gl_Position = vPosition; }");
|
|
386
|
-
const fs = compileShader(gl, gl.FRAGMENT_SHADER, FS_GREEN);
|
|
387
|
-
gl.shaderSource(fs, FS_RED);
|
|
388
|
-
const prog = gl.createProgram();
|
|
389
|
-
gl.attachShader(prog, vs);
|
|
390
|
-
gl.attachShader(prog, fs);
|
|
391
|
-
gl.bindAttribLocation(prog, 0, "vPosition");
|
|
392
|
-
gl.linkProgram(prog);
|
|
393
|
-
gl.useProgram(prog);
|
|
394
|
-
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
395
|
-
const pixel = drawFullscreenAndRead(gl, prog, 0);
|
|
396
|
-
expect(pixelClose(pixel, [
|
|
397
|
-
255,
|
|
398
|
-
0,
|
|
399
|
-
0,
|
|
400
|
-
255
|
|
401
|
-
])).toBeTruthy();
|
|
402
|
-
destroyTestFBO(gl, fbo);
|
|
403
|
-
gl.deleteProgram(prog);
|
|
404
|
-
gl.deleteShader(vs);
|
|
405
|
-
gl.deleteShader(fs);
|
|
406
|
-
});
|
|
407
|
-
});
|
|
408
|
-
await describe("conformance/programs/get-active-test: getActiveAttrib", async () => {
|
|
409
|
-
beforeEach(async () => {
|
|
410
|
-
glArea.make_current();
|
|
411
|
-
});
|
|
412
|
-
await it("getActiveAttrib returns correct info for standard attribs", async () => {
|
|
413
|
-
const prog = linkProgram(gl, VS_STANDARD, FS_STANDARD);
|
|
414
|
-
expect(gl.getProgramParameter(prog, gl.LINK_STATUS)).toBeTruthy();
|
|
415
|
-
const count = gl.getProgramParameter(prog, gl.ACTIVE_ATTRIBUTES);
|
|
416
|
-
expect(count).toBe(2);
|
|
417
|
-
const infos = [];
|
|
418
|
-
for (let i = 0; i < count; i++) {
|
|
419
|
-
const info = gl.getActiveAttrib(prog, i);
|
|
420
|
-
expect(info).not.toBeNull();
|
|
421
|
-
infos.push(info);
|
|
422
|
-
}
|
|
423
|
-
const names = infos.map((i) => i.name).sort();
|
|
424
|
-
expect(names).toContain("a_vertex");
|
|
425
|
-
expect(names).toContain("a_normal");
|
|
426
|
-
const vertexInfo = infos.find((i) => i.name === "a_vertex");
|
|
427
|
-
expect(vertexInfo.type).toBe(gl.FLOAT_VEC4);
|
|
428
|
-
expect(vertexInfo.size).toBe(1);
|
|
429
|
-
const normalInfo = infos.find((i) => i.name === "a_normal");
|
|
430
|
-
expect(normalInfo.type).toBe(gl.FLOAT_VEC3);
|
|
431
|
-
expect(normalInfo.size).toBe(1);
|
|
432
|
-
gl.deleteProgram(prog);
|
|
433
|
-
});
|
|
434
|
-
await it("getActiveAttrib with out-of-range index returns null and INVALID_VALUE", async () => {
|
|
435
|
-
const prog = linkProgram(gl, VS_STANDARD, FS_STANDARD);
|
|
436
|
-
const count = gl.getProgramParameter(prog, gl.ACTIVE_ATTRIBUTES);
|
|
437
|
-
const result = gl.getActiveAttrib(prog, count);
|
|
438
|
-
expect(result).toBeNull();
|
|
439
|
-
expect(gl.getError()).toBe(gl.INVALID_VALUE);
|
|
440
|
-
gl.deleteProgram(prog);
|
|
441
|
-
});
|
|
442
|
-
await it("getActiveAttrib with null program throws", async () => {
|
|
443
|
-
expect(() => gl.getActiveAttrib(null, 0)).toThrow();
|
|
444
|
-
});
|
|
445
|
-
});
|
|
446
|
-
await describe("conformance/programs/get-active-test: getActiveUniform", async () => {
|
|
447
|
-
beforeEach(async () => {
|
|
448
|
-
glArea.make_current();
|
|
449
|
-
});
|
|
450
|
-
await it("getActiveUniform returns correct info for u_modelViewProjMatrix", async () => {
|
|
451
|
-
const prog = linkProgram(gl, VS_STANDARD, FS_STANDARD);
|
|
452
|
-
const count = gl.getProgramParameter(prog, gl.ACTIVE_UNIFORMS);
|
|
453
|
-
expect(count).toBeGreaterThan(0);
|
|
454
|
-
let found = null;
|
|
455
|
-
for (let i = 0; i < count; i++) {
|
|
456
|
-
const info = gl.getActiveUniform(prog, i);
|
|
457
|
-
if (info?.name === "u_modelViewProjMatrix") found = info;
|
|
458
|
-
}
|
|
459
|
-
expect(found).not.toBeNull();
|
|
460
|
-
expect(found.type).toBe(gl.FLOAT_MAT4);
|
|
461
|
-
expect(found.size).toBe(1);
|
|
462
|
-
gl.deleteProgram(prog);
|
|
463
|
-
});
|
|
464
|
-
await it("getActiveUniform with out-of-range index returns null and INVALID_VALUE", async () => {
|
|
465
|
-
const prog = linkProgram(gl, VS_STANDARD, FS_STANDARD);
|
|
466
|
-
const count = gl.getProgramParameter(prog, gl.ACTIVE_UNIFORMS);
|
|
467
|
-
const result = gl.getActiveUniform(prog, count);
|
|
468
|
-
expect(result).toBeNull();
|
|
469
|
-
expect(gl.getError()).toBe(gl.INVALID_VALUE);
|
|
470
|
-
gl.deleteProgram(prog);
|
|
471
|
-
});
|
|
472
|
-
await it("getActiveUniform with null program throws", async () => {
|
|
473
|
-
expect(() => gl.getActiveUniform(null, 0)).toThrow();
|
|
474
|
-
});
|
|
475
|
-
});
|
|
476
|
-
win.destroy();
|
|
477
|
-
});
|
|
478
|
-
};
|
|
479
|
-
|
|
480
|
-
//#endregion
|
|
481
|
-
export { programs_spec_default as default };
|
|
7
|
+
void main() { gl_FragColor = vec4(1.0); }`;function _(e,t,n){let r=e.createShader(t);return e.shaderSource(r,n),e.compileShader(r),r}function v(e,t,n,r){let i=_(e,e.VERTEX_SHADER,t),a=_(e,e.FRAGMENT_SHADER,n),o=e.createProgram();if(e.attachShader(o,i),e.attachShader(o,a),r)for(let[t,n]of r)e.bindAttribLocation(o,n,t);return e.linkProgram(o),o}function y(e,t,n=`a_position`){let i=typeof n==`string`?e.getAttribLocation(t,n):n,a=e.createBuffer();return e.bindBuffer(e.ARRAY_BUFFER,a),e.bufferData(e.ARRAY_BUFFER,new Float32Array([-4,-4,4,-4,0,4]),e.STREAM_DRAW),e.enableVertexAttribArray(i),e.vertexAttribPointer(i,2,e.FLOAT,!1,0,0),e.drawArrays(e.TRIANGLES,0,3),e.disableVertexAttribArray(i),e.deleteBuffer(a),r(e,0,0)}var b=async()=>{await l(`Display`,async()=>{let r=i();if(!r){console.warn(`WebGL context not available — skipping conformance/programs tests`);return}let{gl:l,glArea:b,win:x}=r;b.make_current(),await o(`conformance/programs/program-test: compileShader`,async()=>{a(async()=>{b.make_current()}),await c(`good vertex shader should compile`,async()=>{let e=_(l,l.VERTEX_SHADER,`attribute vec4 aVertex; void main() { gl_Position = aVertex; }`);s(l.getShaderParameter(e,l.COMPILE_STATUS)).toBeTruthy(),l.deleteShader(e)}),await c(`good fragment shader should compile`,async()=>{let e=_(l,l.FRAGMENT_SHADER,`precision mediump float; void main() { gl_FragColor = vec4(1.0); }`);s(l.getShaderParameter(e,l.COMPILE_STATUS)).toBeTruthy(),l.deleteShader(e)}),await c(`getShaderParameter with desktop-only INFO_LOG_LENGTH returns null and INVALID_ENUM`,async()=>{let e=_(l,l.VERTEX_SHADER,`attribute vec4 v; void main() { gl_Position = v; }`);s(l.getShaderParameter(e,35716)).toBeNull(),s(l.getError()).toBe(l.INVALID_ENUM),l.deleteShader(e)})}),await o(`conformance/programs/program-test: attachShader / detachShader`,async()=>{a(async()=>{b.make_current()}),await c(`attaching a vertex shader succeeds`,async()=>{let e=_(l,l.VERTEX_SHADER,d),t=l.createProgram();l.attachShader(t,e),s(l.getError()).toBe(l.NO_ERROR),l.deleteProgram(t),l.deleteShader(e)}),await c(`attaching the same shader twice generates INVALID_OPERATION`,async()=>{let e=_(l,l.VERTEX_SHADER,d),t=l.createProgram();l.attachShader(t,e),l.getError(),l.attachShader(t,e),s(l.getError()).toBe(l.INVALID_OPERATION),l.deleteProgram(t),l.deleteShader(e)}),await c(`attaching two vertex shaders to same program generates INVALID_OPERATION`,async()=>{let e=_(l,l.VERTEX_SHADER,d),t=_(l,l.VERTEX_SHADER,`attribute vec4 v; void main() { gl_Position = v * 0.5; }`),n=l.createProgram();l.attachShader(n,e),l.getError(),l.attachShader(n,t),s(l.getError()).toBe(l.INVALID_OPERATION),l.deleteProgram(n),l.deleteShader(e),l.deleteShader(t)}),await c(`detaching an attached shader succeeds`,async()=>{let e=_(l,l.VERTEX_SHADER,d),t=l.createProgram();l.attachShader(t,e),l.detachShader(t,e),s(l.getError()).toBe(l.NO_ERROR),l.deleteProgram(t),l.deleteShader(e)}),await c(`detaching a non-attached shader generates INVALID_OPERATION`,async()=>{let e=_(l,l.VERTEX_SHADER,d),t=_(l,l.FRAGMENT_SHADER,f),n=l.createProgram();l.attachShader(n,t),l.getError(),l.detachShader(n,e),s(l.getError()).toBe(l.INVALID_OPERATION),l.deleteProgram(n),l.deleteShader(e),l.deleteShader(t)})}),await o(`conformance/programs/program-test: getAttachedShaders`,async()=>{a(async()=>{b.make_current()}),await c(`empty program returns empty list`,async()=>{let e=l.createProgram();s(l.getAttachedShaders(e)?.length).toBe(0),l.deleteProgram(e)}),await c(`attached shaders appear in getAttachedShaders`,async()=>{let e=_(l,l.VERTEX_SHADER,d),t=_(l,l.FRAGMENT_SHADER,f),n=l.createProgram();l.attachShader(n,e),l.attachShader(n,t);let r=l.getAttachedShaders(n);s(r.length).toBe(2),s(r.includes(e)).toBeTruthy(),s(r.includes(t)).toBeTruthy(),l.deleteProgram(n),l.deleteShader(e),l.deleteShader(t)}),await c(`detached shaders are removed from getAttachedShaders`,async()=>{let e=_(l,l.VERTEX_SHADER,d),t=_(l,l.FRAGMENT_SHADER,f),n=l.createProgram();l.attachShader(n,e),l.attachShader(n,t),l.detachShader(n,e);let r=l.getAttachedShaders(n);s(r.length).toBe(1),s(r.includes(t)).toBeTruthy(),l.deleteProgram(n),l.deleteShader(e),l.deleteShader(t)})}),await o(`conformance/programs/program-test: linkProgram / useProgram`,async()=>{a(async()=>{b.make_current()}),await c(`valid program should link`,async()=>{let e=v(l,d,f,[[`aVertex`,0],[`aColor`,1]]);s(l.getProgramParameter(e,l.LINK_STATUS)).toBeTruthy(),s(typeof l.getProgramInfoLog(e)).toBe(`string`),l.deleteProgram(e)}),await c(`program with no fragment shader should fail to link`,async()=>{let e=_(l,l.VERTEX_SHADER,d),t=l.createProgram();l.attachShader(t,e),l.linkProgram(t),s(l.getProgramParameter(t,l.LINK_STATUS)).toBeFalsy(),l.deleteProgram(t),l.deleteShader(e)}),await c(`program with no vertex shader should fail to link`,async()=>{let e=_(l,l.FRAGMENT_SHADER,f),t=l.createProgram();l.attachShader(t,e),l.linkProgram(t),s(l.getProgramParameter(t,l.LINK_STATUS)).toBeFalsy(),l.deleteProgram(t),l.deleteShader(e)}),await c(`using a valid program should succeed`,async()=>{let e=v(l,d,f,[[`aVertex`,0],[`aColor`,1]]);l.useProgram(e),s(l.getError()).toBe(l.NO_ERROR),l.useProgram(null),l.deleteProgram(e)}),await c(`using an invalid (unlinked) program should generate INVALID_OPERATION`,async()=>{let e=_(l,l.VERTEX_SHADER,d),t=l.createProgram();l.attachShader(t,e),l.linkProgram(t),l.useProgram(t),s(l.getError()).toBe(l.INVALID_OPERATION),l.deleteProgram(t),l.deleteShader(e)}),await c(`drawing with null program generates INVALID_OPERATION`,async()=>{let n=v(l,u,p,[[`a_position`,0]]),r=t(l,2,2),i=l.createBuffer();l.bindBuffer(l.ARRAY_BUFFER,i),l.bufferData(l.ARRAY_BUFFER,new Float32Array([0,0,1,0,0,1]),l.STATIC_DRAW),l.vertexAttribPointer(0,2,l.FLOAT,!1,0,0),l.enableVertexAttribArray(0),l.useProgram(null),l.drawArrays(l.TRIANGLES,0,3),s(l.getError()).toBe(l.INVALID_OPERATION),l.disableVertexAttribArray(0),l.deleteBuffer(i),e(l,r),l.deleteProgram(n)})}),await o(`conformance/programs/program-test: deleteProgram / deleteShader`,async()=>{a(async()=>{b.make_current()}),await c(`deleting the current program does not affect the current rendering state`,async()=>{let r=v(l,u,p,[[`a_position`,0]]);l.useProgram(r),l.deleteProgram(r);let i=t(l,2,2),a=y(l,r,0);s(l.getError()).toBe(l.NO_ERROR),s(n(a,[255,0,0,255])).toBeTruthy(),e(l,i),l.useProgram(null)}),await c(`unattached deleted shader is invalid immediately`,async()=>{let e=_(l,l.FRAGMENT_SHADER,p);l.deleteShader(e),l.compileShader(e),s(l.getError()).toBe(l.INVALID_VALUE)}),await c(`attached deleted shader is still valid while attached`,async()=>{let e=_(l,l.VERTEX_SHADER,u),t=_(l,l.FRAGMENT_SHADER,p),n=v(l,u,p,[[`a_position`,0]]);l.attachShader(n,e),l.getError();let r=_(l,l.FRAGMENT_SHADER,m),i=l.createProgram();l.attachShader(i,e),l.attachShader(i,r),l.deleteShader(r),l.compileShader(r),s(l.getShaderParameter(r,l.COMPILE_STATUS)).toBeTruthy(),l.deleteProgram(n),l.deleteProgram(i),l.deleteShader(e),l.deleteShader(t)})}),await o(`conformance/programs/program-test: relink updates rendering`,async()=>{a(async()=>{b.make_current()}),await c(`relinking with a new fragment shader updates the program output`,async()=>{let r=t(l,2,2),i=_(l,l.VERTEX_SHADER,u),a=_(l,l.FRAGMENT_SHADER,p),o=l.createProgram();l.attachShader(o,i),l.attachShader(o,a),l.bindAttribLocation(o,0,`a_position`),l.linkProgram(o),l.useProgram(o),s(l.getProgramParameter(o,l.LINK_STATUS)).toBeTruthy(),l.clear(l.COLOR_BUFFER_BIT);let c=y(l,o,0);s(n(c,[255,0,0,255])).toBeTruthy(),l.shaderSource(a,m),l.compileShader(a),l.linkProgram(o),s(l.getProgramParameter(o,l.LINK_STATUS)).toBeTruthy(),l.clear(l.COLOR_BUFFER_BIT),c=y(l,o,0),s(n(c,[0,255,0,255])).toBeTruthy(),e(l,r),l.deleteProgram(o),l.deleteShader(i),l.deleteShader(a)}),await c(`relinking clears uniforms — output should be transparent black`,async()=>{let r=t(l,2,2),i=_(l,l.VERTEX_SHADER,u),a=_(l,l.FRAGMENT_SHADER,`precision mediump float; uniform vec4 u_color; void main() { gl_FragColor = u_color; }`),o=l.createProgram();l.attachShader(o,i),l.attachShader(o,a),l.bindAttribLocation(o,0,`a_position`),l.linkProgram(o),l.useProgram(o);let c=l.getUniformLocation(o,`u_color`);l.uniform4f(c,1,0,0,1),l.clear(l.COLOR_BUFFER_BIT);let d=y(l,o,0);s(n(d,[255,0,0,255])).toBeTruthy(),l.linkProgram(o),l.clear(l.COLOR_BUFFER_BIT),d=y(l,o,0),s(n(d,[0,0,0,0])).toBeTruthy(),e(l,r),l.deleteProgram(o),l.deleteShader(i),l.deleteShader(a)})}),await o(`conformance/programs/gl-shader-test`,async()=>{a(async()=>{b.make_current()}),await c(`creating a GEOMETRY shader should return null`,async()=>{s(l.createShader(36313)).toBeNull()}),await c(`deferred compilation: shader linked with source set after first compile`,async()=>{let r=t(l,2,2),i=_(l,l.VERTEX_SHADER,`attribute vec4 vPosition; void main() { gl_Position = vPosition; }`),a=_(l,l.FRAGMENT_SHADER,m);l.shaderSource(a,p);let o=l.createProgram();l.attachShader(o,i),l.attachShader(o,a),l.bindAttribLocation(o,0,`vPosition`),l.linkProgram(o),l.useProgram(o),l.clear(l.COLOR_BUFFER_BIT),s(n(y(l,o,0),[255,0,0,255])).toBeTruthy(),e(l,r),l.deleteProgram(o),l.deleteShader(i),l.deleteShader(a)})}),await o(`conformance/programs/get-active-test: getActiveAttrib`,async()=>{a(async()=>{b.make_current()}),await c(`getActiveAttrib returns correct info for standard attribs`,async()=>{let e=v(l,h,g);s(l.getProgramParameter(e,l.LINK_STATUS)).toBeTruthy();let t=l.getProgramParameter(e,l.ACTIVE_ATTRIBUTES);s(t).toBe(2);let n=[];for(let r=0;r<t;r++){let t=l.getActiveAttrib(e,r);s(t).not.toBeNull(),n.push(t)}let r=n.map(e=>e.name).sort();s(r).toContain(`a_vertex`),s(r).toContain(`a_normal`);let i=n.find(e=>e.name===`a_vertex`);s(i.type).toBe(l.FLOAT_VEC4),s(i.size).toBe(1);let a=n.find(e=>e.name===`a_normal`);s(a.type).toBe(l.FLOAT_VEC3),s(a.size).toBe(1),l.deleteProgram(e)}),await c(`getActiveAttrib with out-of-range index returns null and INVALID_VALUE`,async()=>{let e=v(l,h,g),t=l.getProgramParameter(e,l.ACTIVE_ATTRIBUTES);s(l.getActiveAttrib(e,t)).toBeNull(),s(l.getError()).toBe(l.INVALID_VALUE),l.deleteProgram(e)}),await c(`getActiveAttrib with null program throws`,async()=>{s(()=>l.getActiveAttrib(null,0)).toThrow()})}),await o(`conformance/programs/get-active-test: getActiveUniform`,async()=>{a(async()=>{b.make_current()}),await c(`getActiveUniform returns correct info for u_modelViewProjMatrix`,async()=>{let e=v(l,h,g),t=l.getProgramParameter(e,l.ACTIVE_UNIFORMS);s(t).toBeGreaterThan(0);let n=null;for(let r=0;r<t;r++){let t=l.getActiveUniform(e,r);t?.name===`u_modelViewProjMatrix`&&(n=t)}s(n).not.toBeNull(),s(n.type).toBe(l.FLOAT_MAT4),s(n.size).toBe(1),l.deleteProgram(e)}),await c(`getActiveUniform with out-of-range index returns null and INVALID_VALUE`,async()=>{let e=v(l,h,g),t=l.getProgramParameter(e,l.ACTIVE_UNIFORMS);s(l.getActiveUniform(e,t)).toBeNull(),s(l.getError()).toBe(l.INVALID_VALUE),l.deleteProgram(e)}),await c(`getActiveUniform with null program throws`,async()=>{s(()=>l.getActiveUniform(null,0)).toThrow()})}),x.destroy()})};export{b as default};
|
|
@@ -1,142 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { createGLSetup } from "./setup.js";
|
|
3
|
-
import { beforeEach, describe, expect, it, on } from "@gjsify/unit";
|
|
4
|
-
|
|
5
|
-
//#region src/ts/conformance/rendering-basic.spec.ts
|
|
6
|
-
const VS_SRC = `
|
|
1
|
+
import{destroyTestFBO as e,drawTriangle as t,makeProgram as n,makeTestFBO as r,pixelClose as i}from"../test-utils.js";import{createGLSetup as a}from"./setup.js";import{beforeEach as o,describe as s,expect as c,it as l,on as u}from"@gjsify/unit";const d=`
|
|
7
2
|
attribute vec2 position;
|
|
8
|
-
void main() { gl_Position = vec4(position, 0.0, 1.0); }
|
|
9
|
-
|
|
10
|
-
void main() { gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); }`;
|
|
11
|
-
var rendering_basic_spec_default = async () => {
|
|
12
|
-
await on("Display", async () => {
|
|
13
|
-
const setup = createGLSetup();
|
|
14
|
-
if (!setup) {
|
|
15
|
-
console.warn("WebGL context not available — skipping conformance/rendering-basic tests");
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
18
|
-
const { gl, glArea } = setup;
|
|
19
|
-
glArea.make_current();
|
|
20
|
-
await describe("rendering-basic/clear-color", async () => {
|
|
21
|
-
beforeEach(async () => {
|
|
22
|
-
glArea.make_current();
|
|
23
|
-
});
|
|
24
|
-
const W = 10, H = 10;
|
|
25
|
-
function testColor(r, g, b, a) {
|
|
26
|
-
const fbo = makeTestFBO(gl, W, H);
|
|
27
|
-
gl.clearColor(r / 255, g / 255, b / 255, a / 255);
|
|
28
|
-
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
29
|
-
const pixels = new Uint8Array(W * H * 4);
|
|
30
|
-
gl.readPixels(0, 0, W, H, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
|
|
31
|
-
destroyTestFBO(gl, fbo);
|
|
32
|
-
for (let i = 0; i < W * H * 4; i += 4) {
|
|
33
|
-
if (pixels[i] !== r || pixels[i + 1] !== g || pixels[i + 2] !== b || pixels[i + 3] !== a) return false;
|
|
34
|
-
}
|
|
35
|
-
return true;
|
|
36
|
-
}
|
|
37
|
-
await it("clearColor black (0,0,0,0) fills all pixels", async () => {
|
|
38
|
-
expect(testColor(0, 0, 0, 0)).toBe(true);
|
|
39
|
-
});
|
|
40
|
-
await it("clearColor white (255,255,255,255) fills all pixels", async () => {
|
|
41
|
-
expect(testColor(255, 255, 255, 255)).toBe(true);
|
|
42
|
-
});
|
|
43
|
-
await it("clearColor green (0,255,0,255) fills all pixels", async () => {
|
|
44
|
-
expect(testColor(0, 255, 0, 255)).toBe(true);
|
|
45
|
-
});
|
|
46
|
-
await it("clearColor magenta (255,0,255,0) fills all pixels", async () => {
|
|
47
|
-
expect(testColor(255, 0, 255, 0)).toBe(true);
|
|
48
|
-
});
|
|
49
|
-
});
|
|
50
|
-
await describe("rendering-basic/simple-shader", async () => {
|
|
51
|
-
beforeEach(async () => {
|
|
52
|
-
glArea.make_current();
|
|
53
|
-
});
|
|
54
|
-
await it("fullscreen green triangle covers every pixel", async () => {
|
|
55
|
-
const W = 50, H = 50;
|
|
56
|
-
const fbo = makeTestFBO(gl, W, H);
|
|
57
|
-
gl.clearColor(0, 0, 0, 0);
|
|
58
|
-
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
59
|
-
const prog = makeProgram(gl, VS_SRC, FS_GREEN);
|
|
60
|
-
gl.useProgram(prog);
|
|
61
|
-
drawTriangle(gl);
|
|
62
|
-
const pixels = new Uint8Array(W * H * 4);
|
|
63
|
-
gl.readPixels(0, 0, W, H, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
|
|
64
|
-
destroyTestFBO(gl, fbo);
|
|
65
|
-
let allGreen = true;
|
|
66
|
-
for (let i = 0; i < W * H * 4; i += 4) {
|
|
67
|
-
if (!pixelClose(pixels.subarray(i, i + 4), [
|
|
68
|
-
0,
|
|
69
|
-
255,
|
|
70
|
-
0,
|
|
71
|
-
255
|
|
72
|
-
])) {
|
|
73
|
-
allGreen = false;
|
|
74
|
-
break;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
expect(allGreen).toBe(true);
|
|
78
|
-
expect(gl.getError()).toBe(gl.NO_ERROR);
|
|
79
|
-
});
|
|
80
|
-
});
|
|
81
|
-
await describe("rendering-basic/draw-indexed", async () => {
|
|
82
|
-
beforeEach(async () => {
|
|
83
|
-
glArea.make_current();
|
|
84
|
-
});
|
|
85
|
-
await it("drawElements covers every pixel with green", async () => {
|
|
86
|
-
const W = 50, H = 50;
|
|
87
|
-
const fbo = makeTestFBO(gl, W, H);
|
|
88
|
-
gl.clearColor(1, 0, 0, 1);
|
|
89
|
-
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
90
|
-
const prog = makeProgram(gl, VS_SRC, FS_GREEN);
|
|
91
|
-
gl.useProgram(prog);
|
|
92
|
-
const vbuffer = gl.createBuffer();
|
|
93
|
-
gl.bindBuffer(gl.ARRAY_BUFFER, vbuffer);
|
|
94
|
-
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
|
|
95
|
-
-1,
|
|
96
|
-
-1,
|
|
97
|
-
1,
|
|
98
|
-
-1,
|
|
99
|
-
-1,
|
|
100
|
-
1,
|
|
101
|
-
1,
|
|
102
|
-
1
|
|
103
|
-
]), gl.STATIC_DRAW);
|
|
104
|
-
gl.enableVertexAttribArray(0);
|
|
105
|
-
gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
|
|
106
|
-
const ebuffer = gl.createBuffer();
|
|
107
|
-
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ebuffer);
|
|
108
|
-
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array([
|
|
109
|
-
0,
|
|
110
|
-
1,
|
|
111
|
-
2,
|
|
112
|
-
2,
|
|
113
|
-
1,
|
|
114
|
-
3
|
|
115
|
-
]), gl.STATIC_DRAW);
|
|
116
|
-
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
|
|
117
|
-
const pixels = new Uint8Array(W * H * 4);
|
|
118
|
-
gl.readPixels(0, 0, W, H, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
|
|
119
|
-
gl.deleteBuffer(vbuffer);
|
|
120
|
-
gl.deleteBuffer(ebuffer);
|
|
121
|
-
destroyTestFBO(gl, fbo);
|
|
122
|
-
let allGreen = true;
|
|
123
|
-
for (let i = 0; i < W * H * 4; i += 4) {
|
|
124
|
-
if (!pixelClose(pixels.subarray(i, i + 4), [
|
|
125
|
-
0,
|
|
126
|
-
255,
|
|
127
|
-
0,
|
|
128
|
-
255
|
|
129
|
-
])) {
|
|
130
|
-
allGreen = false;
|
|
131
|
-
break;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
expect(allGreen).toBe(true);
|
|
135
|
-
expect(gl.getError()).toBe(gl.NO_ERROR);
|
|
136
|
-
});
|
|
137
|
-
});
|
|
138
|
-
});
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
//#endregion
|
|
142
|
-
export { rendering_basic_spec_default as default };
|
|
3
|
+
void main() { gl_Position = vec4(position, 0.0, 1.0); }`,f=`
|
|
4
|
+
void main() { gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); }`;var p=async()=>{await u(`Display`,async()=>{let u=a();if(!u){console.warn(`WebGL context not available — skipping conformance/rendering-basic tests`);return}let{gl:p,glArea:m}=u;m.make_current(),await s(`rendering-basic/clear-color`,async()=>{o(async()=>{m.make_current()});function t(t,n,i,a){let o=r(p,10,10);p.clearColor(t/255,n/255,i/255,a/255),p.clear(p.COLOR_BUFFER_BIT);let s=new Uint8Array(400);p.readPixels(0,0,10,10,p.RGBA,p.UNSIGNED_BYTE,s),e(p,o);for(let e=0;e<400;e+=4)if(s[e]!==t||s[e+1]!==n||s[e+2]!==i||s[e+3]!==a)return!1;return!0}await l(`clearColor black (0,0,0,0) fills all pixels`,async()=>{c(t(0,0,0,0)).toBe(!0)}),await l(`clearColor white (255,255,255,255) fills all pixels`,async()=>{c(t(255,255,255,255)).toBe(!0)}),await l(`clearColor green (0,255,0,255) fills all pixels`,async()=>{c(t(0,255,0,255)).toBe(!0)}),await l(`clearColor magenta (255,0,255,0) fills all pixels`,async()=>{c(t(255,0,255,0)).toBe(!0)})}),await s(`rendering-basic/simple-shader`,async()=>{o(async()=>{m.make_current()}),await l(`fullscreen green triangle covers every pixel`,async()=>{let a=r(p,50,50);p.clearColor(0,0,0,0),p.clear(p.COLOR_BUFFER_BIT);let o=n(p,d,f);p.useProgram(o),t(p);let s=new Uint8Array(2500*4);p.readPixels(0,0,50,50,p.RGBA,p.UNSIGNED_BYTE,s),e(p,a);let l=!0;for(let e=0;e<2500*4;e+=4)if(!i(s.subarray(e,e+4),[0,255,0,255])){l=!1;break}c(l).toBe(!0),c(p.getError()).toBe(p.NO_ERROR)})}),await s(`rendering-basic/draw-indexed`,async()=>{o(async()=>{m.make_current()}),await l(`drawElements covers every pixel with green`,async()=>{let t=r(p,50,50);p.clearColor(1,0,0,1),p.clear(p.COLOR_BUFFER_BIT);let a=n(p,d,f);p.useProgram(a);let o=p.createBuffer();p.bindBuffer(p.ARRAY_BUFFER,o),p.bufferData(p.ARRAY_BUFFER,new Float32Array([-1,-1,1,-1,-1,1,1,1]),p.STATIC_DRAW),p.enableVertexAttribArray(0),p.vertexAttribPointer(0,2,p.FLOAT,!1,0,0);let s=p.createBuffer();p.bindBuffer(p.ELEMENT_ARRAY_BUFFER,s),p.bufferData(p.ELEMENT_ARRAY_BUFFER,new Uint16Array([0,1,2,2,1,3]),p.STATIC_DRAW),p.drawElements(p.TRIANGLES,6,p.UNSIGNED_SHORT,0);let l=new Uint8Array(2500*4);p.readPixels(0,0,50,50,p.RGBA,p.UNSIGNED_BYTE,l),p.deleteBuffer(o),p.deleteBuffer(s),e(p,t);let u=!0;for(let e=0;e<2500*4;e+=4)if(!i(l.subarray(e,e+4),[0,255,0,255])){u=!1;break}c(u).toBe(!0),c(p.getError()).toBe(p.NO_ERROR)})})})};export{p as default};
|