pixijs / picture

A plugin that includes a sprite renderer that reduces border artifacts and 3 blend mode implementations for WebGL
MIT License
67 stars 20 forks source link

When you set blendMode equal to DST_OUT for sprite, you need to set filters for the parent Container. Is this a bug? #20

Open shenfusheng opened 3 years ago

shenfusheng commented 3 years ago

I am using pixi (6.1.2) to implement a drawing board. My current approach is to use Graphic to implement the brush, and then convert it to Sprite. The eraser also converts Graphic to Sprite and then sets blendMode=PIXI.BLEND_MODES.DST_OUT, but now I encounter One question, I must set a filter on the Container to make DST_OUT take effect. When there are many Containers on the page with filters set, the FPS of the page will drop significantly. I want to ask if there is a way to avoid using filters to make blendMode take effect. Hope to get your help, thank you very much. Here is a demo I wrote about setting blendMode: https://codepen.io/shenfusheng/pen/bGRLzWz

ivanpopelyshev commented 3 years ago

You want to erase something without touching background color, right? You need a extra renderTexture, yours or from a filter, on your big container. You dont have to add it to all containers, just the top one.

Lets take only one pixel, that was colored orange, then drawn red. You want to erase red to get orange back, but where exactly do you want this info about past "orange" to be stored?

Also in your demo you use main bundle "pixi.js", not "pixi-legacy.js", so "forceCanvas:true" wont work there.

shenfusheng commented 3 years ago

You want to erase something without touching background color, right? You need a extra renderTexture, yours or from a filter, on your big container. You dont have to add it to all containers, just the top one.

Lets take only one pixel, that was colored orange, then drawn red. You want to erase red to get orange back, but where exactly do you want this info about past "orange" to be stored?

Also in your demo you use main bundle "pixi.js", not "pixi-legacy.js", so "forceCanvas:true" wont work there.

First of all, thank you for your help. English is not my native language, so my expression may be somewhat incorrect. Please forgive me.

  1. I tried to add filters to the topmost Container before, but it made the graphics jagged. I also tried to use the graphics-smooth library instead of PIXI.Graphics. The sawtooth is gone, but some white spots will be produced. I don't know how to avoid these spots. image

  2. The orange background color is just what I set casually. The normal whiteboard should be the white background color, and then draw red strokes. The eraser will erase the red strokes with the movement of the mouse without affecting the background color. I don’t need to store the background color.

  3. The last point you said "forceCanvas: true" will not work, I am a little confused, it will affect the role of blendMode?

One last question? What is the best way to use pixi to implement an eraser to erase strokes? I am not sure whether my current approach is the best.

ivanpopelyshev commented 3 years ago

I tried to add filters to the topmost Container before, but it made the graphics jagged.

welcome to webgl. You cant have antialiasing not in main framebuffer. https://github.com/pixijs/graphics-smooth partially saves the problem (please read README and dont just apply it), or you can just enable MSAA in that filter (msaaQuality or some other field? we added it), but that's memory, or you can just generateCanvasTexture() brushes if you have "pixi-legacy"

  1. then you can just erase whatever you want and then SRC_OUT or how it done in the end ( after all other elements) - put background behind all that transparency
  2. i mean that if you want to test whether something works on canvas2d - you need pixi-legacy.js, not pixi.js

The best way so far is to store renderTexture or better grid of renderTextures, and do all drawing operations there. Put many brush sprites in the same drawcall to save performance, like your curve from last frame to current one is approximated with 10 brush sprites - do them in same container. If you develop something