• <legend id='HFH1u'><style id='HFH1u'><dir id='HFH1u'><q id='HFH1u'></q></dir></style></legend>
          <bdo id='HFH1u'></bdo><ul id='HFH1u'></ul>

      1. <tfoot id='HFH1u'></tfoot>

        <small id='HFH1u'></small><noframes id='HFH1u'>

        <i id='HFH1u'><tr id='HFH1u'><dt id='HFH1u'><q id='HFH1u'><span id='HFH1u'><b id='HFH1u'><form id='HFH1u'><ins id='HFH1u'></ins><ul id='HFH1u'></ul><sub id='HFH1u'></sub></form><legend id='HFH1u'></legend><bdo id='HFH1u'><pre id='HFH1u'><center id='HFH1u'></center></pre></bdo></b><th id='HFH1u'></th></span></q></dt></tr></i><div id='HFH1u'><tfoot id='HFH1u'></tfoot><dl id='HFH1u'><fieldset id='HFH1u'></fieldset></dl></div>

        使用 WebGL 将两个画布混合到一个上

        时间:2023-06-21
        <i id='3wyTT'><tr id='3wyTT'><dt id='3wyTT'><q id='3wyTT'><span id='3wyTT'><b id='3wyTT'><form id='3wyTT'><ins id='3wyTT'></ins><ul id='3wyTT'></ul><sub id='3wyTT'></sub></form><legend id='3wyTT'></legend><bdo id='3wyTT'><pre id='3wyTT'><center id='3wyTT'></center></pre></bdo></b><th id='3wyTT'></th></span></q></dt></tr></i><div id='3wyTT'><tfoot id='3wyTT'></tfoot><dl id='3wyTT'><fieldset id='3wyTT'></fieldset></dl></div>
      2. <tfoot id='3wyTT'></tfoot>

            <bdo id='3wyTT'></bdo><ul id='3wyTT'></ul>
              <tbody id='3wyTT'></tbody>
          • <small id='3wyTT'></small><noframes id='3wyTT'>

                <legend id='3wyTT'><style id='3wyTT'><dir id='3wyTT'><q id='3wyTT'></q></dir></style></legend>
                • 本文介绍了使用 WebGL 将两个画布混合到一个上的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

                  问题描述

                  我要做的是将两个画布混合到一个画布上,用于我正在创建的绘图应用程序.我非常了解 Javascript,但我真的不知道从哪里开始使用 WebGL,而且由于这不是一项非常艰巨的任务,我假设如果我不使用它会产生更快的处理速度另一个库,例如 Three.js 或其他类似的库.

                  What I'm trying to do is blend two canvases onto a single canvas for a drawing app I am creating. I know Javascript very well, but I really don't have any clue where to start with WebGL and since it isn't a very hard task to do, I'm assuming it would be yield quicker processing speeds if I don't use another library like Three.js or others of that sort.

                  我已经拥有的是用户将要绘制的画布(我们称它们为画布 A 和 B),它们都是隐藏的,而画布 C 正在显示.

                  What I already have are canvases that the user will be drawing on (Let's call them canvas A and B) which are both hidden and canvas C which is being shown.

                  <canvas id='C' width=800 height=600></canvas>
                  
                  <canvas id='A' width=800 height=600 style='display:none'></canvas>
                  <canvas id='B' width=800 height=600 style='display:none'></canvas>
                  

                  我已经完成了主绘图应用程序,供用户选择要在其上绘制的图层并在其上绘图,但是我如何能够使用 WebGL 使用某种混合模式将两个图层混合在一起(即:乘) 当用户继续使用 WebGL 编辑画布?

                  I already have the main drawing app done for the user to pick the layer to draw on and to draw on it, but how would I be able to use WebGL to blend the two layers together using some blend mode (ie: multiply) as the user continues to edit the canvases using WebGL?

                  起初我尝试在这里关注其他帖子:https://stackoverflow.com/a/11596922/1572938但我很困惑.

                  At first I tried following the other post here: https://stackoverflow.com/a/11596922/1572938 but I got confused.

                  如果有人想填补我的 jsfiddle 上的空白,那将非常有效!http://jsfiddle.net/W3fVV/1/

                  If someone wants to fill in the gaps on my jsfiddle for the other post that would work very well! http://jsfiddle.net/W3fVV/1/

                  推荐答案

                  这里有一个用图片绘制的例子:https://webglfundamentals.org/webgl/lessons/webgl-image-processing.html

                  There's an example of drawing with images here: https://webglfundamentals.org/webgl/lessons/webgl-image-processing.html

                  WebGL 不关心源是图像、画布还是视频.所以改变样本从

                  WebGL doesn't care if the sources are images, canvases or video. So change the samples from

                  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, someImage);
                  

                  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, someCanvas);
                  

                  然后编写一个片段着色器来混合这两个纹理

                  Then write a fragment shader to blend the 2 textures as in

                  precision mediump float;
                  
                  // our 2 canvases
                  uniform sampler2D u_canvas1;
                  uniform sampler2D u_canvas2;
                  
                  // the texCoords passed in from the vertex shader.
                  // note: we're only using 1 set of texCoords which means
                  //   we're assuming the canvases are the same size.
                  varying vec2 v_texCoord;
                  
                  void main() {
                       // Look up a pixel from first canvas
                       vec4 color1 = texture2D(u_canvas1, v_texCoord);
                  
                       // Look up a pixel from second canvas
                       vec4 color2 = texture2D(u_canvas2, v_texCoord);
                  
                       // return the 2 colors multiplied
                       gl_FragColor = color1 * color2;
                  }
                  

                  您需要设置这 2 个纹理并告诉您的 GLSL 程序您将它们放在哪些纹理单元上.

                  You'll need to setup the 2 textures and tell your GLSL program which texture units you put them on.

                  function setupTexture(canvas, textureUnit, program, uniformName) {
                     var tex = gl.createTexture();
                  
                     updateTextureFromCanvas(tex, canvas, textureUnit);
                  
                     // Set the parameters so we can render any size image.
                     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.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
                     gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
                  
                     var location = gl.getUniformLocation(program, uniformName);
                     gl.uniform1i(location, textureUnit);
                  }
                  
                  function updateTextureFromCanvas(tex, canvas, textureUnit) {
                    gl.activeTexture(gl.TEXTURE0 + textureUnit);
                    gl.bindTexture(gl.TEXTURE_2D, tex);
                    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas);
                  }
                  
                  var tex1 = setupTexture(canvas1, 0, program, "u_canvas1");
                  var tex2 = setupTexture(canvas2, 1, program, "u_canvas2");
                  

                  示例:

                  function main() {
                    var canvas1 = document.getElementById("canvas1");
                    var canvas2 = document.getElementById("canvas2");
                    var ctx1 = canvas1.getContext("2d");
                    var ctx2 = canvas2.getContext("2d");    
                    ctx1.fillStyle = "purple";
                    ctx1.arc(64, 64, 30, 0, Math.PI * 2, false);
                    ctx1.fill();
                    ctx2.fillStyle = "cyan";
                    ctx2.fillRect(50, 10, 28, 108);
                      
                    // Get A WebGL context
                    var canvas = document.getElementById("webgl");
                    var gl = canvas.getContext("webgl");
                    if (!gl) {
                      return;
                    }
                  
                    // setup GLSL program
                    var program = twgl.createProgramFromScripts(gl, ["2d-vertex-shader", "2d-fragment-shader"]);
                    gl.useProgram(program);
                  
                    // look up where the vertex data needs to go.
                    var positionLocation = gl.getAttribLocation(program, "a_position");
                    var texCoordLocation = gl.getAttribLocation(program, "a_texCoord");
                  
                    // provide texture coordinates for the rectangle.
                    var texCoordBuffer = gl.createBuffer();
                    gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);
                    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
                        0.0,  0.0,
                        1.0,  0.0,
                        0.0,  1.0,
                        0.0,  1.0,
                        1.0,  0.0,
                        1.0,  1.0]), gl.STATIC_DRAW);
                    gl.enableVertexAttribArray(texCoordLocation);
                    gl.vertexAttribPointer(texCoordLocation, 2, gl.FLOAT, false, 0, 0);
                  
                    // lookup uniforms
                    var resolutionLocation = gl.getUniformLocation(program, "u_resolution");
                  
                    // set the resolution
                    gl.uniform2f(resolutionLocation, canvas1.width, canvas1.height);
                  
                    // Create a buffer for the position of the rectangle corners.
                    var buffer = gl.createBuffer();
                    gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
                    gl.enableVertexAttribArray(positionLocation);
                    gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
                  
                    // Set a rectangle the same size as the image.
                    setRectangle(gl, 0, 0, canvas.width, canvas.height);
                      
                      function setupTexture(canvas, textureUnit, program, uniformName) {
                         var tex = gl.createTexture();
                  
                         updateTextureFromCanvas(tex, canvas, textureUnit);
                  
                         // Set the parameters so we can render any size image.
                         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.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
                         gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
                        
                         var location = gl.getUniformLocation(program, uniformName);
                         gl.uniform1i(location, textureUnit);
                      }
                  
                      function updateTextureFromCanvas(tex, canvas, textureUnit) {
                        gl.activeTexture(gl.TEXTURE0 + textureUnit);
                        gl.bindTexture(gl.TEXTURE_2D, tex);
                        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas);
                      }
                  
                      var tex1 = setupTexture(canvas1, 0, program, "u_canvas1");
                      var tex2 = setupTexture(canvas2, 1, program, "u_canvas2");
                  
                    // Draw the rectangle.
                    gl.drawArrays(gl.TRIANGLES, 0, 6);
                  }
                  
                  function setRectangle(gl, x, y, width, height) {
                    var x1 = x;
                    var x2 = x + width;
                    var y1 = y;
                    var y2 = y + height;
                    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
                       x1, y1,
                       x2, y1,
                       x1, y2,
                       x1, y2,
                       x2, y1,
                       x2, y2]), gl.STATIC_DRAW);
                  }
                  
                  main();

                  canvas {
                      border: 2px solid black;
                      width: 128px;
                      height: 128px;
                  }

                  <script src="https://twgljs.org/dist/3.x/twgl.min.js"></script>
                  <!-- vertex shader -->
                  <script id="2d-vertex-shader" type="x-shader/x-vertex">
                  attribute vec2 a_position;
                  attribute vec2 a_texCoord;
                  
                  uniform vec2 u_resolution;
                  
                  varying vec2 v_texCoord;
                  
                  void main() {
                     // convert the rectangle from pixels to 0.0 to 1.0
                     vec2 zeroToOne = a_position / u_resolution;
                  
                     // convert from 0->1 to 0->2
                     vec2 zeroToTwo = zeroToOne * 2.0;
                  
                     // convert from 0->2 to -1->+1 (clipspace)
                     vec2 clipSpace = zeroToTwo - 1.0;
                  
                     gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);
                  
                     // pass the texCoord to the fragment shader
                     // The GPU will interpolate this value between points.
                     v_texCoord = a_texCoord;
                  }
                  </script>
                  <!-- fragment shader -->
                  <script id="2d-fragment-shader" type="x-shader/x-fragment">
                      precision mediump float;
                  
                      // our 2 canvases
                      uniform sampler2D u_canvas1;
                      uniform sampler2D u_canvas2;
                  
                      // the texCoords passed in from the vertex shader.
                      // note: we're only using 1 set of texCoords which means
                      //   we're assuming the canvases are the same size.
                      varying vec2 v_texCoord;
                  
                      void main() {
                           // Look up a pixel from first canvas
                           vec4 color1 = texture2D(u_canvas1, v_texCoord);
                  
                           // Look up a pixel from second canvas
                           vec4 color2 = texture2D(u_canvas2, v_texCoord);
                  
                           // return the 2 colors multiplied
                           gl_FragColor = color1 * color2;
                      }
                  </script>
                  <!-- fragment shader -->
                  <script id="aa2d-fragment-shader" type="x-shader/x-fragment">
                  precision mediump float;
                  
                  // our texture
                  uniform sampler2D u_canvas1;
                  uniform sampler2D u_canvas2;
                  
                  // the texCoords passed in from the vertex shader.
                  varying vec2 v_texCoord;
                  
                  void main() {
                     gl_FragColor = texture2D(u_canvas1, v_texCoord);
                  }
                  </script>
                  <canvas id="canvas1" width="128" height="128"></canvas>
                  <canvas id="canvas2" width="128" height="128"></canvas>
                  <canvas id="webgl" width="128" height="128"></canvas>

                  这篇关于使用 WebGL 将两个画布混合到一个上的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

                  上一篇:如果多次应用,带有 alpha 的 rgba fillStyle 不会变得完全不透明 下一篇:Fabric.js 动态裁剪单个对象

                  相关文章

                  <small id='OCRwJ'></small><noframes id='OCRwJ'>

                  1. <tfoot id='OCRwJ'></tfoot>
                    <legend id='OCRwJ'><style id='OCRwJ'><dir id='OCRwJ'><q id='OCRwJ'></q></dir></style></legend>
                      • <bdo id='OCRwJ'></bdo><ul id='OCRwJ'></ul>
                      <i id='OCRwJ'><tr id='OCRwJ'><dt id='OCRwJ'><q id='OCRwJ'><span id='OCRwJ'><b id='OCRwJ'><form id='OCRwJ'><ins id='OCRwJ'></ins><ul id='OCRwJ'></ul><sub id='OCRwJ'></sub></form><legend id='OCRwJ'></legend><bdo id='OCRwJ'><pre id='OCRwJ'><center id='OCRwJ'></center></pre></bdo></b><th id='OCRwJ'></th></span></q></dt></tr></i><div id='OCRwJ'><tfoot id='OCRwJ'></tfoot><dl id='OCRwJ'><fieldset id='OCRwJ'></fieldset></dl></div>