@gjsify/webgl 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/esm/canvas-webgl-widget.js +12 -0
- package/lib/esm/conformance/attribs.spec.js +296 -0
- package/lib/esm/conformance/buffers.spec.js +203 -0
- package/lib/esm/conformance/context.spec.js +302 -0
- package/lib/esm/conformance/programs.spec.js +468 -0
- package/lib/esm/conformance/rendering-basic.spec.js +136 -0
- package/lib/esm/conformance/rendering.spec.js +424 -0
- package/lib/esm/conformance/setup.js +36 -0
- package/lib/esm/conformance/state.spec.js +348 -0
- package/lib/esm/conformance/textures.spec.js +354 -0
- package/lib/esm/conformance/uniforms.spec.js +305 -0
- package/lib/esm/conformance-test.js +23 -0
- package/lib/esm/extensions/ext-color-buffer-float.js +13 -0
- package/lib/esm/extensions/ext-color-buffer-half-float.js +13 -0
- package/lib/esm/extensions/oes-texture-half-float.js +19 -0
- package/lib/esm/index.js +5 -0
- package/lib/esm/test-utils.js +65 -0
- package/lib/esm/test.js +2 -2
- package/lib/esm/webgl-buffer.js +1 -1
- package/lib/esm/webgl-context-base.js +3371 -0
- package/lib/esm/webgl-framebuffer.js +1 -1
- package/lib/esm/webgl-program.js +1 -1
- package/lib/esm/webgl-renderbuffer.js +1 -1
- package/lib/esm/webgl-rendering-context.js +95 -3253
- package/lib/esm/webgl-shader.js +2 -1
- package/lib/esm/webgl-texture.js +1 -1
- package/lib/esm/{index.spec.js → webgl1.spec.js} +2 -2
- package/lib/esm/webgl2-rendering-context.js +617 -27
- package/lib/esm/webgl2.spec.js +573 -1
- package/lib/types/conformance/setup.d.ts +14 -0
- package/lib/types/extensions/ext-blend-minmax.d.ts +2 -2
- package/lib/types/extensions/ext-color-buffer-float.d.ts +4 -0
- package/lib/types/extensions/ext-color-buffer-half-float.d.ts +4 -0
- package/lib/types/extensions/ext-texture-filter-anisotropic.d.ts +2 -2
- package/lib/types/extensions/oes-element-index-unit.d.ts +2 -2
- package/lib/types/extensions/oes-standard-derivatives.d.ts +2 -2
- package/lib/types/extensions/oes-texture-float-linear.d.ts +2 -2
- package/lib/types/extensions/oes-texture-float.d.ts +2 -2
- package/lib/types/extensions/oes-texture-half-float.d.ts +5 -0
- package/lib/types/extensions/stackgl-destroy-context.d.ts +3 -3
- package/lib/types/extensions/stackgl-resize-drawing-buffer.d.ts +3 -3
- package/lib/types/index.d.ts +1 -0
- package/lib/types/test-utils.d.ts +24 -0
- package/lib/types/types/extension.d.ts +2 -2
- package/lib/types/utils.d.ts +9 -10
- package/lib/types/webgl-buffer.d.ts +3 -3
- package/lib/types/webgl-context-base.d.ts +267 -0
- package/lib/types/webgl-framebuffer.d.ts +3 -3
- package/lib/types/webgl-program.d.ts +3 -3
- package/lib/types/webgl-renderbuffer.d.ts +3 -3
- package/lib/types/webgl-rendering-context.d.ts +5 -250
- package/lib/types/webgl-shader.d.ts +4 -3
- package/lib/types/webgl-texture-unit.d.ts +3 -3
- package/lib/types/webgl-texture.d.ts +3 -3
- package/lib/types/webgl-vertex-attribute.d.ts +5 -5
- package/lib/types/webgl2-rendering-context.d.ts +95 -6
- package/package.json +13 -11
- package/prebuilds/linux-x86_64/Gwebgl-0.1.typelib +0 -0
- package/prebuilds/linux-x86_64/libgwebgl.so +0 -0
|
@@ -0,0 +1,424 @@
|
|
|
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";
|
|
11
|
+
import { createGLSetup } from "./setup.js";
|
|
12
|
+
const VS = `
|
|
13
|
+
precision mediump float;
|
|
14
|
+
attribute vec2 position;
|
|
15
|
+
void main() { gl_Position = vec4(position, 0.0, 1.0); }`;
|
|
16
|
+
const VS_DEPTH = `
|
|
17
|
+
attribute vec2 position;
|
|
18
|
+
uniform float depth;
|
|
19
|
+
void main() { gl_Position = vec4(position, depth, 1.0); }`;
|
|
20
|
+
const FS_COLOR = `
|
|
21
|
+
precision mediump float;
|
|
22
|
+
uniform vec4 color;
|
|
23
|
+
void main() { gl_FragColor = color; }`;
|
|
24
|
+
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 = `
|
|
41
|
+
precision mediump float;
|
|
42
|
+
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 = `
|
|
283
|
+
precision mediump float;
|
|
284
|
+
uniform float u_z;
|
|
285
|
+
attribute vec2 a_position;
|
|
286
|
+
void main() { gl_Position = vec4(a_position, u_z, 1.0); }`;
|
|
287
|
+
const fsSrc = `
|
|
288
|
+
precision mediump float;
|
|
289
|
+
uniform vec4 u_color;
|
|
290
|
+
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
|
|
424
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { CanvasWebGLWidget } from "@gjsify/webgl";
|
|
2
|
+
import GLib from "@girs/glib-2.0";
|
|
3
|
+
import Gtk from "@girs/gtk-4.0";
|
|
4
|
+
function createGLSetup() {
|
|
5
|
+
Gtk.init();
|
|
6
|
+
let result = null;
|
|
7
|
+
const readyLoop = new GLib.MainLoop(null, false);
|
|
8
|
+
const win = new Gtk.Window({});
|
|
9
|
+
win.set_default_size(200, 200);
|
|
10
|
+
const glArea = new CanvasWebGLWidget();
|
|
11
|
+
glArea.onReady((canvas, g) => {
|
|
12
|
+
try {
|
|
13
|
+
const gl = g;
|
|
14
|
+
let gl2 = null;
|
|
15
|
+
try {
|
|
16
|
+
gl2 = canvas.getContext("webgl2");
|
|
17
|
+
} catch (_) {
|
|
18
|
+
}
|
|
19
|
+
result = { gl, gl2, glArea, win };
|
|
20
|
+
} finally {
|
|
21
|
+
readyLoop.quit();
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
win.set_child(glArea);
|
|
25
|
+
win.present();
|
|
26
|
+
const giveUpId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 1e4, () => {
|
|
27
|
+
readyLoop.quit();
|
|
28
|
+
return GLib.SOURCE_REMOVE;
|
|
29
|
+
});
|
|
30
|
+
readyLoop.run();
|
|
31
|
+
GLib.source_remove(giveUpId);
|
|
32
|
+
return result;
|
|
33
|
+
}
|
|
34
|
+
export {
|
|
35
|
+
createGLSetup
|
|
36
|
+
};
|