Nyrion Posted October 25, 2019 Share Posted October 25, 2019 I've been trying to sort this out for a bit. I'll try to keep it simple. I'm using pixi-layers & pixi v4. I have Sprites that use a texture (generally png) as a light. This gets added to the stage and assigned to a sorting group. Layering works fine at this point. Next is ambient lighting, it's also added to the stage at the highest zIndex and assigned to the sorting group so (obviously it renders above everything else). Next each light has a mask that is based off of the Sprites texture. This gets added to the ambient lighting container. Herein lies the problem. The mask in the ambient lighting container, of course renders at the same zIndex that the ambient lighting container is at and not at the zIndex that the light sprite is at. The mask should render at the same zIndex as the light sprite. Any suggestions on how to go about this? Thanks! I've attached an example screenshot of my current results. As you can see the light sprite renders at the proper zIndex (lets say 3 for example). The tree renders at zIndex 4 for example. The mask renders above the tree (which it shouldn't). ivan.popelyshev 1 Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted October 25, 2019 Share Posted October 25, 2019 (edited) > The mask in the ambient lighting container, of course renders at the same zIndex that the ambient lighting container is at and not at the zIndex that the light sprite is at. Mask is rendered in "renderer.maskManager.pushMask" operation, in a container that is masked. Yes, there is a problem with how to make masks with pixi-layers. Fortunately, you have minimal example, right? Please publish it and tell me more info about it. Two possible outcomes: 1. we find how to adjust pixi-layers logic thus masks works the way you want 2. we find that mask isnt actually needed, instead we need gray version of tree in light layer or something like that Welcome to the forums! That's a powerful first post. Edited October 25, 2019 by ivan.popelyshev Quote Link to comment Share on other sites More sharing options...
Nyrion Posted October 25, 2019 Author Share Posted October 25, 2019 (edited) Thanks for your reply ivan and thanks for the welcome! I am unable to post the full logic of this as it's tied into a massive project i'm working on, but i've stripped out the steps to get to this point and posted it on fiddle and a code example below to work with. I've also linked to a video of this in action. Fiddle Link: https://jsfiddle.net/1caoymvs/ (start at around line 754) Hope this code example is clear! Thanks again. this.container = new PIXI.Container(); this.container.zIndex = 1; this.container.sortGroup = new PIXI.display.Group( 0, false ); this.container.sortLayer = new PIXI.display.Layer( this.container.sortGroup ); this.stage.addChild( this.container.sortLayer ); // @stage is an instance of PIXI.display.Stage this.container.parentGroup = this.container.sortGroup; this.container.parentLayer = this.container.parentLayer; this.stage.addChild( this.container ); // The ambient lighting container with mask children this.ambientOverlay = new PIXI.Sprite( PIXI.Texture.WHITE ); this.ambientOverlay.zIndex = 999999; this.ambientOverlay.tint = 0x000000; this.ambientOverlay.width = this.width; this.ambientOverlay.height = this.height; this.ambientOverlay.parentGroup = this.container.sortGroup; this.ambientOverlay.parentLayer = this.container.sortLayer; this.container.addChild( this.ambientOverlay ); // @theTexture being a cached Texture this.light = new Sprite_Light( theTexture, this ); // Sprite_Light is a simple extension of PIXI.Sprite ultimately this.light.zIndex = 2; this.light.parentGroup = this.container.sortGroup; this.light.parentLayer = this.container.sortLayer; this.container.addChild( this.light, this ); /* The "tree" is part of a tilemap (think how RPG Maker MV uses pixi-tilemap) that's also added to "container". The tilemap is also assigned a parentGroup/parentLayer, the layering of the tilemap works fine. So it seems option 1 with a gray version might be expensive There are also other "Sprites" on the scene on various layers with textures The "texture" used for the light as well as the lights positioning may also be changed during runtime. */ window.Sprite_Light = function() { this.initialize.apply( this, arguments ); }; Sprite_Light.prototype = Object.create( Sprite.prototype ); Sprite_Light.prototype.constructor = Sprite_Light; Sprite_Light.prototype.initialize = function( texture, scene ) { Sprite.prototype.initialize.call( this ); this.texture = new PIXI.Texture( this.texture.baseTexture ); if ( this.lightMask ) this.removeChild( this.lightMask ); this.lightMask = new PIXI.Sprite( this.texture ); this.addChild( this.lightMask ); scene.ambientOverlay.removeChildren(); this.lightMaskOverlay = new PIXI.Sprite( PIXI.Texture.WHITE ); this.lightMaskOverlay.mask = this.lightMask; scene.ambientOverlay.addChild( this.lightMaskOverlay ); /* Here is the problem, adding the mask to @ambientOverlay Sprite_Light renders on the correct layer (2), but the mask renders on layer (999999) Is it possible for the mask as a child of @ambientOverlay to render in said container but follow it's own zIndex so it matches Sprite_Light? */ }; Nyion.mp4 Edited October 25, 2019 by Nyrion Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted October 25, 2019 Share Posted October 25, 2019 btw stage.ambientOverlay.parentGroup = stage.sortGroup; stage.ambientOverlay.parentLayer = stage.sortLayer; you need only one of those. Groups are just the global variables, layer is in current stage. Theoretically, i can just remove all "Group" mentions from plugin at all and leave only layers. Group is just a handy CONSTANT, you can declare it globally without dependencies to stage. Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted October 25, 2019 Share Posted October 25, 2019 (edited) OK, now i really dont understand what do you want to do there. Behaviour with zIndex=1 is correct because you have a texture on that sprite, of course it affects somehow, tree itself is rendered above if that zIndex is smaller. Also, that place this.lightMaskOverlay = new PIXI.Sprite( PIXI.Texture.WHITE ); this.lightMaskOverlay.mask = this.lightMask; scene.ambientOverlay.addChild( this.lightMaskOverlay ); shows that you dont understand what pixi-layers is doing, and why all those layers (groups) exist. Because that code shouldn't exist at all if you use pixi-layers. Imagine that you dont use pixi-layers at all. You have a problem - some items you put inside a Character have to be rendered before/after all other elements. For example, Shadows and HPBar. You first renderer all shadows, then characters, then hpbars. Now we have a problem - when you add a character, you have to create three objects and put them in different containers. Also, if you destroy it, you have to remove shadows and hp too! Also, when oyu move character, you also have to change position of those things! pixi-layers allows you to put hpbar and shadow inside character but to render them when their parentLayer is rendered. That means , every frame for that layer "_activeChildren" are calculated, you can see the list of temporary children in that field of layer! In case you dont have direct reference to the layer, for example your architecture is very modular and exporting all those things is pain - you can use "parentGroup" , and group is really a constant in your global module. How light is done: we have separate layer that has filter on it, that way everything that is rendered inside goes into temp framebuffer, and the result is blended together. Now, we can add a light to character but specify that is actually light with "parentLayer = lightLayer" like here: https://pixijs.io/examples/#/plugin-layers/lighting.js ============== I think that you dont fully understand that code, or I dont understand your logic. I recommend to write the same small demo but without pixi-layers at all, then i'll show you how to add layers that way you can remove many lines of code. Right now it looks like layers only increase number of lines of code. For that purpose, try to animate position of those trees and move them together with light. In general, layers plugin is supposed to help automate things you already understand and can do by hand. Edited October 25, 2019 by ivan.popelyshev Quote Link to comment Share on other sites More sharing options...
Nyrion Posted October 25, 2019 Author Share Posted October 25, 2019 (edited) Thanks for the response ivan. I wasn't aware that assigning parentGroup wasn't really needed, i've noted this. Maybe I don't understand how pixi-layers works or my logic isn't understandable. Basically, the light sprites render in the correct order. The tree sprites also render in the correct order. It's the ambient lighting container thats at the highest zIndex that has the problem. If I don't add children (mask from the light sprite's texture) then obviously the lights aren't visible since the ambient lighting container sits above everything. But since the ambient lighting container sits above everything so does all of its children. I've created a new fiddle, with the pixi-layer stuff stripped out. **Basically the bottom tree should not be lit by the light. https://jsfiddle.net/4u9gw2sL/ Edited October 25, 2019 by Nyrion ivan.popelyshev 1 Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted October 25, 2019 Share Posted October 25, 2019 (edited) > It's the ambient lighting container thats at the highest zIndex that has the problem. your Light_Sprite is also a sprite with texture and its zIndex change affects the rendering order. Its children are ok Also I like people who are working on that kind of things, because they give me fuel for more changes in pixi-layers. I just look how people solve lighting problems manually , assist with removing masks when its possible (mask is a bit slow thing for many objects), and then compress their vision into new algo for pixi-layers. That work is actual impovement of good old Flash scene tree. Other renderers just add "displayLists" that cant possibly work with filters/masks or remove hierarchy like phaser3 did, before people asked to bring containers back. Here, we are working on actual improvement of concepts that people love. Edited October 25, 2019 by ivan.popelyshev Quote Link to comment Share on other sites More sharing options...
Nyrion Posted October 25, 2019 Author Share Posted October 25, 2019 I knew this would be a complex problem before I began as I couldn't find anywhere where someone else has done this (at least publicy posted). Do you have any suggestions on how to solve this? The only thing I can think of is to modify pixi-layers to include sub-children sorting of some type. For example... Say the "ambient lighting container" is at zIndex=999999 pixi-layers should render this at the appropriate zIndex. But lets also include a property say "considerChildZIndex" for the "ambient lighting container" And the "ambient lighting containers" children (which are mask Sprites) can also contain a zIndex (that matches the Sprite_Light's zIndex). So when the sorting is done in pixi-layers it will check for "considerChildZIndex" and if found will check the children of that and render the children in the proper order? Just thinking out loud, i'm not sure if this is realistic or feasible. Thanks ivan! Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted October 25, 2019 Share Posted October 25, 2019 (edited) I still believe its a problem with your sprites order and your usage of masks. I've specified stage.lightForSecondTree.renderable = false; and now i see that red light is gone completely. Of course it was rendered below the tree, like you specified. I dont understand the result you want to get Again, I remind you that mask is not renderable, it doesnt have order, at all. Its just pushed/popped when its time to render "lightMaskOverlay". Imagine that you have transparent-white version of that mask and you use it as a texture for "lightMaskOverlay", it'll be the same. In fact i can point you how to do it without mask but it requires extra plugins and i dont want to make it more difficult. Now, I want you to write me here complete order in which things should be rendered, and when do you want to apply the mask. Lets try make pixi scene that way the objects are rendered in order you want. I think that there's something wrong with that order. Yes, its sometimes difficult to imagine those things in your brain without drawing schemes. Edited October 25, 2019 by ivan.popelyshev Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted October 25, 2019 Share Posted October 25, 2019 (edited) What do we have : Tree1, Light_Sprite1, Light_Overlay (masked), Tree2, Light_Sprite2, Light2_Overlay (masked2). Also, ambientLayer that is rendered in separate framebuffer and then blended using MULTIPLY. Whats your order of things? Edited October 25, 2019 by ivan.popelyshev Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted October 25, 2019 Share Posted October 25, 2019 (edited) Btw, the result is usually worth it. We have that guy @ anisoft in pixijs slack who's very good at lighting and he's posting videos like http://youtube.com/watch?v=khj9zwuk9w0 I can invite you to pixijs slack if you want Edited October 25, 2019 by ivan.popelyshev Quote Link to comment Share on other sites More sharing options...
Nyrion Posted October 25, 2019 Author Share Posted October 25, 2019 The render order should be: Tree1, Light_Sprite1, Light_Overlay (masked), Light_Sprite2, Light2_Overlay (masked2), Tree2 The result I want to get is similar to what the video you posted has for lighting. Global ambient lighting with lights at different layers (notice how the light in that video is underneath the base of the tree) Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted October 25, 2019 Share Posted October 25, 2019 (edited) and how do you want to do that if light_overlay should be rendered inside ambient light, which is completely in different framebuffer, that should be applied after everything else? I dont get it whats special about base of the tree compared to the rest of tree Edited October 25, 2019 by ivan.popelyshev Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted October 25, 2019 Share Posted October 25, 2019 (edited) As an option, you can try to do the same thing in photoshop if you know how. Edited October 25, 2019 by ivan.popelyshev Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted October 25, 2019 Share Posted October 25, 2019 (edited) Maybe you want to separate base of the tree and put it under red light? Make two parts of tree? Edited October 25, 2019 by ivan.popelyshev Quote Link to comment Share on other sites More sharing options...
Nyrion Posted October 25, 2019 Author Share Posted October 25, 2019 (edited) I'm not sure how to do that ?, to get it to render in the proper order. The base of the tree is not illuminated by the light above it (I was referring to the youtube video you linked to). Edited October 25, 2019 by Nyrion Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted October 25, 2019 Share Posted October 25, 2019 no, I mean, your order is contradictory. Can you give me png of the result you want, something like that? Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted October 25, 2019 Share Posted October 25, 2019 Also in youtube all that light/ is used with some kind of depth map, it can be on different heights. Quote Link to comment Share on other sites More sharing options...
Nyrion Posted October 25, 2019 Author Share Posted October 25, 2019 (edited) Hope this makes sense, thanks! Edited October 25, 2019 by Nyrion ivan.popelyshev 1 Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted October 26, 2019 Share Posted October 26, 2019 (edited) Yep, it makes sense if you have containers "under tree" and "on tree" : layer_ground, layer_ambient_ground_light, layer_tree, layer_ambient_top_light. And you put your stuff in those containers. Yep, two ambient layers ? Now imagine how many sprites you have create per one object and understand why did i make that "layers" plugin. So, what to do: 1. try to compose scene with those two trees and ambient lights without pixi-layers 2. then ill help you to use layers for that 3. then we'll introduce sorting, there are several ways, i know short ones. Hm, why do you actually use pixi-4? Is that Rpgmaker-related? I can help better if you have pixi-5 Edited October 26, 2019 by ivan.popelyshev Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted October 26, 2019 Share Posted October 26, 2019 (edited) Also, there's a way to debug. First, without layers: just set "renderable=false" on containers that you dont want to see , leave only one that you are interested about. Remove its blendMode if you have one - now you see output only in particular "layer". Another way - install https://spector.babylonjs.com/ and press record button (page will be refreshed) then record again when you want to capture single frame. That way you'll see the progress how pixi draws the stage. For example, I take https://www.pixiplayground.com/#/edit/KwAJycAw0oEQd6_YKbQb0 and record one frame: https://monosnap.com/file/prMqppZ6DrPLmb4qNeFDBvEX2iSJAV https://monosnap.com/file/yXi7umGiTch6Yig1DdnrE0pSaG8ZPx You can see extra framebuffers. Also there's a list of webgl commands, and if you try Spector extension on that thing from playground - you'll see pthat pixi is pretty efficient. That's because I enabled batching of those circles with " PIXI.GraphicsGeometry.BATCHABLE_SIZE = 1000; Otherwise it could show how every circle was rendered separately. Yes, its a tool from babylonJS team. We love babylon for that! Edited October 26, 2019 by ivan.popelyshev Quote Link to comment Share on other sites More sharing options...
Nyrion Posted October 26, 2019 Author Share Posted October 26, 2019 The second fiddle I posted is without pixi-layers, will that work for your help? Yeah, I use v4 as there is a lot of dependency to allow for compatibilty with RPG Maker MV. Oh thats awesome, thanks for showing me that! Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted October 26, 2019 Share Posted October 26, 2019 Yes, jt worked. Its just not possible to put your light under tree as "ambient", you need extra layer below all the trees. Two things: 1.you want light1, tree2, light2 2. All lights have to be summed together inseparate framebuffer Thats a contradiction Actually there is a way to fix that , we need extra tree sprite in lights! I can explain it tomorrow, i need to sleep Quote Link to comment Share on other sites More sharing options...
Nyrion Posted October 26, 2019 Author Share Posted October 26, 2019 (edited) This makes sense, that is a good suggestion. Awesome, thanks for taking the time! I considered this before but wasn't sure how to take into account if the position/size/scale/texture/etc of a light changes or other lights that interesect if that makes sense. Edited October 26, 2019 by Nyrion Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted October 26, 2019 Share Posted October 26, 2019 OK, the idea of how to use one-layer-ambient and at the same time do what you want is : Put in ambient dark versions of trees. just "sprite.tint=0" in ambient for trees. You might wanna use gray version of trees, in that case you need dark-light tint, and here's the plugin: https://github.com/gameofbombs/pixi-heaven/tree/v4.x - that can also help to remove masks that you use (in case you multiply by transparent light, not black-white one!) 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.