Before I had even settled on a definitive proposal for my Final Major Project, I already knew that I was going to use some form of modular level building kit to build it.
I’ve discussed the advantages of modularity in several posts which can be found on my main blog HERE but it wasn’t until I started to create the first version of my level kit over summer that the practical advantages became completely apparent. I had used similar kits before in other projects, mainly the Trident project which I had worked on over summer and it was the success of this project which spurred me on further to keep practicing modularity.
Last year whilst undertaking my Self Initiated Project, I mentioned Tor Frick; an environment artist who frequents the Polycount forums and is responsible for sparking my interest in alternate approaches to level building.
In his project Frick uses one texture atlas to create 99% of the incredible looking One Texture Sci-Fi lab environment.
For my Final Major Project I am taking a similar approach, but due to the constraints of my chosen engine (Unity) I do not have the flexibility that is offered by UDKs vertex painting utility.
Before modelling the tiles, I created several textures in Adobe Photoshop which can be used in a modular fashion. These first textures were a simple combination of phototextures combined with Photshop filters and 2D geomtery created using the shape and selection tools in Photoshop.
I was also introduced to Knald by my tutor, which I used to create some normal maps for the textures. Similar to NDo and Crazybump before it, the normal maps exported using the software were far too intense and resulted in artifacting in the engine when light was introduced. Admittedly this is down to my own inexperience rather than the software.
As you can see the textures above do not for an atlas, instead they are several separate textures placed together for the convenience of uploading.
I decided to create a test atlas to observe how the texture would tile and fit together when in the Unity engine. Below is my first attempt at a texture atlas for the project.
I then used this atlas to create a set of modular corridors which can snap together in the Unity engine to build my level. Before building the tiles however, I needed to find an appropriate scale to build to. In the past, the scale 512×512 worked rather effectively, in UDK, Source SDK and in my last Unity project. The environment in my Final Major Project however is in stark contrast to the large outdoor environment in the Trident Project.
To get a good idea for scale, and also the pieces which I would need to produce the environment I created some textures in Photoshop which would allow me to accurately gauge the scale when applied to plane primitives in Unity. I then used the planes to create a scene in Unity which I could use to test models, textures and scripts.
As it turned out, 512X512 was slight large for my intended purpose. There was several ways which I tested to remedy this problem.
Firstly I tried to raise the camera height of the First Person Character controller in Unity. This worked to a degree, yet I found that the higher center of gravity resulted in strange camera movement.
The second solution was to reduce the scale of the level tiles, which did not appeal at all. Using consistent measurements is crucial to producing modular environments, and having level tiles of odd scales would result in gaps in the level geometry, mismatched tiles and host of other problems.
In the end I decided to leave the tiles at the original scales. While this worked fine for walls and floor tiles, doors and windows had to be altered to scale properly with the player. Once I was happy with the scale in my test room, I started to apply the texture to my level tiles.
I already had a set of tiles which I created for my initial prototype in semester one. These tiles were constructed using simple cube primitives in 3DS MAX with chamfered edges. To keep the size consistent across the different tiles, I used the same value in the Chamfer dialogue: 32. This is advantageous for two reasons; firstly because it is a power of two, and secondly because it is a power of two it is easy to remember. After taking breaks from modelling it is often easy to forget things such as this, but by keeping the value part of the consistent power of two scale, it is easy to remember.
Below is the finished tile set – Version 1 with the texture atlas applied.
At first I was quite happy with this tile set. While the actual geometry was quite simplistic, the texture itself carried quite a lot of weight in terms of detail, adding visual interest to the walls. Add in the fact that the levels will be quite dark, I was satisfied that the tiles would fit together quite well.
Originally I created some standard shapes that would lock together easily to make the levels. Straight corridors, corner pieces aswell as rooms of various sizes. Soon however I realised that I would also need some standalone pieces for creating more varied and detailed interiors. Instead of starting from scratch, I simply used the edit poly modifier in 3DS MAX to tear some of the pieces apart, resulting in single walls, single floor tiles and mirrored corners which could be used to create more expansive rooms.
I imported these tiles into the Unity engine to test just how flexible they were, and spend a few hours experimenting with different configurations of rooms, corridors and more intricate constructions such as balconies, gantries and elevated corridors. It soon became apparent that by including vertical gameplay, as recommended in my first semestre presentation, the amount of tiles needed would increase exponentially. For every Corridor, a double height corridor would be needed. For every wall, a standalone wall, wall with ceiling and double height wall would be needed.
The irregular shape of the tiles, with chamfered corners also cause some problems. The tutorial featured HERE mentions keeping the “footprint” of the modular tiles the same, so they can fit together on either axis. The problem I encountered was because the chamfered parts of the meshes resulted in mismatched edges when placed against to the double-height meshes created for vertical gameplay.
This meant that the only way to create the double-height tiles would be to alter the chamfers on every single tile which would have a double height version.
Below is several mock-ups which I created in the Unity engine to test tile compatability, normal maps and lighting.
My first experiment was successful in some respects; I now had a definitive scale to work to and through experimentation am aware of the limitations and extents to which modular tiles will work. I’m aware that while corridor pieces ill work well for some parts, flexible and adaptable stand-alone pieces are needed to fulfill more intricate parts of the level.
For the second version of my tiles, I decided on creating more visually interesting corridors. Instead of small corner chamfers I decided to create wide, slanted corridors.
For the atlas, I used a combination of the textures I had created earlier, mostly the white metal wall texture which can be seen previously. At this stage I was trying to pin down a definitive look for the medical deck of the station, hence the white sterile look.
Creating the level tiles posed quite a problem; how could I ensure that the angle of the diagonal protruded feature was consistent through. I cam up with a creative solution, using a separat piece of geometry as a ruler/guide.
Below is an animated .GIF which demonstrates the process for creating the corner piece of the Version 2 tile set.
I used this same process for all of the pieces required, which were essentially the same as the last version minus the vertical double-height tiles.
Below is the version 2 tile set, finished and textured with several other assets made for the tile set including doors and windows.
Even this early in the project I was rather happy with this tileset. The way they fit together, the combination of colours and the overall style. That is not to say the’re perfect, my biggest complaint is with the texturing. Despite the fact that medical deck should be sterile and monotone, there is simply not enough variation to spark any visual interest. I decided to create a test level using this tileset to observe any problems which might arise from using such a neutral palette.
After constructing a test map in Unity, I realised there were a fair amount of errors in the tileset, the most prominent being smoothing errors.
There was also a problem with optimisation; the small level viewed below generated as many as 2 milion draw calls at run time, resulting in sluggish performance on higher graphic settings when built using Unity.
I carried out some research into opimisation in the Unity engine, finding some excellent sources of advice and practical ways to optimise my level. The links below gave me great insight into the behind-the-scenes processes carried out at run time which result in performance hits.
Using this information, I formed a plan to help with the optimisation of my project.
Firstly, as per the recommendations above I decided to minimise the amount of textures in my scene as much as possible (which was already part of my initial concept, using texture atlases and modular texturing rather than unique textures per-object)
Secondly, marking all inanimate objects as static in the editor. in essence this was already a requirement to bake the lightmaps into the level, albeit with a greater performance benefit than leaving it unchecked.
Lastly, through reading other peoples problems on the forums I discovered that it is inefficient to have dynamic lights affecting multiple meshes. To reduce any performance drops associated with lighting, I decided to minimise the amount of Per-pixel lights in each scene to 3. I could have reduced the number even further, but flashing broken lights help to create the atmosphere and ambience which I am aiming for.
Taking into account the lessons learned from my first and second attempts, I aimed to create some more detailed and visually interesting level tiles. After reading and re-reading Thiago Klafke’s modular environment building tutorial I decided that I wanted to introduce some more organic, curvaceous elements into the environment.
At this point I had also decided that the absence of normal and specular maps had left the previous environments looking rather underwhelming. I decided to re-employ the skills of projection mapping and normal map baking which I started to develop in the second year to create my next modular texture.
I started in 3DS MAX by creating a plane primitive which was subdivided into 4. This would serve as the plane onto which to bake the finished normal and ambient occlusion maps, which I could then use to create my texture atlas.
I gathered a ton of reference image from various sources online to help me decided on what elements to include in this new atlas. When I was happy with the various elements I sketched out the layout on paper, making sure to use the power of two scale which I previously dedicated. By using this scale consistently with texture work aswell as modelling, I was maintaining both scale and proportion, in the sense that a trim texture measuring 32 Pixels by 512 Pixels would fit perfectly onto geometry measuring 32 units by 512 units.
Below is several sketches of various texture panels and modular atlases which I planned on implementing. Some of the textures are unique, for sections of the environment which would be rarely repeated whilst others I tried to make as versatile as possible, to be mapped onto different pieces of geometry in the level.
The design I decided to go with for version 3 can be found on the left, divided into two 512 x 512 sections. For the sake of visual fidelity however, I rendered the projection out at 2048, resulting in a 1024 x 2048 texture atlas.
Below is the high poly mesh used to bake the normal and ambient occlusion maps used for the final meshes as well as the final texture.
To create the texute I imported the ambient occlusion map into Photoshop to use as a mask.I then used the hue/saturation functions to lighten and darken some areas of the texture to create contrast. I the overlaid a subtle metal texture over the top of the ambient occlusion mask and then used the fill tool set to all layers to create the chipped and worn metal effect which can be seen on the red metal trim.
This texture atlas turned out far better than my previous results. The red accentuates and adds variety to the texture and the trims can be used to great effect on doorways, edges, girders and the like. Using this atlas as a base, I created the version 3 tileset which can be seen below.
I used the same process to create these tiles as the rest; adding in edge loops and extruding to create the bottom and top border and then overlaying the appropriate UV islands over the texture map in the UV editor in 3DS MAX. Creating the arched doorways and windows was a little more problematic. I tried several methods, but the one detailed below seemed to work best.
Integrating the arch into the wall panels was simple enough. I added two extra edge loops vertically to the wall panel and then one vertical. I then deleted the faces where the archway was to go and then applied a symmetry modifier to the doorway until it was an appropriate size.
Again, as with the rest of my tile attempts I created a small test area in Unity to see how the tiles fit together and look together.
As I mentioned earlier this version of the tile set was my favourite by far, however I had not planned far enough ahead in terms of composition. I realised that by adding raised borders to the floor pieces, I had to ensure that any wall tiles must also fit flushly with this border. For tiles which run parallel to the floor panels, that was not an issue. For tiles which were perpendicular however, I found that gaps had appeared between meshes which affected the lightmapping of the test level. A similar problem had also occurred with the wall tiles. Again referring back to Thiago Klafke’s tutorial, the vertical edges of the wall tiles were not straight. This meant that any other mesh which would be used in conjunction with the wall tiles must also have the same profile.
This comes back to the theory of a “footprint” for the meshes, or a precise area in which each mesh should occupy in order to be tileable on both a horizontal and vertical axis.
The main problem I had with this set however was that I had miscalculated the size of the seperate areas in the atlas. I was under the impression that halving the original size of the atlas (2048) would allow me to keep some semblance of organisation when it came to the UV mapping process. In particular I thought that I might be able to use the snap function in the UV editor to neatly allocate the space to the necessary islands, and the fact that the edges and vertices on the UV map would be snapped would reduce the amount of seams in the final models. Unfortunately this was not the case. I soon discovered that the grid spacing and snap settings in the 3DS MAX UV editor work of a seperate scale, and do not allow for custom grid spacing to the extent I required.
Lastly, the tileset was just not as flexible as I first assumed. I found it difficult to create more meshes using the atlas as a template due to constraints which were imposed by the size of the sections in the texture atlas. The floor pieces featured above for example, required mirroring one small section of the atlas four times which resulted in four times the amount of polygons.
For this next tile set, I tried to reinvoke the spirit of the last, reusing some of the forms and patterns, but with the aim to make it more flexible by adding as much detail as possible.
Version 4 was also produced from a high to low poly projection, albeit much more detailed and ultimately more complicated.
Like the last set, I created the high poly by subdividing a plane and using each smaller plane as a guide to create the geometry. This time however I ensured that each section was accurately proportioned, resulting in a much cleaner method of unwrapping which allowed me to snap the vertices and edges to grid lines in the UV editor as mentioned above. Also at this time in the project I had found a reliable and high quality screen capture software. Below is a recording of the process of building the high poly mesh for version 4.
Unfortunately I’ve had to cut the video down. Even sped up to 800% the total video was still 30 minutes long, but below is a screenshot of the finished mesh, from which I projected the ambient occlusion and normal map just like before.
I encountered a problem while working on this atlas which would not allow me to project the entire mesh onto the plane. I instead I subdivided the base plane by 4 and projected each quarter of the atlas as a 1024 map. I then compiled each quadrant of the atlas in Photoshop, resulting in a 2048 x 2048 texture atlas which lots of features.
Despite my effort to create an extremely flexible atlas by adding more detail, I found that the sheer amount of detail in the atlas resulted in a low resolution, pixelated texture. Nevertheless I endeavored to continue testing it to see whether I could salvage anything. One thing that did work was my calculation in subdividing the atlas into sections, enabling me to quickly snap the vertices and edges in the UV editor. I created a texture using the same method for version 3 and then got to work building the tiles.
Again I used the same method of extruding and editing a 512 X 512 plane. The tiles created were essentially the same as version 3, with some minor differences. Firstly I used the symmetry modifier to produce some corridor tiles, similar to in version 1 and 2. Creating the more intricate tiles such as intersections was actually really simple. I realised that by rotating the symmetry modifier gizmo by 45 degrees I could mirror the geometry into corners, and by adding yet another symmetry modifier that corner would become a 4 way intersection.
I thought that reducing the extruded details on the wall might enable the different modules to snap together more easily, however the same problem as last time was present, with holes in various parts of the geometry. I also experience a strange error in which some polygons would not render at all when imported into the Unity engine. After the work put it I had to abandon yet another tilset, yet all was not lost.
After experimenting with four different styles and methods of creating the tiles I had learned a lot about how best to implement the system.
Taking a look back at both Thiago Klafke’s Zest Foundation and Tor Frick’s One Texure Environment, I came to the realisation that despite both environments looking extremely polished and complex, the individual components themselvs; the tiles, weren’t all that complex.
And more importantly they follow the “footprint” rule mentioned earlier, Thiago’s especially.
I also noticed that Thiago’s textures were relatively sparse, devoid of noisy detail and the texture itself was also subtle allowing the units to tile without seams, he also included “buttress” features on the end of some of the meshes to hide any seams that may be present.
After downloading the .UPK and .UDK graciously provided by Tor Frick on his website, I examined how the level is constructed. On the surface the environment looks intricately detailed, examining the various components in the scene however shows that the majority of the level itself is created from simple shapes, subdivided and UV wrapped with expertise to show details where they are required.
I also noticed that there is floating geometry present on some of the models which allows details to be mapped onto using the UVW modifiers in 3DS MAX. This explains how the pieces can be so varied even using a single texture, albeit with the tradeoff of a higher polycount.
And lastly I noticed that Frick had used small pieces of geometry to cover the lightmapping seams which are present in the level.
Despite having abandoned a considerable amount of assets, not to mention time, I now felt ready to prepare my final tileset for building my levels.
Over the course of this project and after abandoning each phase of tiles I had learned from each mistake, picking up methods and techniques over time which I now felt prepared to integrate into my final build.
– Keep a consistent scale for each asset (128,256,512,1024)
– Follow the “Footprint” rule
– Subdivide the texture atlas 3 times, no more; the grid in 3DS MAX only supports up to 3 subdivisions
– Quantity does not equal quality. Find a balance between large panel textures and trim textures
– Decals can be used to add variety to tiles
– Symmetry modifier in 3DS MAX can be used to quickly create additional level tiles
– Mark level meshes as static to enable draw-call batching
– Use subtle textures, rather than high contrast textures that do not tile well.
– Plan ahead; list the assets needed and check whether they are compatible before building, texturing etc.