alexzchen Posted March 10, 2020 Share Posted March 10, 2020 When I use mask and blendmode(MULTIPLY) alone, they are all right, but if they are used together, it will turn black. Is that right? function setup(loader, res) { let lower = new PIXI.Sprite(PIXI.loader.resources["lower"].texture) let uper = new PIXI.TilingSprite(PIXI.loader.resources["uper"].texture) let mask = new PIXI.Sprite(PIXI.loader.resources["mask"].texture) uper.blendMode = PIXI.BLEND_MODES["MULTIPLY"]; //uper.mask = mask; stage.addChild(mask); stage.addChild(lower); stage.addChild(uper); } Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted March 10, 2020 Share Posted March 10, 2020 (edited) Your order of operations is wrong. You just cant do that multiply trick without extra layer. There are three ways to do this stuff: 1. Sprite Mask 2. DST_OUT aka ERASE blendMode, in separate layer. , means that you need a container with uper+mask , and AlphaFilter on it to move it to separate framebuffer. 3. Same as 2. but instead of extra container you add low on top with SRC_IN blendMode or something like that (as a result it draws behind picture). Requires transparent background. I will set up example for you later. Edited March 10, 2020 by ivan.popelyshev Quote Link to comment Share on other sites More sharing options...
alexzchen Posted March 10, 2020 Author Share Posted March 10, 2020 Thank you very much. I really need an example. I've worked hard for this requirement for a whole month. I'm a Pixi beginner Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted March 10, 2020 Share Posted March 10, 2020 (edited) Here you go: https://www.pixiplayground.com/#/edit/gf4R13uySPmp2ktzAC3MT just swap textures to whatever you want, and maybe swap maskTexture , in the demo you can draw on it. If you still dont understand why do you need filter there, you probably have to experiment with photoshop and other editors more. Layers are essential part, without it you cant do lighting and other kind of effects. The first question should be "if we have pictures A,B,C , does it matter whether B blends on A first or C blends on B?". If you still dont have a single clue - try experiment with canvas2d without pixi, just pure RenderingContext2D drawImage method. Edited March 10, 2020 by ivan.popelyshev Quote Link to comment Share on other sites More sharing options...
alexzchen Posted March 10, 2020 Author Share Posted March 10, 2020 I've tried your demo, but it still doesn't work. Here is my code: https://www.pixiplayground.com/#/edit/DPZGFIoYSgTtkkXSAmPTm. Please help me to have a look Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted March 10, 2020 Share Posted March 10, 2020 I rewrote your demo a bit, look at it again. Quote Link to comment Share on other sites More sharing options...
alexzchen Posted March 10, 2020 Author Share Posted March 10, 2020 Thank you for your help, but the final effect I want is as follows, pls see the attachment, the white part of the mask layer is exposed, and multiply with the bottom image Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted March 10, 2020 Share Posted March 10, 2020 Switch to DST_IN, or change texture places... OH WAIT THAT's EXTRA MULTIPLY! Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted March 10, 2020 Share Posted March 10, 2020 Look again please. The only problem I have now is that your mask texture is too small Quote Link to comment Share on other sites More sharing options...
alexzchen Posted March 11, 2020 Author Share Posted March 11, 2020 Perfect!!! Thank you so much, thank you ~ ivan.popelyshev 1 Quote Link to comment Share on other sites More sharing options...
alexzchen Posted March 19, 2020 Author Share Posted March 19, 2020 Thanks for your solution again, now I hava another problem, when the lower sprite and mask use the same picture, it will cause a gray border, I'm trying to zoom in the mask picture, and it's going to be obvious, I guess it's because the edge of picture are not clear enough, is there anyway to solve it? here is my code: https://www.pixiplayground.com/#/edit/DPZGFIoYSgTtkkXSAmPTm tks Quote Link to comment Share on other sites More sharing options...
alexzchen Posted March 19, 2020 Author Share Posted March 19, 2020 In principle, if I use the same picture, the cut part by the mask should be exactly the same as the lower picture, there should be no gray border... Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted March 20, 2020 Share Posted March 20, 2020 (edited) For now you can try do the math of why that black border happens. All pixijs textures have premultiplied alpha. https://github.com/pixijs/pixi.js/blob/dev/packages/core/src/state/utils/mapWebGLBlendModesToPixi.ts#L19 https://www.w3.org/TR/compositing-1/#blending Otherwise, I can look at it next week. I hope you understand that knowledge of all those blend modes is rare thing in our html5 gamedev community. That issue you are asking me to solve is HARD. Edited March 20, 2020 by ivan.popelyshev Quote Link to comment Share on other sites More sharing options...
alexzchen Posted March 20, 2020 Author Share Posted March 20, 2020 I think I already know some reasons, the edge of the picture has some transparency, but the mask does not, so when the picture cut by mask multiply with the lower sprite, the edge will turn black, does it mean that the mask solution is inappropriate in my scene, I should look for other ways? Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted March 20, 2020 Share Posted March 20, 2020 Article from another thread, just to be consistent: http://www.adriancourreges.com/blog/2017/05/09/beware-of-transparent-pixels/ Quote Link to comment Share on other sites More sharing options...
alexzchen Posted March 27, 2020 Author Share Posted March 27, 2020 (edited) I come up with a simple idea. Since TillingSprite can handle all the effects of the upper picture that I need, including movement, rotation, displacement, etc., and then I will add a separate custom filter for multiply with lower layer pictures and cut the transparent part, it works like a mask, is my idea feasible? the shader code some like: vec4 sample = texture2D(uSampler, coord); if (gl_FragColor.a != 0.0) { gl_FragColor.rgb = (sample * uColor).rgb * gl_FragColor.rgb; } Edited March 27, 2020 by alexzchen Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted March 27, 2020 Share Posted March 27, 2020 (edited) no, because you have no access to pixel underneath. You cant read value from "gl_FragColor" There is a plugin that allows to do something like that, it copies whats underneath in separate uSampler, called "pixi-picture" but i hadnt move it to v5 yet. I think best idea is to take SpriteMaskFilter as a base. It takes sampler (whats inside container) and a sprite (texture + transform). You can add extra texture there - a colorful one , dont forget to set its wrapMode to repeat. The only problem is that you'll need to scale it too. I tihnk I will be able to help you tomorrow. I bet I can do that in 10 minutes or so but my brain time is very limited and I have many other requests too Edited March 27, 2020 by ivan.popelyshev Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted March 27, 2020 Share Posted March 27, 2020 (edited) Yes, the topic itself is very interesting, I have experience with it, and I even had a huge tutorial video for that kind of things, but its in russian Need more time (sigh) to make actual huge article or even a book chapter about it. PixiJS has the best API for those things (among other html5 renderers) but even then its not fully documented for regular folks to use without extra help. P.S. also you didnt take into account premultiplied alpha in your calculation - that's the main problem here we cant solve with blend Edited March 27, 2020 by ivan.popelyshev Quote Link to comment Share on other sites More sharing options...
alexzchen Posted March 27, 2020 Author Share Posted March 27, 2020 Thanks for reply, I guess the implementation of this 'SpriteMaskFilter' is very similar to the DisplacementFilter, it will give a texture parameter as a sampler and use its pixel information to do multiply, and remove the transparent part at the same time Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted March 27, 2020 Share Posted March 27, 2020 (edited) 5 minutes ago, alexzchen said: Thanks for reply, I guess the implementation of this 'SpriteMaskFilter' is very similar to the DisplacementFilter, it will give a texture parameter as a sampler and use its pixel information to do multiply, and remove the transparent part at the same time Or add second sprite if you want to position second texture without problems, applyFilter can handle two copies of positiong code The thing with multiply is that you have to unpremultiply first. HEre's V4 shader for OVERLAY: https://github.com/pixijs/pixi-picture/blob/master/src/OverlayShader.ts And here's my multiply shader from secret project: vec4 src = texture2D(uSampler, vTextureCoord); vec4 dest = texture2D(uBackdrop, vTextureCoord); if (dest.a == 0.0) { gl_FragColor = src; return; } if (src.a == 0.0) { gl_FragColor = dest; return; } vec4 mult; mult.rgb = (dest.rgb / dest.a) * ((1.0 - src.a) + src.rgb); mult.a = min(src.a + dest.a - src.a * dest.a, 1.0); mult.rgb *= mult.a; Edited March 27, 2020 by ivan.popelyshev Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted March 27, 2020 Share Posted March 27, 2020 (edited) Actually now that i think about it, there's easier way, without custom filters/shaders: 1. Use TilingSprites of color and cloth to get a multiplied result in renderTexture 2. Now you have cloth and new bacgrkound, you can just mask that background with your black-white mask (sprite mask, "container.mask = myWhiteMask") and it'll work. Yes, it uses SpriteMaskFilter internally. Edited March 27, 2020 by ivan.popelyshev Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted March 27, 2020 Share Posted March 27, 2020 Even easier: Use black background and colors+mask. Put cloth on top with MULTIPLY blendMode. Quote Link to comment Share on other sites More sharing options...
alexzchen Posted March 27, 2020 Author Share Posted March 27, 2020 Thanks, I will have a try follow your suggesion Quote Link to comment Share on other sites More sharing options...
alexzchen Posted March 27, 2020 Author Share Posted March 27, 2020 Actually, I remember that I have tried the mask solution a week ago, it will cause gray border, as long as there is a certain transparency on the edge of the picture, so I will try the custom filter first tonight, even though I don't know how to write a filter, hope to succeed Quote Link to comment Share on other sites More sharing options...
alexzchen Posted March 27, 2020 Author Share Posted March 27, 2020 (edited) 5 hours ago, ivan.popelyshev said: Even easier: Use black background and colors+mask. Put cloth on top with MULTIPLY blendMode. I tried again with your suggestion, but still have a gray border, and the color looks a little wrong, it seems darker than it used to be use sprite as a mask: https://www.pixiplayground.com/#/edit/QLaZYeWHqrVkkrj-ZRL9h use container https://www.pixiplayground.com/#/edit/DPZGFIoYSgTtkkXSAmPTm Edited March 27, 2020 by alexzchen Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.