jere Posted February 26, 2016 Share Posted February 26, 2016 Hi! I've been working on a canvas game for a while, hit some performance issues I just can't get around, and am hoping Pixi is the answer. So I'm struggling a bit to learn how to implement everything I can do in canvas in Pixi. So here goes my current problem: I need a "source-atop" replacement. I want to draw some tile, overlay it with a totally opaque red sprite (eventually it'll be transparent, but it's opaque for this proof of concept), and then mask that sprite with the original tile objects which together will form an irregular shape. I wrote some test code and had no issues, but when I bring it into my project I get a very odd behavior: the second sprite suddenly appears transparent. Here's the code: this.container = new PIXI.Container(); this.container.position.x = this.i * tileSize; //base sprite var tileTexture = new PIXI.Texture(ssTexture, new PIXI.Rectangle(ssl[0], ssl[1], 16, 16)); var tileSprite = new PIXI.Sprite(tileTexture); this.container.addChild(tileSprite); //tile mask generated from sprite var tileMask = new PIXI.Sprite(this.container.generateTexture(WebGLRenderer)); //sunlight var sunlightOverlay = new PIXI.Sprite(sunlightTexture); this.container.addChild(sunlightOverlay); //mask sunlight sunlightOverlay.mask = tileMask; sunlightOverlay.addChild(tileMask); this.level.PixiContainer.children[this.j*2+1].addChild(this.container); And here's the behavior: 1) Draw just the tile. 2) Draw the overlay. Obviously, it will have a different shape than the first tile which is why I need to mask it. 3) This is the object that will be used as a mask for the overlay. I used generateTexture() before adding the overlay. 4) Now I set the mask to actually be used as a mask. I'm expecting a simple red square. It masks properly, but the overlay is inexplicably made transparent. I don't know what to try here. There must be something simple I'm misunderstanding. Any thoughts? Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted February 26, 2016 Share Posted February 26, 2016 There's no source-atop blending mode in pixi. Masking can solve problem only temporary. Why do you need that stuff anyway? I mean, you can assign "white" texture instead of that block Quote Link to comment Share on other sites More sharing options...
jere Posted February 26, 2016 Author Share Posted February 26, 2016 I am making an overhead game which features beams of sunlight*. A tile can be bathed in sunlight, which I plan to implement as a semi-transparent yellowish rectangle. If I don't mask the rectangle, it's going to have the shape of a rectangle instead of whatever else it's supposed to be covering. You can see the intended behavior here: https://pbs.twimg.com/media/CU6bT3VWcAAa-Fn.png:large The tile on the left with the torch is covered in sunlight. So is the character. A big block of yellow wouldn't work. This seems like a perfect fit for masking. I don't follow you when you say "masking can solve problem only temporary." *Sunlight isn't the only thing I need either. I need the same behavior for characters standing in the shadows and other things. Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted February 26, 2016 Share Posted February 26, 2016 Why not add sprite or graphics with "ADD" or "MULTIPLY" blendMode? UPD. Oh , i understand how do you want to do that. Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted February 26, 2016 Share Posted February 26, 2016 Try assign filter to tiles / character , ColorMatrixFilter Also try specifying tint for sprite: sprite.tint = 0xffffff or something like that Quote Link to comment Share on other sites More sharing options...
jere Posted February 26, 2016 Author Share Posted February 26, 2016 Thank you. I will give that a try when I get a chance. Quote Link to comment Share on other sites More sharing options...
MichaelZ Posted March 11, 2016 Share Posted March 11, 2016 Having this EXACT problem now myself... where when using a Sprite (with a source image as a texture) as a mask... the mask seems to effect the alpha channel of the source texture. As I understand, stencil buffers (which I'd assume this would be using for the WebGL renderer), should only effect the inclusion/exclusion of the source pixel, not the alpha value of the pixel. Additionally, setting a sprite mask absolutely destroy's performance... especially on iPads... but its even noticable on desktops (huge red flag). Both these things are making me suspect something is fishy with the PIXI implementation... and I'll start diving into PIXI to try to see what's going on. Is this a known issue? Is there a better approach to leveraging the WebGL stencil buffer? Quote Link to comment Share on other sites More sharing options...
MichaelZ Posted March 11, 2016 Share Posted March 11, 2016 After some PIXI diving and debugging it turns out the performance issue was due to a mis-use of the masking on our end: we needed to apply it once to a parent container instead of once per child object (~200). This removed the horrible performance hit and its ok on device now. As for the transparency vs inclusion/exclusion: I believe PIXI doesn't use a stencil buffer here but probably adds support for this within some shader that gets used. I suppose a multiply per pixel rather than an if is probably more performant anyway. We worked around this issue by pre-processing on load the assets used for the stencil and setting all color values of non-transparent pixels to 0xFFFFFF which then results in the behavior we want with the masking. So things seem ok... and I'm no longer suspicious of the implementation However, there are of course new issues that have come up that I'm looking into atm: - It seems masks don't work with Particle Containers. Is this a known issue? Limitation? - Having a bug where I can't seem to resize UP the mask size on window resize... resizing down works... but not up and the old small size is used. If anyone has any insight into the 2 issues above please let me know. Quote Link to comment Share on other sites More sharing options...
MichaelZ Posted March 16, 2016 Share Posted March 16, 2016 Returning to the performance question... I am using a sprite as a mask. The cost of applying this mask is more than I expect. Looking a bit into the implementation it seems that setting a Sprite as a mask triggers the shader used to be the SpriteMaskFilter instead of the default Texture shader. This filter shader is quite more complex than the Texture shader which I am assuming is the main difference when I switch between setting the mask and not. I would assume masking could use the StencilMask functionality built into WebGL instead of manually handling this in the shader. I do see the Stencil buffer is used within PIXI in places. So my question is: is there any way to leverage the stencil buffer for performing masking with a sprite to make optimal use of the hardware acceleration? And if not... any tips I should know about for using sprites as masks? Quote Link to comment Share on other sites More sharing options...
MichaelZ Posted March 18, 2016 Share Posted March 18, 2016 Update on the clipping bug: https://github.com/pixijs/pixi.js/issues/2402 Would still love an answer to my question: is there any way to leverage the stencil buffer for performing masking with a sprite to make optimal use of the hardware acceleration? And if not... any tips I should know about for using sprites as masks? Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted March 19, 2016 Share Posted March 19, 2016 @MichaelZ Basically, you just need a RenderTexture, and draw your sprites into it, then use it as a parameter for a filter, like SpriteMaskFilter does. That way you'll have all control, you'll be able to change how mask works and you wont even need the stencil buffer for it. Please dont use masks to create lighting effects, use filters. 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.