Procedural texturing

From FlightGear wiki
Revision as of 11:38, 3 January 2013 by Thorsten (talk | contribs) (Created page with " (Work in progress) Procedural texturing is a set of techniques where the color of a pixel is not determined by a texture image but fully or partially by evaluating a mathema...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

(Work in progress)

Procedural texturing is a set of techniques where the color of a pixel is not determined by a texture image but fully or partially by evaluating a mathematical function. This article describes why procedural texturing is useful, what it can and can't do and how it is used and configured in Flightgear.

The terrain texturing challenge

The Flightgear terrain is segmented into different landclasses (Urban, Ocean, Glacier, ShrubCover,...) which describe what the terrain at a location is like. In the default texturing scheme, the file materials.xml is used to describe (among other things) what texture sheet is mapped onto a given landclass.

A typical terrain texture sheet has 512x512 pixels and is mapped onto a 2000m x 2000m sized area, which means that each pixel covers a 4m x 4m area in unsloped terrain. For the sake of the argument, assume the texture has a size of 300 kB in compressed form which expands to about 1 MB in the GPU memory after mipmapping.

The optimal distance to view the texture is when every texture pixel corresponds to a pixel on the screen, as then the maximum possible detail of the texture is exploited. Assuming a 60 deg field of view looking straight down onto the texture, that distance is about 2500 m.

If the texture is seem from a much larger distance, it does not large enough to cover the terrain, and hence it is automatically repeated. From about 3 times the optimal distance, this repetition creates a visually rather pronounced pattern which is referred to as tiling:

An example for texture tiling

If the texture is seen from a much smaller distance, a single texture pixel covers multiple screen pixels, which makes the terrain look coarse-grained and unrealistic:

An example for low texture resolution

A third problem occurs because the boundaries of the landclasses are vector data, i.e. they appear as unnaturally sharp division lines between different textures.

Thus, the main challenges for realistic terrain texturing can be summarized as the three areas

  • tiling
  • resolution
  • boundaries

Addressing the challenges

Tiling and resolution are correlated problems, i.e. many solution to one tend to make the other worse. For instance, resolution can easily be dealt with by mapping the texture sheet onto a smaller area, say 500m x 500 m, which gives a pixel size of 1m. However, then tiling becomes apparent from just 1500 m distance, i.e. almost inevitably.

Tiling is also reduced if the variation of contrast inside a texture is reduced, i.e. the texture becomes more 'dull' and the pattern repetition is less obvious:

An example for texture tiling Reduced contrast makes the problem less apparent

However, contrasts within a texture are the best way to distract the eye from the sharp landclass boundaries, so if one uses low contrast textures, the landclass boundary problem gets often worse.

Tiling can also be reduced at the expense of texture detail if a single texture sheet is mapped onto a larger area.

To some degree, all problems lessen with increased texture resolution - using 4096x4096 texture sheets allow 0.5m x 0.5m resolution if mapped onto the same areas - but memory consumption quickly becomes as issue as a single texture sheet of that size uses ~64 MB of graphic memory already.

Photo texturing

The tiling problem can be solved if each 2000m x 2000m area to be textured does not get the same texture sheet. If aerial imagery is used (see Photoscenery) then also the landclass boundary is solved. However, this inevitably creates a resolution problem. To see this, consider the following numbers: On a clear day, the visibility from airliner cruise altitude can easily be 120 km. This means that 45.000 square kilometers of terrain are visible at any given time. Using 2000mx2000m mapped texture sheets as in the example above, unique terrain texturing then needs 11.000 different texture sheets with a size of 1 MB each in graphic memory, or about 11 GB of graphic memory, quite exceeding the capabilities of modern graphic cards. Assuming that about 1 GB of graphic memory is available for terrain textures (clouds, models, the cockpit,... also need memory), the individual pixel must have a size of 12 m x 12 m or larger, which means that photoscenery can either not be used for large visibility, or has a terrible resolution from close-up, or uses a LOD scheme (the above photoscenery would still use 3 GB of harddisk space though).

Photo-texturing has other disadvantages - for instance the photographs are usually taken in a particular season in certain light, so the scene may easily seem unrealistic or wrong in a different season or at a different time of the day. Flightgear texturing also encodes meta-information (where on a texture to place trees or buildings) - such meta-information can not easily be encoded in photoscenery.

Procedural texturing

Procedural texturing is a solution to both the tiling and the resolution problem, and partially also for the boundary problem. A mathematical function, unlike a lookup table (which a texture in essence is) does not end at any boundary, i.e. it can simply be used across the whole scene without ever creating a repetition. Using a suitable noise function to mix various textures, a complete de-tiling effect can be achieved (this is really the same scene):

An example for texture tiling Procedural texturing removes the tiling

A function can also be evaluated at any scale resolution. Unlike a texture which needs to be stored regardless if it is used or not, a function only needs to be evaluated for every screen pixel, i.e. the workload and memory requirement do not grow quadratically with the needed resolution but only linear. This scaling allows to dynamically add details to the scene as one gets closer (this is really the same scene):

An example for low texture resolution Procedural texturing adds details at close range