logo80lv
Articlesclick_arrow
Talentsclick_arrow
Events
Workshops
Aboutclick_arrow
profile_login
Log in
0
Save
Copy Link
Share

Breakdown: How to Create a City in the Clouds with an Asian-European Style

Anthony Zheng shared the workflow behind the City in the Clouds project, detailing how he managed to create the castle using Unreal Engine's procedural generation system and explaining how he did the texturing.

Introduction

Hello, my name is Anthony Zheng. I am a 3D Environment Artist aspiring to work in the games and entertainment industry. I began my 3D art journey in 2021 while studying at Michigan State University. What started as a couple of fun classes quickly became an obsession. Early on, I began specializing in 3D environment art, as I found myself drawn to the field's technical depth and storytelling potential. 

After graduating in 2024, I recognized that I still had a lot to learn. As the industry became more competitive, I recognized that I needed to further develop my skills if I wanted to succeed. While balancing part-time and contract jobs, I dedicated even more time to refining my craft, treating each project and portfolio piece as a stepping stone towards the game industry. 

By mid 2025, I felt I was ready to take on something more ambitious. A project that would not only refine my existing skills but also force me to adapt new techniques and workflows. This led me to begin my latest project, City Above the Clouds.

City Above the Clouds

While deciding on the project, this incredible concept art by the Artist Ting Yue immediately stood out. I was captivated by the scene's composition and ethereal atmosphere. The way it invites you into its heavenly world suspended above the clouds felt both visually striking and narratively rich. The piece was massive, intimidating, and exactly the type of environment that would push me to my limits.

I immediately started looking into both European castles and traditional Asian architecture. Identifying and understanding how these two styles coexisted in the concept art was essential in building a world that felt fantastical, while remaining visually grounded and familiar.

I also gather references for smaller, detailed elements that would make the world feel more lived in and believable. This included studying ornate Asian motifs that would be used for my trim sheet, as well as brick and stone texture variations for the castle walls.

I also spent time researching vegetation native to the mountainous regions of China, as well as the rock formations that could form the striking mountains that exist in the concept.

The initial blockout phase was relatively straightforward and began with establishing the larger elements in the scene, primarily the landscape, castle walls, and towers. I always try to capture the overall atmosphere and essence of the piece as early as possible. Focusing on the composition and lighting before any of the smaller details.

Background mountains were generated within Gaea, allowing me to quickly define larger forms and silhouettes. The foreground landscape surrounding the city was sculpted within Unreal Engine to give me more control over the details. The building pieces were modeled within Blender before being assembled within Unreal, where I would continue to iterate on lighting and composition.

Procedurally Generating the Castle

I knew early on that hand placing every piece of the castle would have been time-consuming and difficult to iterate on. So I decided to dedicate a few weeks to learning Unreal Engine's procedural generation system to create a tool that would allow me to generate large portions of the castle within seconds.

This is the PCG graph for my main building structure. It grants me control over the building's size, height, wall types, ornate details, columns, and roof details, and smaller pieces like fences on the roof. While the graph might look intimidating for someone who has never used Unreal PCG, all of the features follow similar instructions.

Utilizing Unreal's blueprint and spline system, I was able to distribute modular walls along spline points and duplicate them upwards to create a multistoried structure. By multiplying the size of the walls and the number of floors, I was able to get the structure's exact height.

With this measurement, I am able to ensure the top floor, fences, or other ornate pieces consistently align with the top of the building. It is also essential to keep important values as blueprint parameters to allow control over the individual elements within the overview scene.

Beyond the main castle structure, I also extended the PCG workflow to create tools for controlling the size of my towers, spawning villages on top of my buildings, and populating my background mountains with foliage planes.

There are many great tutorials and introductions on Unreal's PCG system. This video by Procedural Minds was key in helping me create the multistoried building system and allowing me to control the height and wall pieces of my castle.

Texturing Process

For the texturing process, all of the materials used in the scene were made in Substance 3D Designer and Painter. With these being some of my more significant Designer Tileable materials used within the project.

Texturing an environment of this scale required an approach that would minimize noticeable texture repetition, while also reducing the amount of time needed for vertex painting different layers. In the end, I relied on a combination of procedural masking and layer blending techniques that allowed me to quickly and naturally blend together different materials.

For larger assets, such as the walls to the castle, my master material utilizes the world-alignment texture node to give me consistent control over the tiling size, regardless of the size of my assets.

On top of this, I introduced a cloud noise mask that allowed me to naturally blend between the 4 different brick materials. This not only creates natural-looking brick variation, but it also saves me time from hand-painting the walls.

The graph below controls the masking properties of the cloud noise between the different material layers. In order to make the masking as seamless as possible, I made sure to combine the cloud mask with a Height Lerp node to ensure the layers would merge realistically. I also added a vertex color mask to easily erase bricks from unwanted areas.

As a result, this shader allows me to procedurally layer multiple materials with control over each layer, significantly reducing the manual work of vertex painting each new layer into the scene.

Depth Field AO to Simulate Dirt Accumulation

During the Development, I realized I needed stronger shadows and dirt buildup to increase visual contrast on the castle and better define where large structures intersect. I found a solution that implemented Unreal's distance field AO node that simulates ambient occlusion between meshes within proximity.

In order to create a dirt-built-up effect, I ran a tileable dirt mask texture through the mask created by the DepthField AO node. This way, instead of functioning purely as an Ambient Occlusion mask, it can also simulate natural dirt accumulation in the crevices of the castle, further pushing the contrast in the castle without the need to paint on an additional material layer.

I highly recommend this video by AndrewWeirArt if you would like to learn more about the Depth Field AO node.

Trim Sheets and RGB Texturing

For a lot of the smaller pieces, I relied on a trim sheet and RGB masking workflow. The trimsheet allowed me to quickly introduce ornate details to selected areas on my assets. By utilizing multiple UV channels, some assets also incorporated additional RGB masking to further push visual fidelity and detail variation.

The images below showcase the workflow of one of my assets that combines multiple texturing techniques. The base is built with tileable materials, followed by adding trim details, and then finalized by adding RGB masking for additional edge wear and detail.

Having the option to blend between these three different methods not only saves a lot of time compared to creating fully unique textures, but it also aids in reducing draw cards, as multiple assets can utilize the same trim sheet and even share the same RGB texture mask.

Decals

As a final touch for texture variation. I added decals for dirt and broken bricks created within Substance 3D Designer. I wanted a mix between sharp and subtle decals, with the broken walls being more defined and the water drip stains being more subtle.

For the broken bricks, I wanted to experiment with Parallax Occlusion to create a sense of realistic depth that is harder to achieve with just a Normal Map.

Creating Custom Clouds

Looking at the original concept, I knew clouds were an essential piece to this environment. If I wanted to capture the same ethereal feeling created by those vibrant, fluffy clouds, generic fog and cloud planes were not enough.

To address this, I ventured on a side quest to learn how to create my own Volumetric Database (VDB) clouds within the software EmberGen. Experimenting with Embergen was quite fun, and it didn't take too long to familiarize myself with the parameters within the software to start creating realistic clouds.

Once the VDB was created, I encountered an additional challenge within Unreal Engine. I found that Unreal’s built-in VDB sparse volume material lacked the level control I needed for creating soft, fluffy clouds. The final results often appeared closer to dense smoke rather than an atmospheric cloud. To address the problem, I ventured out to create my own VDB shader.

This Tutorial by Winbush was a strong start to understanding the core features of the shader. After which, I expanded the shader by incorporating elements from Unreal's native Sparse Volume Material shader and additional nodes and techniques I learned from the Unreal community forums.

This approach gave me finer control over cloud density, opacity, color, emissive properties, and internal shadows. Allowing the clouds to better support the scene's mood and composition. All of the features in my clouds can be seen in the graph and video below.

Foliage

Foliage is another major aspect of the environment, but since it would be densely populated throughout the landscape, I focused much more on fast iteration and optimization rather than details.

The foliage atlas for all the vegetation in the scene was created with a combination of ZBrush, Substance 3D Designer, and Painter. I choose to model and sculpt the larger leaves and flowers to get more control over the details.

Foliage with more repeating patterns, like fern and pine leafs were created within Substance 3D Designer, as it gave me much quicker iterations on leaf density, scale, and variation. Once the atlas was complete, all of the branches and plants were created within SpeedTree.

My foliage shader took a lot of inspiration from this foliage shader video series by BenCloward. This provided a much higher level of control over the aesthetic of my foliage, compared to the default shader that's generated when importing directly from Speedtree.

Since trees occupy such a large portion of the environment, I wanted to reduce drawcards and polycount as much as possible to improve performance. This included using LODs to reduce polycount and reducing texture sizes.

Additionally, in areas that are far enough that the details are not readable, I replaced full 3D trees with intersecting tree image planes. This allowed me to significantly reduce polycount while preserving overall silhouette and visual depth of the environment.

Characters

As characters have never been my specialty, I didn't want to spend too much time sculpting out the traditional Chinese hanfu. So I decided to spend a couple of days learning Marvelous Designer to get a basic cloth simulation for the clothes, before further sculpting within ZBrush, adding accessories in Blender, and texturing in Substance 3D Painter.

As for the hair cards, I decided to experiment with a workflow that allowed me to build on techniques I was already familiar with. I started by simulating and grooming hair in Blender and baking the results onto a texture sheet in a Substance 3D Painter before texturing.

Once the hair cards were created, I decided to experiment with Nurbs Path curves to apply the hair cards. I first converted the path to a mesh and aligned it onto the hair cards. I then duplicated the original curve path to ensure they had the same resolution and points as the original.

I applied the duplicate curves directly to the head, creating the silhouette of the hair. From there, I continue adding more curves of varying sizes to fill in areas and introduce loose and dangling hair for break up and realism.

After the cards were placed, I converted them into a mesh and transferred the UVs from the original path, completing the hair assembly. While this approach may not be the most optimized method for creating hair, I was quite proud of being able to come up with a method that leveraged my existing skill set while also quickly producing game-ready hair.

Simulating Flowing Cloth in Unreal Engine

Since my final presentation included a video render, I wanted the shawl of the character to slowly float in the wind, reminiscent of celestial figures that exist in Asian mythology. To achieve this effect, I utilized Unreal's simplegrasswind node that applies a subtle world position offset to the mesh.

To ensure only selected areas are affected by the wind, in Blender, I used red vertex painting to define selected areas. This mask was then referenced in the Unreal material graph by calling upon the vertex color's red channel, allowing me to precisely control where the movement would be applied.

Conclusion

Overall this project took me approximately six months of on-and-off development, balancing time between contract work, part-time jobs, and preparing for unexpected interviews. This project has taught me far more than I initially anticipated.

Beyond learning new software and techniques to solve technical challenges, the project also pushed me to improve my time management and planning abilities to properly scope and execute my largest environment yet. 

This constant need to improve, innovate, and explore new ideas is exhausting, but it is also the aspect of 3D environment art that I enjoy the most. Every new project introduces its own set of problems to solve and systems to learn, constantly pushing me outside of my comfort zone.

Being required to adapt, experiment, and develop new workflows is what makes the process both challenging and rewarding. It is everything I love about making 3D environment art, and I am excited to start working on my next project.

My advice for other artists who are on this endless journey of improving their craft is the following:

  • Avoid Stagnation: I believe the worst thing an artist can do is nothing at all. Whether that comes from graduating college, being overwhelmed by work-life balance, or being stuck on a project that seems to never end. Stagnation is the enemy of growth. Being able to manage time and committing to the nonstop journey of improvement is the strongest quality an artist can have.
  • Planning is essential for any artistic project: This can come in many forms, gathering the right references, testing solutions to future challenges, or studying the techniques of others who have already walked a similar path. Art is an unpredictable mountain, so do not be afraid to set time aside to plan out a clear course of action.
  • Reach out throughout the process: None of my portfolio pieces would have been possible without the advice, critique, and feedback I received during their development. Do not hesitate to reach out for feedback while the project is still in progress. Another perspective can provide the clarity needed to push you forward.

Anthony Zheng, 3D Environment Artist & Modeler

Interview conducted by Gloria Levine

Ready to grow your game’s revenue?
Talk to us

Comments

0

arrow
Type your comment here
Leave Comment
Ready to grow your game’s revenue?
Talk to us

We need your consent

We use cookies on this website to make your browsing experience better. By using the site you agree to our use of cookies.Learn more