Я могу использовать WebGL внутри рабочих и хорошо с этим работать. Но мне также нужно использовать fabri c. js по многим причинам.
Теперь проблема в том, что я могу использовать WebGL в javascript главном потоке, но когда дело доходит до работника, сталкиваюсь с 2 проблемы:
Я не могу вернуть холст Offscreen обратно в основной поток от работника, чтобы я мог использовать его внутри fabri c. js canvas.
Я не могу использовать библиотеку fabri c. js внутри Web Worker с использованием importScripts.
Код:
<canvas id="canvas" width="500" height="500"></canvas>
<canvas id="c2"></canvas>
main.js
---------
var canvas = document.getElementById('canvas');
var offscreen = canvas.transferControlToOffscreen();
var canvas2 = new fabric.Canvas('c2');
var worker = new Worker("offscreencanvas.js");
console.log(canvas2);
var rect = new fabric.Rect({
top : 100,
left : 100,
width : 60,
height : 70,
fill : 'red'
});
canvas2.add(rect);
worker.postMessage({
canvas: offscreen,
fabric : fabric
}, [offscreen]);
worker.onmessage = (e) => {
console.log(e);
};
offscreen.js
-------------
importScripts('./fabric.js');
var vertexShader = `#version 300 es
precision mediump float;
in vec2 position;//vertices : WebGL vertex coordinates
in vec2 texCoords;// Texture coordinates
out vec2 textureCoords; //Take input from vertex shader and serve to fragment shader
void main () {
gl_Position = vec4(position, 0.0, 1.0);
textureCoords = texCoords;
}
`;
var fragmentShader = `#version 300 es
precision mediump float;
out vec4 color;
void main() {
color = vec4(1.0, 0.0, 0.0, 1.0);
}
`;
getShader = (gl, shaderSource, shaderType) => {
var shader = gl.createShader(shaderType);
gl.shaderSource(shader, shaderSource);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
console.error(gl.getShaderInfoLog(shader));
}
return shader;
};
getProgram = (gl, vertexShaderSource, fragmentShaderSource) => {
var vs = getShader(gl, vertexShaderSource, gl.VERTEX_SHADER);
var fs = getShader(gl, fragmentShaderSource, gl.FRAGMENT_SHADER);
var program = gl.createProgram();
gl.attachShader(program, vs);
gl.attachShader(program, fs);
gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
console.error(gl.getProgramInfoLog(program));
}
return program;
};
createAndBindBuffer = (gl, bufferType, typeOfDrawing, data) => {
var buffer = gl.createBuffer();
gl.bindBuffer(bufferType, buffer);
gl.bufferData(bufferType, data, typeOfDrawing);
gl.bindBuffer(bufferType, null);
return buffer;
};
createAndBindTexture = (gl, image, width, height) => {
var texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
if (width && height) {
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, image);
} else {
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
}
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.bindTexture(gl.TEXTURE_2D, null);
return texture;
};
const prepareRectVec2 = (startX, startY, endX, endY) => {
return [startX, startY, endX, startY, startX, endY,
startX, endY, endX, endY, endX, startY];
};
const getGLContext = (canvas) => {
var gl = canvas.getContext('webgl2');
//0.0 -> 1.0
gl.clearColor(1.0, 1.0, 1.0, 1.0);
gl.clear(gl.DEPTH_BUFFER_BIT|gl.COLOR_BUFFER_BIT);
return gl;
};
const linkGPUAndCPU = (obj, gl) => {
var position = gl.getAttribLocation(obj.program, obj.gpuVariable);
gl.enableVertexAttribArray(position);
gl.bindBuffer(obj.channel || gl.ARRAY_BUFFER, obj.buffer);
gl.vertexAttribPointer(position, obj.dims, obj.dataType || gl.FLOAT,
obj.normalize || gl.FALSE, obj.stride || 0, obj.offset || 0);
return position;
};
var vertices = prepareRectVec2(-1.0, -1.0, 1.0, 1.0);
var textureCoordinates = prepareRectVec2(0.0, 0.0, 1.0, 1.0);
onmessage = async evt => {
var canvas = evt.data.canvas;
var gl = getGLContext(canvas);
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT);
var program = getProgram(gl, vertexShader, fragmentShader);
gl.useProgram(program);
var buffer = createAndBindBuffer(gl, gl.ARRAY_BUFFER, gl.STATIC_DRAW, new Float32Array(vertices));
linkGPUAndCPU({program : program, buffer : buffer, dims : 2, gpuVariable : 'position'}, gl);
gl.drawArrays(gl.TRIANGLES, 0, vertices.length/2);
console.log(canvas);
var rect = new fabric.Rect({
top : 100,
left : 100,
width : 60,
height : 70,
fill : 'red'
});
};