Hamid Khoshbakht discussed the recent project that he worked on together with Emran Bayati and shared the workflow and tips for working with modular packs.
My name is Hamid Khoshbakht. I’m a self-taught environment and level artist. I started my career as a level designer in an indie company. I worked on several indie projects and also a real-time animation series. Currently, I work in Codemasters studio as an experienced artist. The first AAA title I worked on was Grid 2019, where I mostly worked on terrain, terrain textures, and also on buildings. And now, I’m working on Dirt Rally 2.0 DLCs.
Well, medieval castles are always appealing for environment artists. It started when my friend Emran Bayati showed me photos of a gorgeous Spanish castle, and we decided to create such an environment in UE4 together. Although we weren’t faithful to this particular Spanish castle and tried to achieve a generic modular fortress.
The goal I wanted to achieve was a package that:
I wanted this set to be simple and minimalistic but highly customizable, and also to make it possible easily integrate on different levels. The reason behind this ‘’simplicity’’ was that creating a complex and full-detailed environment may take months. And it’s harder when you do such a project besides working on your full-time job!
I also didn’t want this simplicity of assets to lead to a plain and low-detailed level.
Models can be categorized into 4 different sets :
As mentioned before, asset production time & simplicity were IMPORTANT in this project. So, we tried to avoid complex assets, especially in modular parts. All assets are made by poly-modeling in 3Ds-Max, and some rare assets had a small touch in Zbrush.
Part of the job like walls, props, and bodies was done by Emran, and I created wooden structures, foliage, and cloths.
Firstly, I want to talk about the workflow and the “big picture”: I decided to use the Material Layering method, which nowadays is a popular workflow in Unreal Engine. In this workflow, there is a material library made with tileable textures, and these materials are used as layers in different assets. For example, one tileable wood texture is used in different wooden assets.
This was beneficial for several reasons:
For the first pass of texturing in this project, my focus was on creating a simple material library. To achieve this, I needed to create material functions using tileable textures and noises. Some simple functions I could achieve inside Unreal Material Editor by using different noises as masks (like simple metal), while for other functions, I was heavily dependent on Substance Designer (stone walls, wood, tree bark etc)
I also created a pair for wall textures meant to be used with vertex painting.
An example of tileable textures created in Substance Designer is Stonewall: my goal was to create only one substance graph but to be able to get various results by just changing input mask and tweaking parameters. It was a challenge, but the result was satisfying for me.
I created a stone wall, cobblestone, brick, and floor materials with just one graph.
The second step was creating materials and material instances.
This scene is composed of less than 20 master materials. Some of them are simple (like the master material used for unique assets) and some are more advanced.
An example of material creation is the floor. I had a tile material on a 2x2 meter module, it was repetitive, after creating a vertex-paintable material, I used a clouds noise as world aligned texture and used it as a mask to change luminosity, color, and roughness of floors. Using this world-align feature means these details will be applied non-uniformly based on the location of mesh in the world. After that, vertex paint was used to add more details to the floor.
A good modular package helps you to populate your world very fast and also gives you tools and options to avoid or hide repetition.
As you know, creating large scale environments and worlds is a huge and time-consuming process and may take months to accomplish. But with a good modular design, it can be achieved with a great saving of time and resources. And also it’s more memory friendly because of instancing features and reducing textures quantity.
Lighting: since this environment is large-scale, I didn’t want to go through the time-consuming baking light process, so I chose the dynamic lighting setup. Also, I used LightPropogationVolumes(LPV) for indirect lighting. LPV is a system for dynamic global illumination in the Unreal engine.
One thing I always do at the early stages of creating levels (before starting the asset production process) is setting up a basic lighting(something close to the desired lighting that I want to achieve) and testing my textures and materials in this setup. This way, I reduce the time of re-editing textures at the final lighting stage.
I wanted this package to look good in different lighting conditions, so I set up 3 base lightings: daytime, sunset, and night.
I created a level for each of these lightings and linked them in main test map. This way I could easily switch between lighting scenarios and check how assets look.
I achieved the final render by tweaking and playing with main light source, skylight, height fog, and post-process volume.
To make the scene more dramatic, I also created a simple volumetric fog particle using tutorials on youtube. The post-processing part was also a bit of playing with color-grading, bloom, AO, and etc. The only thing to mention is the post-process material I created to sharpen the final render to give a bit of strength to the final image.
Design your modules and test them by block-out before jumping into the production of the model. Creating modular environments is a precise and punctual process. Your modules need to snap and tile correctly.
Do not give character to your modules either in geometry nor texture, because these elements will repeat and will look awful. By character I mean: any high contrast detail that will catch the eye while repeating.
Although this does have a drawback. This will lead to a plain and monotonous module. To overcome this you can: