Вы говорите, что никогда не использовали WebGL. Это говорит о том, что вам нужны несколько руководств , потому что как использовать WebGL не то, что можно объяснить одним ответом на переполнение стека.
Самый распространенный способ нарисовать круг с отверстием в нем. в WebGL - это создание треугольников, образующих круг с отверстием в нем. Это то, что делают все основные библиотеки 2D-графики с ускорением на GPU.
function makeCircleTriangles(innerRadius, outerRadius, divisions, start = 0, end = Math.PI * 2) {
const positions = [];
for (let d = 0; d <= divisions; ++d) {
const u = d / divisions;
const angle = start + (end - start) * u;
const s = Math.sin(angle);
const c = Math.cos(angle);
positions.push(c * innerRadius, s * innerRadius);
positions.push(c * outerRadius, s * outerRadius);
}
const indices = [];
for (let d = 0; d < divisions; ++d) {
const offset = d * 2;
indices.push(offset + 0, offset + 1, offset + 2);
indices.push(offset + 2, offset + 1, offset + 3);
}
return {position, indices};
}
const gl = document.querySelector('canvas').getContext('webgl');
const vs = `
attribute vec4 position;
uniform mat4 matrix;
void main() {
gl_Position = matrix * position;
}
`;
const fs = `
precision highp float;
void main() {
gl_FragColor = vec4(0, .6, 0, 1);
}
`;
// compile shaders, link progrma, look up locations
const programInfo = twgl.createProgramInfo(gl, [vs, fs]);
const {positions, indices} = makeCircleTriangles(30, 70, 64);
// calls gl.createBuffer, gl.bindBuffer, gl.bufferData for each array
const bufferInfo = twgl.createBufferInfoFromArrays(gl, {
position: { numComponents: 2, data: positions },
indices,
});
gl.useProgram(programInfo.program);
// calls gl.bindBuffer, gl.enableVertexAttribArray, gl.vertexAttribPointer
twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
// calls gl.uniform
twgl.setUniforms(programInfo, {
matrix: [
2 / gl.canvas.clientWidth, 0, 0, 0,
0, 2 / gl.canvas.clientHeight, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
],
});
gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);
function makeCircleTriangles(innerRadius, outerRadius, divisions, start = 0, end = Math.PI * 2) {
const positions = [];
for (let d = 0; d <= divisions; ++d) {
const u = d / divisions;
const angle = start + (end - start) * u;
const s = Math.sin(angle);
const c = Math.cos(angle);
positions.push(c * innerRadius, s * innerRadius);
positions.push(c * outerRadius, s * outerRadius);
}
const indices = [];
for (let d = 0; d < divisions; ++d) {
const offset = d * 2;
indices.push(offset + 0, offset + 1, offset + 2);
indices.push(offset + 2, offset + 1, offset + 3);
}
return {positions, indices};
}
<canvas></canvas>
<script src="https://twgljs.org/dist/4.x/twgl.min.js"></script>
Второй наиболее распространенный способ - нарисовать четырехугольник (2 треугольника) с текстурой круга с отверстием в нем.