Использование работника WebGL с fabri c. js - PullRequest
0 голосов
/ 13 апреля 2020

Я могу использовать 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'
    });
  };
...