3

从 2016 年开始编辑:为globalCompositeOperation实现了“乘”值。性能对于实时图形来说绰绰有余。


本质上,我有两个画布(一个是用于绘图的不可见画布),我想使用多重混合模式将不可见画布混合到可见画布上。

Context.globalCompositeOperation不包括乘法(尽管我认为应该),并且使用imageData手动混合画布太慢(我需要能够以 60fps 的速度进行此操作)。

有什么更快的方法可以用来混合画布吗?我相信这可以使用WebGL来完成,但我没有使用它的经验。

4

1 回答 1

5

WebGL 的混合模式也不包括(源和目标的)乘法。但是,您可以使用 WebGL 的渲染到纹理功能有效地执行乘法运算:

  1. 让您的可见画布成为 WebGL 画布。
  2. 创建两个纹理;称它们为“源”和“目的地”。
  3. 将您的不可见画布内容渲染到“源”纹理;这可以通过直接使用 WebGL 绘图操作(不使用额外的画布)或通过将 2D 不可见画布的内容上传到纹理来完成(这是一个内置操作):

    var sourceTexture = gl.createTexture()
    gl.bindTexture(gl.TEXTURE_2D, sourceTexture)
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, sourceCanvas)
    // ...also set texture filters — see any WebGL tutorial...
    
  4. 渲染要与“目标”纹理相乘的其他内容。

  5. 最后,针对实际可见的画布,使用片段着色器将“源”和“目标”纹理相乘。这里的技术是用于后期处理效果的技术——我建议查找这样的教程或简单的示例。简而言之,要将片段着色器应用于整个画布,您需要绘制一个覆盖整个视口的全屏四边形几何体。顶点着色器是微不足道的,片段着色器就像:

    varying vec2 texCoord;
    uniform sampler2D sourceTexture;
    uniform sampler2D destTexture;
    void main(void) {
      gl_FragColor = texture2D(sourceTexture, texCoord) * texture2D(destTexture, texCoord);
    }
    

如果你想每帧做多个重叠的乘法混合,那么如果不超过 8 个,你可以扩展上面的过程来乘几个纹理;如果有很多,您将需要执行多个阶段,将两个纹理相乘,同时渲染到第三个,然后交换角色。

如果您想要更具体的答案,请扩展您的问题,并详细说明您要相乘的图形数量和类型。

于 2012-07-22T00:36:38.793 回答