Drawing lots of textures with OpenGL can be slow, especially if we do it in several passes, or by rebinding textures a lot. That is why we need to pack textures into texture pages, and use several texture units with multitexturing to draw several texture at once. This presents some problems, as Freeciv uses plenty of layers of information, and graphics card today do not have very many texture units. Basically, the number of passes we need to do (redrawing everything) is texture pages / texture units. So the fewer texture pages we need, the better. We can assume that everyone today have 4 texture units on their graphics cards. But Freeciv has many more layers, and we want to finish drawing the terrain with one pass. We do this by rendering many of the possible combinations beforehand and storing them in the texture pages. However, texture pages are not infinitely large, either, we can assume a maximum of 2048x2048 for modern cards, less for older ones, so we need to keep the number of combinations down.
We have lots of basic tiles, which we'll call pies, because they taste so good and get cut up into neat triangular slices. The slices again are composed of layers of good tasting textures, where each layer corresponds to one texture page that is applied on the slice.
For terrain, the first texture page will contain basic terrain slices. No combinations are created here, making terrain types easily modifiable.
The second texture page contains irrigation, farmland and rivers. Since you cannot have irrigation and farmland at the same time, and we have five basic river directions (including origin), the number of combinations here is 3 * 5 + 2 = 17.
The third texture page contains road, rail and fortress wall. Since you cannot have road and rail at the same time, and we have 6 basic directions for road and rail (no origin, but each direction has to have the option of going in toward pie center for cities), the number of combinations here is 6 * 2 * 2 = 24.
Cities are done in a separate, second pass, added on pies as rectangular textures. The hut, airbase, fallout and pollution specials cannot be combined with cities, and would very much like occupy the larger center of the pie, and are therefore added in this pass. Mines are added in this pass, too, because although you can build both mine and city on the same tile in Freeciv, you only ever see the city (this combination should be considered a misfeature, but that is another matter).
Units and their attributes are done in a third, separate pass, also as rectangular textures.
- Pie: The basic tile unit, which is either a hexagon or a pentagon.
- Slice: A triangular piece of a pie. A pie is composed of 5 (pentagon) or 6 (hexagon) slices.
- Layer: A triangular texture that is applied on top of a slice. Often a slice can have 3 layers.
- Texture unit: Each texture unit on a graphics card can draw one texture simultaneously.
- Texture page: A texture uploaded through OpenGL to the graphics card containing many separate, tightly packed slices.
- Multitexturing: See this presentation
Source Code Edit
Source Code is available for testing from GNA SVN: http://svn.gna.org/viewcvs/buckyball/trunk/
The program currently features three major components (for definitions of the various terms see above):
- fgl -- OpenGL core. Error reporting, the main loop, window mgmt, PNG loader, texture manager backend.
- triren -- Triangle renderer. This component is supposed to render the terrain of the earth when it's done. It basically puts triangles to the screen, doing the appropriate optimizations so this happens fast. Vertex buffers are implemented, VBOs may come in the future. A hacky texture manager is there. Visibility management is now out of scope for the rendering engine and will be handled at a higher level. Support for disabling subsets of the triangles is there.
- camera -- Camera management code has been split out in a separate module. It does proper animations of the world when clicking and dragging it; fov-based zoom is there; seems to be quite stable. Code for the plane maps is missing, and we'll probably need some frustum/sphere or frustum/box intersection code. Subtile picking code is lacking.
- test_util -- A tiny wrapper around everything which provides a basic user interface for development work.
- world -- Currently a vague mix of testing code and the world generators. When it's done, it is supposed to do the following
- be able to provide the world mesh (i.e. coordinates of the tiles), for at least two topologies: sphere (buckyball/hexball) and plane (hexplane)[For generating beautifully easy spheres made of hexagons and pentagons, I suggest starting with an icosahedron and then subdividing using Leif Kobbelt's root3 subdivision sheme, http://citeseer.ist.psu.edu/viewdoc/download;jsessionid=CB23D9C583913A53C423033608576A7F?doi=10.1.1.43.1955&rep=rep1&type=pdf]
- be able generate a map (i.e. playable continents and such) on that mesh, possibly using a PNG file as input
- provide abstractions to both the Freeciv backend code (as in game rules, AI, network, ...) and triren. To Freeciv, it should present a set of tiles called /pies/ and connections (possible moves) among those. To triren, it presents a list of triangles called /slices/, complete with numerical values for vertices, normal vectors and texture numbers for each layer, so that triren has all the information required to render them properly. A huge part of "world" will be glue code translating between those components. It needs to break down the game /pies/ down into 5 or 6 /slices/. Then it will have to choose textures which represent the game content on the screen, and tile properly.
The creation of textures faces one serious problem: The map consists of hexagons and pentagons. Probably the only way to simplify this is to create textures for slices instead of for pies, which can then be combined to form either hexagonal or pentagonal pies.
The slice textures should be oriented along a few fixed points: the center point of the pie, which is a corner of the slice, the other two corners of the slice, and the middle points of the slice's sides.
Perhaps the different layers can follow different rules:
- the lowest layer, used to create the terrain, could perhaps consist of overlapping circular textures. each circular texture is centered on a pie center and extends to the pie corners, slightly overlapping the neighboring pies along the edges of the pie. the part that extends into the neighboring pie fades outward, creating soft edges.
- the second layer, consisting of terrain modifiers (farmland, irrigation) could also consist of circular textures spanning 2/3 of the pie diameter
- the third layer, consisting of road, rail, fortress wall and rivers could then be slice-based. as long as the angle at which road (and rail) touch slice borders is 90 degrees, there is no distortion or sudden angulation
- rivers flow between pies, curving into this or that tile, based on the direction they come from and flow to. coding this should be relatively easy.
- the last layer is for cities and mines, added as rectangular textures
Texturing - State of the renderer Edit
The rendering engine currently can do two layers of triangular textures which are loaded from PNG files (v9textures). (See shiny new screenshot.) Upgrade to 4 layers poses no further problems, however the v9textures file format is far from optimal. The edges of our triangles remain untextured because of missing overlap space. (In short, the textures are too small.) During the planning of texturing this should be considered, and solid hexagonal/pentagonal/round textures should be used in the future.