Hi, I’m a collaborator working with OP on this game. Chiming in a bit during their downtime to clarify some things so they don’t have to do all the heavy lifting in communication on top of working on all the code.
Clarification:
What they meant by “multiple layers”:
We’re working on a game that is 2D & sprite based, but has a structure that imitates a Z-layer; think like 2D Zelda games like Link to the Past, where you can jump down ledges or walk down stairs, and the player is moved to another layer that has its own collision map so you can walk under bridges on the upper layer, things like that.
The way we have structured this is, each layer is an individual Node2D with multiple objects attached to it. This includes, among other things, an arbitrary number of “ground” TileMapLayers in each Node2D layer group; these all go underneathe the entities present on the layer, but it’s useful to be able to have multiple tilemaplayers so we can layer tile graphics over each other without needing to redraw a bunch of unique variants (e.g., imagine you have a bunch of ground tiles and you have a table you want to put on top of them but still see parts of the ground. We use multiple tilemaplayers for this.)
Above these tilemaplayers (well, below in the editor basically; but being lower in the editor makes it “above” them visually because of how Godot sorting works) we have a special tilemaplayer currently called PlayerLayer, but we’ll be renaming it to something like EntityLayer because we have been working on unifying our entity system, so I’ll be referringto it as that. This layer is also a child of the aforementioned Node2D. Currently, the purpose of this layer is to let us easily put tiles in the map that we want entities to be able to go behind it has Y-Sorting enabled, and entities are all children to the EntityLayer in each layer group so they interact with the Y-sort (additionally, this helps us make sure when moving an object from layer group to layer group, they can be paired to something that is consistently above the “ground” tilemaplayers)
Current Status & Problem:
This brings us to where we’re at right now and what we’re actually trying to accomplish here, versus the issue present:
As it stands, everything in the layer system functions just fine as we want it for motion (entities can move from higher layers to lower layers etc, and individual entities will correctly appear “behind” anything on EntityLayer if they are higher than that object y-positionally)
The issue is how this interacts with the shader. We do not want the entity to silhouette from standing behind, say, a short fence or a table or something on the same layer that they’re obscured by using the EntityLayer Y-Sorting. What we do want is to be able to grab information from the layers that are “above” the entities; i.e., if you’re in the “layer 3” Node2D group, you’d want to silhouette behind the combined tiles of the upper layer 2 and layer 1; walking under a bridge on an upper layer, for example, should show the entity as a shadow of itself, and we should be able to do this pixel-by-pixel so they can be partially silhouetted for the parts covered, etc.
We want the object to silhouette under things that are “always above” it-- i.e. on a higher layer-- but we also want them to simply get obscured by things on the same layer in EntityLayer without silhouetting. At present it works if everything they can be behind silhouettes them, but we don’t like the way that this looks with the Y-sort, so we want to be more restrictive.
The problem is that, we could really use some guidance on, basically:
- How to make the shader look at the the graphics drawn by tilemaplayers only on Node2D layers above the Node2D layers that the entities we’re trying to shade are on
- Some examples of functions, possible godot tools we’re overlooking, any abstract code examples that could help with this
- Any information about godot’s rendering engine that may be relevant to this, since it is largely a cosmetic effect we don’t want interfering with what’s in place
- How to make certain this works correctly with entities on a variety of layers without it becoming too system intensive, since we need to make sure it looks correct without having to iterate it for a billion cycles.
- Ideally, if the solution is possible without having to rewrite our layer system, since the way it works is built largely into how the game operates at present.
We’re not always certain how to “just draw” things displayed from several different tilemaplayers (nor how to grab the entities for their own buffer that can be compared against it) onto a single buffer that the shader can reference, so any specific advice on rendering functions is very welcome.
Sorry for the extra long post, but I hope this gives the detail necessary to get us where we’re going! Thank you for your help!