Development Pt.4 – Environment

Development Pt.4 – Environment

Let’s focus on environment for a bit. First thing that comes to my mind when talking about environment is nice and neat visuals, . But I would say that there are 2 main elements that create vide game environment, which I would say is visual aspect, and functional aspect as well. Everybody knows what visual aspect is, so I’m going to focus more on second one, functional aspect of the video game envrioment. It could include simple functionality like environmental story telling, arranging objects to tell a story of great battle, or ambush in a forest, a story which is communicated through the visual representation only, without a need of extra description in form of audio narrative or text. Secondly, it could include aspects that can directly affect game functionality/mechanics, like finding specific creatures or resources on some parts of the map only (crocodiles in tropical parts of the map, mammoth in arctic areas of the map…etc.) , or during the specific time of day (i.e. vampires during a night time, werewolves during a full moon only…etc.). Or we can even combine time of the day with a location. Let’s say you need “thick werewolf skin” to craft piece of armor. We know that we need to look for werewolves during a full moon only, but where to look for werewolf with a “thick” skin? Probably not in tropical areas, but rather in freezing, winter environment, where they have adapted to harsh winter conditions by developing a thicker skin that protects them from freezing temperatures. So this type of creature could be found in snowy forests during a full moon phase only. We could also include environmental story telling, to allow player find werewolf faster by placing some werewolf footprints leading to his den…etc. It would help to avoid frustration from spending great amount of time by looking for this specific enemy. Ok, enough talking, let’s jump on development part.

Environment – Visual Aspect

For a change, let’s focus on visuals a bit. Taking into consideration game setting, which is fantasy world with a bit of realism, I imagine dense forests, castles and ruins, remains of ancient civilizations…etc. So let’s start with the forest and floiage. First time I started thinking about creating a game ready tree, I thought “nah, easy, it’s just a trunk and branches with alpha cut-out”. Well, in theory, yes. But in practice, hell no. Making nice and believable realistic foliage that can run in real time is very complex process. Especially because it includes transparency, which is very expensive thing to calculate in real time, and as far as I know, it can’t be done using deffered rendering method, but only by using more expensive forward rendering. Ok, let’s get back to the trees topic. Let’s define first what makes trees and foliage believable. At first, it’s light scattering. A nice effect created by light rays passing through leaves, which is created using additional textures. Secondly, it’s movement (branches and leaves sway…etc.), which is created mostly through the shaders, using WPO (World Position Offset). At this point, knowing complexity and time needed to create enough foliage assets in high enought quality, I’ve decided to pay for a Speedtree license, which is very afordable for indie developers and would save me plenty of time. But, it wouldn’t let me sleep if I wouldn’t explore possibilities how to create such an effects.

Foliage and wind sway

As mentioned before, this is usually done through the shaders, by moving vertices. Let’s approach it as modelling or texturing process, primary detail first (offsetting a whole tree), then secondary (offsetting branches and twigs independently from tree trunk) and tertiary (offsetting twigs independently from branches). So first, i want to get wind direction, which we can store as Vector3 variable (but I’m going to use only first 2 vectors, disregarding Z vector). This variable tells me which direction wind blows on world X and Y axis, and will be used to define direction of vertex offset, and I’m also going to use another variable, wind strength, which defines amount of vertex offset. First thing I want to do is bend a whole tree depending on wind direction.

Offsetting vertices would basically move all vertices, what would result in offsetting whole tree (top picture). But I want tree base to stay on the place, like in real life. For this purpose I’m going to use simple gradient map, that would be used as mask. Think about gradient more like a “value” where black = 0 and white = 1, rather than a colour texture. Multiplying wind strength by gradient will result in moving vertices based on they distance from the tree base/root. Final result is definitely not what I’m looking for. Tree should bend, not tilt.
To fix it, I’m simply going to use “windStrength” variable to offset vertices on Z axis. Tree should bend down, towards the ground, so I’m going to multiply “windStrength” by -1, to get negative value, and this value will be used to offset vertices on Z axis. Same method will be used to bend branches and twigs, but using only X and Y axes. Now it’s time to prepare tree model for testing. For this purpose I’ve decided to use tree model with 3 different UV channels. First UV channel for texturing, second channel for bending whole tree, and third channel to bend branches and twigs independently from tree trunk.
A quick tree mock-up created in Blender. Left image is model with original normals, and right image is model with all normals pointing outwards. This method helps to get nicer, smoother shading on foliage, and individual branch planes are not as visible. Next step is to prepare UVs.
UVs are simple side flat unwrap. Overlapping faces doesn’t matter in this case. Simple gradient map is used as mask, and defines how strong effect “windStrength” variable will have on different parts of the tree. But, there is still one more thing that I have been thinking about. While one side of tree is directly exposed to the wind, other side is in cover, so it should not be affected by wind as much. As long as wind direction is not static value and can be changed, this can’t be done using simple gradient map. Well, in theory, using flat UV unwrap from top view and gradient map that is rotated based on wind drection, it could be done. But I’m going to do that by using object’s world position.
So, at first I want to extract object’s world position (Absolute World Position – ObjectPosition), and then multiply this value by wind direction vectors (X and Y axes only). This will define which side of a tree is facing the same direction as wind (top picture). Last step is to invert this mask by multiplying it by -1 (or invert wind direction). Now this mask can be applied on branches and twigs. Very last step is to multiply final result by B&W noise map, that is slowly moving in wind’s direction (using world coordinates), to fake wind turbulence.
Custom tree sway shader, presented in UE4.

So everything works as expected, tree is bending, branches and twigs are swaying independently from tree trunk, and wind has limited effect on branches that are in cover, behind a tree. But, as I meantioned at the start of this topic, I’m going to use Speedtree, since I really don’t have a time to create rich variety of tree models. But it was nice to explore this topic and learn something new.

Optimization

Small note regarding performance and optimization. Since this method is using multiple UVs, we can simply create simplified versions of the material, and assign them to the different LODs respectively.

  • LOD0 – Highest detail, using 3 UVs. Tree trunk, branches and twigs are animated.
  • LOD1 – Medium detail, using 2 UVs. Tree trunk and brnahces are animated.
  • LOD2 – Low detail, using 1 UV. Only tree trunk is animated.
  • LOD3 – Static mesh, no vertex animation.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Create a website or blog at WordPress.com

Up ↑