World
Wide Guide | Knowledge Bank
| Kukushkin's Notebook |
Design Fundamentals
This section discusses some aspects of choosing colors
for non-textured primitives. The basics for selecting colors are very well
described in the documentation for scenery compilers. Here, only some interesting
details are pointed out.
SCASM requires two separate byte values for a color value instead of a single 16-bit word. The first byte here is the color number and the second byte is the palette selector. Both bytes should be specified as hex numbers.
Non-textured primitives are drawn using a specific color, which has to be selected prior to drawing using a separate instruction. SDL has several instructions for selecting colors for different kinds of primitives. Colors for lines/dots, solid polygons and shaded polygons must be selected using different instructions. These 3 kinds of primitives interpret colors in slightly different ways, and some of them do not accept some color specifications.
Instructions for selecting colors are LineColor(), SurfaceColor() and ShadedColor().
Most colors from the palette F0 change their brightness according to the position of sun and the cloud cover when applied to polygon drawing instructions that supply visibility vectors. However, colors of primitives that do not have visibility vectors, like lines, dots, surfaces drawn with StartSurface()..EndSurface(), roads, etc. normally do not change their intensity this way.
By default, they have the highest intensity possible for the selected color. Using the Brightness() [FSASM:Intensity] instruction, it is possible to make them behave like colors of horizontal polygons. The percentage in Brightness() determines the sensitivity to the direct sunlight. A surface drawn with 100% behaves exactly like a horizontal polygon, while 0% means no effect from the direct sunlight (always the lowest intensity possible).
Colors 00 F0 - 0D F0 react to both diffused and direct sunlight. The color 0E F0 is used for rivers and only reacts to the diffused light. Colors 0F F0 - 15 F0 never change their intensity and remain lit at night. The color 16 F0 reacts to direct sunlight but remains lit at night.
Colors with bigger numbers react to both diffused and direct sunlight, but they often do not produce correct shaded polygons and, starting from even bigger numbers, randomly change their RGB value depending from the position of sun. Some of these colors can be used, but extreme care (and testing) should be taken. Primitives drawn using the palette 68h (transparent) can sometimes be displayed incorrectly when the map view is visible at night. However, FS5 heavily uses this palette for displaying shadows, which suffer from the same problem. In my opinion, additional problems caused by polygons drawn using this palette can be neglected because of that and the palette can be used without any doubts.
Surfaces drawn using palettes 68h and 69h do not change their intensity according to the position of the sun. However, such change is often desirable, especially with the palette 68h which has no equivalent colors in F0.
The response to direct sunlight can be simulated with the help of the TexPolyShading() instruction. While it is supposed to be used mainly for shading of TexPoly()s, this instruction itself does not require a texture to be loaded and thus can also be used for non-textured surfaces. TexPolyShading() takes a vector as parameter and calculates the intensity increase by the direct sunlight. Then, it sets the dx parameter of the texture depending from the result. The code that selects a color can later read this parameter from the variable 1ECC and choose the actual palette color depending from the value of dx. A typical code should look like this:
TexPolyShading( ... ... ... ) ; Calculate dx
SurfaceColor( .. .. ) ; The brightest palette entry
IfVarRange( :Done 1ecc 32 256 )
... ; Further SurfaceColor/IfVarRange pairs
SurfaceColor( .. .. )
IfVarRange( :Done 1ecc 224 256 )
SurfaceColor( .. .. ) ; The darkest palette entry.
:Done
In the worst case, the SurfaceColor() instruction gets executed 8 times. However, it is one of the fastest instructions, so it was much more important to keep the code as short as possible. Here, it occupies 110 bytes, as compared to 4 in case of a usual SurfaceColor( .. F0 ). This approach is thus only justified for cases that cannot be resolved using the palette F0.
TexPolyShading() adjusts the dx parameter of bitmaps only by 32-pixel increments. Because of that, only 8 possibilities for the intensity exist. Some colors have more palette entries than 8. For this reason, the intensity for these colors changes in finer steps when using the palette F0.
Because polygons drawn with transparent colors from the palette 68 do not completely cover the scene behind them, they can resurrect visibility problems within objects that are normally successfully resolved by FS5. For example, inner sides of a convex polyhedron are normally never visible and thus not drawn. But, if it gets a transparent side, its inner sides become visible through this side and must be drawn too. Otherwise, the scene behind would be visible through the transparent side, even if the opposite side of the polyhedron is not supposed to be transparent.
Shaded polygons are displayed using the ShadedPoly() instructions. It requires "vectored" points defined with the VecPoints() instructions, unlike most other drawing instructions where Points() is sufficient. Each "vectored" point is defined by its coordinates and a vector defining the tangential plane to the (to-be)curved surface passing through this point.
Only colors from the palette F0, and only a few of them can be used for shaded polygons. Other colors produce random color effects than can only be used for putting holograms on offices of software companies.
The number of colors available in FS5 is limited, especially at night. Using dithering, it is possible to simulate more colors for polygons than actually present in the palette. This can be done by first drawing a polygon with a color from palettes 69 or F0. Then, the same polygon is drawn again using a transparent color from the palette 68. Half of the pixels from the first polygon remains visible, thus the polygon will appear in a color that is a combination of two. For example, different versions of non-fading yellow can be obtained like this:
SurfaceColor( 79 69 ) ; Bright yellow
Poly( ... )
SurfaceColor( .. 68 ) ; 7A 68 - 7F 68 are white colors of
different
Poly( ... ) ; intensity.