I started porting a 2d-isometric game from another engine to 3d-isometric view in JME3 today.
I’ve set up an orthogonal camera, made the terrain render, and am now at the part where I want to show objects on the map.
It worked nice so far, but now I have a special case where I can’t seem to find the right solution:
I have two 2D Sprites, a tree and some high grass, rendering both on the same tile.
Both of these graphics need different offsets to be centered on the tile and they’re both transparent, so I set their Bucket type to Transparent. Now, the render order is determined by how far away the Geometry is from the camera:
Which results in the grass to be rendered on top of the tree (indicated by coloured quads here):
My goal is to switch that around, to gain this result (that I stitched together in GIMP):
So, long story short, I want to have the grass being rendered below the tree.
As a sidenote, I’m planning to eventually mix both 2D and 3D, keeping things like grass as 2d sprites while bigger objects (like characters or walls) would become 3D objects.
What I’ve already tried / found out:
Using my own GeometryComparator for the Transparent BucketQueue, but that messes up transparency
If I adjust the grasses’ offset a little bit, moving it higher on the screen (in isometric terms, increasing both x and z), it will just dissappear, while the barrel I added for testing renders just fine “behind” the tree.
When I then used the barrel graphic instead and reproduced the situation, the barrel rendered just fine below the tree, which seems really weird to me:
The grass does render when I set the tree on wireframe mode, so it seems to be a similar problem like with the custom GeometryComparator.
The GeometryComparator was fine but you haven’t set an alpha threshold on the material… so even the transparent pixels are rendered into the z-buffer. My guess is that the barrel doesn’t have this problem because it is opaque and all of the opaque objects are rendered first.
Note: you may want to set your GeometryComparator to only partially render based on distance. Most of the stuff will still want proper back to front rendering. One approach would be to set some kind of layer indicator right on the Geometry’s user data and then use this to alter the sort order in your comparator when the layer info is present. Lemur has a more complicated example of this that it uses to render UI elements in a user-specified order.
the barrel was on the Transparent bucket too. I’ve set up my own GeometryComparator now (pastebin) that does it’s custom ordering if the geometries are entities sharing the same tile.
First of all, this is what I ended up with without doing any of that alpha treshold stuff:
The ordering is right, but as I mentioned in my earlier post, the transparency messes up.
I’ve enabled alpha testing (getAdditionalRenderState().setAlphaTest(true)) on the material, which ended up in a somewhat better result:
…but the core problem still exists, the alpha blending between the tree and grass only seems to work if they’re rendered in the correct order based on their camera distance (which does make complete sense if you think about it). So to re-phrase my question, is there a way to achieve the tree being rendered above the grass despite the grass being technically closer to the camera while still keeping the alpha blending functional?
My thoughts about it so far:
Somehow manipulating the bounds of the quads to match my needs without having the actual image move on the screen?
Some kind of multi-pass rendering?
The Translucent Bucket would probably fix this one problem, but would also mess up other things as the tree would be rendered above ALL other entities, even if the perspective would make you assume otherwise, so that won’t work (and can’t be generalized anyways)
Maybe I’m doing something completely wrong with the orthogonal isometric perspective?