Tools are everything in game development today. Let me quickly tell you a story. Back in 1983 home computers were simple enough that you could create a virtual city (made of blocks) using nothing much more than pen and paper to scratch out lines of hexadecimal code. The code would then be entered (by hand) over several coffee fuelled evenings and assuming you got every number correct and didn't suffer a tape loading error you could make amazing new worlds. If this sounds primitive and a lot of hard work, well it was. The technological equivalent of scratching out lines of dirt with a plough. Pioneering stuff.
Modern three-dimensional games are several orders of magnitude more complex than Sandy White's 1983 Ant Attack on the Sinclair ZX Spectrum. To create lush visuals expected from current games, we rely on a host of tools to generate content at different stages of production. Quite often, terrain is the canvas on which content is painted, if you think about it, while you might play a game and think how great the scenery looks, you're not necessarily looking at the terrain but rather the textures, vegetation, buildings and everything else that artist has constructed around it. Before we dive into using GROME we're going to cover some common caveats that apply to most game engines. In this chapter we're going to look at:
Describing a world in data
Game world scales
Starting a new GROME project
Just like modern games, early games like Ant Attack required data that described in some meaningful way how the landscape was to appear. The eerie city landscape of "Antchester" (shown in the following screenshot) was constructed in memory as a 128 x 128 byte grid, the first 128 bytes defined the upper-left wall, and the 128 byte row below that, and so on. Each of these bytes described the vertical arrangement of blocks in lower six bits, for game logic purposes the upper two bits were used for game sprites.
The arrangement of numbers in a grid pattern is still extensively used to represent terrain. We call these grids "maps" and they are popular by virtue of being simple to use and manipulate. A long way from "Antchester", maps can now be measured in megabytes or Gigabytes (around 20GB is needed for the whole earth at 30 meter resolution). Each value in the map represents the height of the terrain at that location.
These kinds of maps are known as heightmaps. However, any information that can be represented in the grid pattern can use maps. Additional maps can be used by 3D engines to tell it how to mix many textures together; this is a common terrain painting technique known as "splatting". Splats describe the amount of blending between texture layers. Another kind of map might be used for lighting, adding light, or shadows to an area of the map. We also find in some engines something called visibility maps which hide parts of the terrain; for example we might want to add holes or caves into a landscape. Coverage maps might be used to represent objects such as grasses, different vegetation layers might have some kind of map the engine uses to draw 3D objects onto the terrain surface. GROME allows us to create and edit all of these kinds of maps and export them, with a little bit of manipulation we can port this information into most game engines. Whatever the technique used by an engine to paint the terrain, height-maps are fairly universal in how they are used to describe topography.
This map represents a 100 square kilometer area of north-west Afghanistan used in a flight simulation.
GROME like many other terrain editing tools uses heightmaps to transport terrain information. Typically importing the heightmap as a gray scale image using common file formats such as TIFF, PNG, or BMP. When it's time to export the terrain project you have similar options to save.
This commonality is the basis of using GROME as a tool for many different engines. There's nothing to stop you from making changes to an exported heightmap using image editing software. The GROME plugin system and SDK permit you to make your own custom exporter for any unsupported formats. So long as we can deal with the material and texture format requirements for our host 3D engine we can integrate GROME into the art pipeline. Well, easier said than done, quite often this is the tricky part which we'll get to at the end of this book.
Using textures for heightmap information does have limitations. The largest "safe" size for a texture is considered 4096 x 4096 although some of the older 3D cards would have problems with anything higher than 2048 x 2048. Also, host 3D engines often require texture dimensions to be a power of 2. A table of recommended dimensions for images follow:
64 x 64
128 x 128
256 x 256
512 x 512
1024 x 1024
2048 x 2048
4096 x 4096
512 x 512 provides efficient trade-off between resolution and performance and is the default value for GROME operations.
If you're familiar with this already then great, you might see questions posted on forums about texture corruption or materials not looking correct. Sometimes these problems are the result of not conforming to this arrangement. Also, you'll see these numbers crop up a few times in GROME's drop-down property boxes. To avoid any potential problems it is wise to ensure any textures you use in your projects conform to these specifications. One exception is Unreal Development Kit (UDK) in which you'll see numbers such as 257 x 257 used, we'll discuss this in Chapter 7, Exporting to Unity, UDK, and Ogre 3D.
If you have a huge amount of terrain data that you need to import for a project you can use the texture formats mentioned earlier but I recommend using RAW formats if possible. If your project is based on real-world topography then importing DTED or GeoTIFF data will extract geographical information such as latitude, longitude, and number of arc seconds represented by the terrain.
Huge landscapes may require a lot of memory, potentially more than a 3D card can handle. In game consoles memory is a scarce resource, on mobile devices transferring the app and storing is a factor. Even on a cutting edge PC large datasets will eat into that onboard memory especially when we get down to designing and building them using high-resolution data. Requesting actions that eat up your system memory may cause the application to fail. We can use GROME to create vast worlds without worrying too much about memory. This is done by taking advantage of how GROME manages data through a process of splitting terrain into "zones" and swapping it out to disk. This swapping is similar to how operating systems move memory to disk and reload it on demand. By default whenever you import large DTED files GROME will break the region into multiple zones and hide them. Someone new to GROME might be confused by a lengthy file import operation only to be presented with a seemingly empty project space.
When creating terrain for engines such as Unity, UDK, Ogre3D, and others you should keep in mind their own technical limitations of what they can reasonably import.
Most of these engines are built for small scale scenes. While GROME doesn't impose any specific unit of measure on your designs, one unit equals one meter is a good rule of thumb. Many third-party models are made to this scale. However it's up to the artist to pick a unit of scale and importantly, be consistent.
Keep in mind many 3D engines are limited by two factors:
Floating point math precision
Z-buffer (depth buffer) precision
As a general rule anything larger than 20,000 units away from the world origin in any direction is going to exhibit precision errors. This manifests as vertex jitter whenever vertices are rotated and transformed by large values. The effects are not something you can easily work around. Changing the scale of the object shifts the error to another decimal point. Normally in engines that specialize in rendering large worlds they either use a camera-relative rendering or some kind of paging system. Unity and UDK are not inherently capable of camera-relative rendering but a method of paging is possible to employ. There are techniques available such as a treadmill style terrain system but these are beyond the scope of this book to demonstrate.
The other issue associated with large scene rendering is z-fighting. The depth buffer is a normally invisible part of a scene used to determine what part is hidden by another, depth-testing. Whenever a pixel is written to a scene buffer the z component is saved in the depth buffer. Typically this buffer has 16 bits of precision, meaning you have a linear depth of 0 to 65,536. This depth value is based on the 3D camera's view range (the difference between the camera near and far distance). Z-fighting occurs when objects appear to be co-planer polygons written into the z-buffer with similar depth values causing them to "fight" for visibility. This flickering is an indicator that the scene and camera settings need to be rethought. Often the easy fix is to increase the z-buffer precision by increasing the camera's near distance. The downside is that this can clip very near objects.
GROME will let you create such large worlds. Its own Graphite engine handles them well. Most 3D engines are designed for smaller first and third-person games which will have a practical limit of around 10 to 25 square kilometers (1 meter = 1 unit). GROME can mix levels of detail quite easily, different regions of the terrain have their own mesh density. If for example you have a map on an island, you will want lots of detail for the land and less in the sea region. However, game engines such as Unity, UDK, and Ogre3 Dare are not easily adapted to deal with such variability in the terrain mesh since they are optimized to render a large triangular grid of uniform size. Instead, we use techniques to fake extra detail and bake it into our terrain textures, dramatically reducing the triangle count in the process. Using a combination of Normal Maps and Mesh Layers in GROME we can create the illusion of more detail than there is at a distance.
A Normal is a unit vector (a vector with a total length of one) perpendicular to a surface. When a texture is used as a Normal map, the red, green, and blue channels represent the vector (x,y,z). These are used to generate the illusion of more detail by creating a bumpy looking surface. Also known as bump-maps. Normal map generation is covered in Chapter 4, Textures and Lighting.
For purposes of demonstration we're going to be working on a hypothetical game as part of a team. We have a design document and the art lead has tasked us with creating the exterior map for the "Volcano Lair" of the evil Doctor Yes and his sidekick, Professor Maybe. Our game features the propitious handsome hero "Guy Goodwin" on a mission to thwart the evil plans of an organization called "DEAD Certainty". The team lead is really enthused and promises it will be great, not really.
Our task is to turn concept and sketches into a detailed virtual environment using GROME as part of the toolset so we can export it for different game engines.
Already we can take away some information about what we can build. The characters sound over the top, the tone of this game is clearly humored, larger than life. It's a first-person game meaning ground detail will need to be pretty high in player accessible areas. This part of the game takes place on an island which has the following key locations as listed in our brief:
A volcano (with interior access via a bunker)
Professor Maybe's villa or laboratory
A power station
River with a boat event
Airfield (with getaway plane)
Creating a rough sketch of our map, we get a feel for relative positions and scale of the terrain we need. We keep main story locations clustered around the origin of the world to reduce precision problems on the destination platforms.
What we can take away from such a sketch is the rough outline of major features, in this case the shape of the island. We can import this at a later stage and use it as a mask in GROME when creating the heightmap.
Generating terrain can be done procedurally which is what we're going to do for our game example. Then we'll use our sketch to create masks we can import into GROME. These work just like masks in programs like Photoshop and GIMP.
If we need to go back and change the position of key locations (for example; the project lead might want to move two places closer together to speed up story progression), we can do this quite easily in GROME using masks or a clone brush tool which we will explore later.
Depending on your host operating system you should launch either the 32-bit or 64-bit Version. If you have more than 4 GB of memory installed and a 64-bit edition of the Windows operating system then you should take advantage of running GROME (64 bit), every bit of extra memory helps (no pun intended). If you need to work with very detailed scenes you should opt for this work environment as it will pay off in terms of swap times. These examples are created using the 32-bit edition which look identical. Let's get started.
Launch GROME 3.1, when greeted with the quick start dialog click on the Create a new project button.
You'll see a New Scene dialog like the following screenshot. Since we want to get started creating our volcano lair we'll call our project
volcano_lair. You'll notice a number of icons grouped under Project Type, the type determines what kind of features you can add to the project. For now we'll just select Complete Scene which is everything.
Before you start to panic, the imposing interface buttons bordering the work area are common editor functions we'll be accessing from other parts of the interface. By default the GROME interface is arranged with the tablet user in mind. If your default view is split into four viewports you can change it to a single viewport through the OPTIONS menu. Select Preferences and set the viewports in the dialog as given in the following screenshot. Be sure to click on the Apply to All button to assign these settings to the current viewports.
In this chapter we looked at heightmaps and how they allow us to import and export to other programs and engines. We touched upon world sizes and limitations commonly found in 3D engines. We then examined a brief for a hypothetical game, sketched out a map in preparation before finally creating a new GROME project file. In the next chapter, we'll look at how the interface is arranged and work through the toolset as we get to grips with the interface.
In the next chapter, we're going to look at the workspace and the all-important layer stack.