How can I use multiple blending mode on canvas in real time?

Change from 2016 . The value "multiply" is implemented for globalCompositeOperation . Performance is more than adequate for real-time graphics.


Essentially, I have two canvases (one is an invisible canvas used for drawing), and I want to mix an invisible canvas onto a visible one with multiply blend mode.

Context.globalCompositeOperation does not include multiplication (although this should, in my opinion) and using imageData to manually change the canvas is too slow (I need to do this at 60 frames per second).

Is there any faster method that I could use to mix the canvases? I believe that this can be done using WebGL , but I have no experience using it.

+2
source share
1 answer

WebGL blending modes also do not include multiplication (source and destination). However, you can efficiently reuse using the WebGL rendering capabilities for texture:

  • Let your visible canvas be a WebGL canvas.
  • Create two textures; name them "source" and "destination."
  • Pull the contents of your invisible canvas into the source texture; this can be done either using WebGL drawing operations directly (without an additional canvas), or by loading your 2D content of an invisible canvas into a texture (this is a built-in operation):

     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... 
  • Edit the other content you want to multiply by the destination texture.

  • Finally, focusing on the real visible canvas, use the fragment shader to multiply the source and destination textures. The methods here are those that are used for effects after processing . I recommend looking for such a tutorial or a simple example. In short, to apply a fragmented shader to the entire canvas, you draw the geometry of a full-screen square that spans the entire viewport. The vertex shader is trivial, and the fragment shader will look like this:

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

If you want to make several overlapping multipliers for each frame, then if there are no more than, say, 8, you can extend the procedure described above to multiply several textures; if there is a lot, you will need to perform several stages of multiplying two textures when rendering to the third, and then exchange roles.

If you want a more specific answer, then please expand your question with more detailed information about how many and which graphics you multiply together.

+4
source

Source: https://habr.com/ru/post/926245/


All Articles