【问题标题】:HTML 2d canvas as texture on webgl canvasHTML 2d 画布作为 webgl 画布上的纹理
【发布时间】:2020-11-17 12:35:30
【问题描述】:

我正在尝试基于此示例here 将具有上下文2d 的画布作为texture 添加到webgl 画布。 webgl 画布上的纹理似乎是空白的,但是当我将纹理画布单独附加到 DOM 时,图像已加载。我可能在这里遗漏了什么?

const canvas = document.createElement("canvas");
    const textureCanvas = document.createElement('canvas');
    textureCanvas.width = 200
    textureCanvas.height = 200
    const ctx = textureCanvas.getContext('2d')
    const img = new Image();
    img.src = "https://i.imgur.com/uIEexIc.jpg";
    img.crossOrigin = 'Anonymous'

    img.onload = (i) => {
      
      ctx.drawImage(img, 0,0, 200, 200)
    }

   
    const gl = canvas.getContext("webgl");
    const canvasTexture = gl.createTexture();
    
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);

    gl.bindTexture(gl.TEXTURE_2D, canvasTexture);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, textureCanvas); 
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST);
    gl.generateMipmap(gl.TEXTURE_2D);

    gl.bindTexture(gl.TEXTURE_2D, null);

【问题讨论】:

    标签: javascript canvas webgl webgl2


    【解决方案1】:

    画布不能用作“实时”纹理。

    换句话说,当您的代码调用gl.texImage2D(....., textureCanvas) 时,画布的内容在那个时刻只被复制到纹理一次。

    在您上面的代码中,流程是这样的

    1. 创建画布
    2. 创建图像
    3. 设置 src 并设置 onload 函数
    4. 创建一个 webgl 纹理
    5. 通过 texImage2D 将空白画布复制到纹理中
    6. 稍后图像完成加载并调用 onload 函数
    7. 图像被绘制到画布中。

    在调用gl.texImage2D之前需要等待图片被绘制到画布中

    【讨论】:

      【解决方案2】:

      我已尝试调查此问题。

      看来,强制纹理画布的尺寸为 2 的幂可以修复纹理可见性。

      您可以尝试在代码中替换此块:

      img.onload = (i) => {
          ctx.drawImage(img, 0,0, 200, 200)
      }
      

      到这个块:

      img.onload = (ev) => {
        const w = getPowerOfTwo(img.width);
        const h = getPowerOfTwo(img.height);
        textureCanvas.width = w
        textureCanvas.height = h
        ctx.drawImage(img, 0, 0, w, h);
        handleLoadedTexture(textureCanvas);
      }
      

      这里我强制textureCanvas的宽度和高度为幂或2。函数在这里:

      function getPowerOfTwo(value, pow) {
        var pow = pow || 1;
        while (pow < value) {
          pow *= 2;
        }
        return pow;
      }
      

      还要注意代码handleLoadedTexture(textureCanvas);。在这里,我使用新加载的图像重绘(更新)纹理。

      您可以在此处测试的所有其他代码:jsfiddle。可以肯定的是,该纹理是从画布提供的,我在图像上方添加了'Hello World' 文本(请参阅handleLoadedTexture)。

      【讨论】:

        猜你喜欢
        • 2021-07-24
        • 2013-01-05
        • 2019-05-07
        • 2014-04-29
        • 2019-01-26
        • 2015-01-28
        • 2014-07-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多