#006 - Tree Time
Hmm... let's see, it's been... checks notes... Two weeks since my last devlog! How the heck did that happen?
Honestly, I've had a lot going on these past couple of weeks, and I'll continue to have lots of stuff happen for the rest of this week and probably the rest of the month as we approach the holidays, but I figured I should at least make time for this devlog about a feature that's already been out a week.
So, let's talk about trees.
Why Though?
I figured trees would be a necessary feature for a number of reasons, including:
- Making the world feel less barren and more diverse. Granted, trees on their own don't help too much, but having at least two different biomes, like what was introduced in 0.1.5 with forests and plains, helps make the environment feel quite a bit more interesting.
- The limited sight that trees create on the landscape provides an additional challenge to the player, as well as having to avoid the trees on low speeds.
- A lot of engine features, like entity collisions and stencils, have yet to be fully implemented, so having static entities with well defined boundaries to test them on lets me see how the collision systems are faring relatively easily (and helped me realize it was all broken when 0.1.5 came out).
To address the additional challenge that trees create, you may have noticed that the wall doesn't accelerate quite as fast in 0.1.5 as it did in previous updates. In fact, it accelerates at half the rate now. This change was a while coming, and I find that the game is still quite difficult to complete even with this change.
Tree collisions will hopefully be much improved when 0.1.6 releases, which will probably not be for a little while longer.
From The Roots
Work on trees began shortly after 0.1.3's release, during Thanksgiving week (for non-Americans, that was the second-to-last week of November this year), and they were originally slated to release with 0.1.4, however they ended up getting delayed to 0.1.5 due to issues with static entity generation (more on that later).
The initial tree models I used I actually borrowed from another project I was working on back in September (they're procedurally generated, but I borrowed the algorithm used to generate them). I was pretty dissatisfied with the models once they were given proper shading and lighting. I did get some funny results when messing around with the generators, though:
I figured I'd move on to something a little simpler, so I did. Rather than going for a sprawling oak or maple, I figured I go for the simple pine.
To begin, I started with the stem.
Pretty simple, right? I messed around with these for a little while, adding simple 'leaves' to them. Thinking ahead, I knew that I wanted different types of models to generate for different levels of detail, and I figured I'd start with the lowest first.
For low level detail models, you want to give the player a good sense of the overall shape of the model without overworking the GPU with excessive details. Hence, shape was what I was really trying to get right here, and I think end the end I got it pretty good. These models just contain the stem and simple triangles for leaves, and when viewed from a distance they look pretty good.
Now, it was time for higher-detail meshes. To start, I turned the simple green triangle leaves into brown triangle branches, which appear to jut out like needles when there aren't any actual pine needles on them. It took a while of experimenting, but I did manage to put some leaves on the branches, which are little cross meshes attached to each branch at a random angle.
After encountering some strange issues (seen near the end of the video), I even applied a texture to each of the leaves as the cherry on top, and that pretty much solidified their final look for the upcoming patch, all before 0.1.4 came out.
Of course, this was only half of the battle for implementing these funny little plants, the other half was the reason the update got delayed.
Forests
The issue I mentioned earlier, static entity generation, was the challenge that themed the latter half of the final week of November, and it's a challenge I still have yet to fully overcome.
Here's the issue laid out in full:
Beaconfall classifies trees as "entities," which are drawable game objects with a given position and scale (boundary) to whom events can be performed (such as spawning or collision with other entities, such as the player). Fair enough, right?
To help optimize things since there are a lot of trees that get drawn, even at high levels of detail, Beaconfall further classifies tree entities as "static," which means they won't move between sectors. This is important, because it allows the tree meshes to actually become part of the sector meshes themselves, drastically reducing the number of draw calls that would otherwise need to be made and increasing performance.
So, if the trees are generated when the sectors are generated, then both need to be generated together. Here lies the heart of the issue: how will they generate?
I mean, my requirements for the generation scheme aren't that complicated, just make sure that the trees are spaced out enough and generate in "forest" areas - which are defined by a simple gradient noise function. But we need the exact points where they'll generate to be the same across different sectors, with different levels of detail. That's a problem, since it means we can't use the previously generated cells used for the terrain for the trees, since there will be less of them the further away they are from you.
My current solution is to use "entity cells," which are scaled equally in world-space but scale down progressively relative to the increase in sector sizes. Each entity cell is scaled to match the scale of a sector at it's highest level of detail.
Each of these cells can "generate" - which is to say, fill with a collection of points, and then "collapse" - move those points to where they're supposed to be. These points are matched with entity types and positions, and trees are generated at their location. Since this is a tough task to do, especially when the world gets a little further out and you end up with sectors with a 27x27x27 (19683) grid of entity cells, some optimization is required.
The most effective level of optimization I currently have is to only count entity cells that are colliding with the surface of the terrain. This makes the final result much more accurate to what I want.
There's a problem, though. When testing it out initially, this resulted in some inconsistencies with tree generation across different levels of detail. Routinely, trees would disappear and reappear while wandering around forests. Entity cell viability is measured with the cell values that are generated with the terrain, rather than sampling new values and making the generation take twice as long. But at certain levels of detail, these measurements might get a little inaccurate and entity cells which shouldn't pass the viability check end up getting through, or vice versa, resulting in more or less trees generating, respectively.
I spent a couple of days messing with the values, broadening the boundaries of each cell, trying to get something which resulted in good consistency. In the end, the results are definitely better than they were when they started, but are by no means perfect. It seems these days there are certain patches of the world where trees don't like generating at certain levels, which I've taken to calling "phantom glades."
(Not pictured here, I don't have any footage, they're a little difficult to come by)
Trees currently only generate in the first 4 levels of detail for sectors. As something to cap off the forest generation, I added in extra detail so that lower levels of sectors: a slightly darkening of areas where forests are present far off in the distance (which you can see in the video).
This can result in some very odd transitions between level 4 and level 5, where the base color of the terrain suddenly gets a lot darker. I'm thinking in the future I'm going to add an even lower level of detail for trees - just a stencil cross-mesh, to be applied to lower levels of detail, to make this transition less jarring.
I briefly experimented with putting trees at even further levels of detail. This ended up being way too slow and made the forest look way too dense, but it looks pretty cool. This is also an example of a phantom glade - the large hole in the center gets populated with trees once you move in closer. For the record, this is the biggest one I've ever seen, and I'm not sure phantom glades of this size are even possible in the actual release.
And that pretty much brings you up to speed with 0.1.5. I also added a developer console with that patch, which I'm almost certainly going to be making heavy use of in the future, but this pretty much covers everything that went into last Tuesday's release.
But We're Not Done Yet
Remember those artistic principles I brought up in the last devlog? I mean, it was a while ago, so I wouldn't blame you if you didn't, but I feel that the trees released in 0.1.5 didn't quite meet those principles, so they'll be getting a small redesign with 0.1.6.
Here's how they currently look:
As you can see, they look a little less realistic and more bright and blotchy than before, in order to match an overall painted look. This change has given way to some of the more apparent issues with using cross-meshes for leaves - they clip into each other in rather unsightly ways at certain points. Again, this design isn't final, and is subject to change, whether with this upcoming release or the next.
Another thing that I absolutely need to bring up is this issue:
Beaconfall's z-fighting issue is something I've always been aware of since the start of development, and I attempted to address it in 0.1.4 (which ended up creating more issues that needed to be patched with 0.1.5), but while z-fighting on large entities such as the wall might be relatively trivial to handle, there's only so much I can do on z-fighting with individual meshes once you reach far enough to touch the beacon.
In 0.1.6, the game will use a higher-precision depth buffer, which some GPUs support, and it should calm down the z-fighting a bit, but this is an OpenGL issue that I'm going to have to figure out a work around for, whether that means somehow simulating and creating my own depth buffer, or perhaps even creating a new renderer in a more verbose rendering API such as Vulkan.
Alright, I think that's all for now. As mentioned at the start, it's been a little slow compared to last month, and it will probably continue to be slow for a little while as I attempt to navigate an important transitional period in my life (graduating college). My current release window for 0.1.6 is "sometime before the end of next week," so like... December 23rd at the absolute latest. There's a surprise feature that I'm cooking up which will take up a bunch of my time as I get ready to release it. I don't think it will actually take that long though.
As always, thanks for reading! Maybe the next devlog won't take as long :)
- 0de
Get Beaconfall
Beaconfall
Existential running simulator.
More posts
- v0.1.8 released.Jan 06, 2024
- v0.1.7 released.Dec 31, 2023
- v0.1.6 released.Dec 26, 2023
- #007 - It's Not Coming Out TodayDec 24, 2023
- v0.1.5 released.Dec 05, 2023
- v0.1.4 releasedNov 29, 2023
- #005 - Painted HillsNov 28, 2023
- #004 - Everything Is Made of IceNov 20, 2023
Leave a comment
Log in with itch.io to leave a comment.