Storms¶
A sandstorm or snowstorm stands on the ground inside an upright cylinder. The storm is haze that fills the cylinder and grains or flakes that blow through it, and the shaders make both, so no particle system is involved. The haze follows the terrain, thins out towards the storm's edge and top, and bunches into gusts that drift with the wind. Units and buildings inside it fade with their depth in the haze. Needs the Direct3D 9 build and a shader model 3 card that reads textures in the vertex shader. Older cards draw no storm.
A storm comes from one of two places:
- A
Stormblock in anFXListstarts a storm where the effect plays. It stays there for itsDuration. - A
W3DStormDrawmodule on an object keeps a storm around the object. The storm follows the object and dies down once the object is gone.
Both take these keys. A key left out takes the value GameData.ini holds for the storm's Type.
There each key carries the type's name in front, so HazeDensity is SandStormHazeDensity for sand
and SnowStormHazeDensity for snow, and the percent keys take a plain number such as
SandStormEdgeFade = 35. The two columns list what GameData.ini starts with. A storm reads
GameData.ini every frame, so in a cheat build a saved change shows on a running storm:
| Key | SAND |
SNOW |
Meaning |
|---|---|---|---|
Type |
SAND or SNOW. Default SAND. |
||
Radius |
300 | 300 | World units from the storm's middle to its edge. |
Height |
120 | 150 | World units the storm stands above the ground. |
EdgeFade |
35% | 35% | Share of the radius over which the storm thins out to nothing. |
FadeTime |
3000 | 3000 | Milliseconds the storm takes to build up, and again to die down. |
HazeColor |
R:194 G:158 B:107 | R:217 G:224 B:235 | Colour of the haze, before the map's lighting. |
HazeDensity |
0.8 | 0.35 | How much 100 world units of haze hide. 0 draws no haze. |
HazeMaxOpacity |
80% | 55% | The most the haze may hide, however deep. |
HazeNoiseSize |
300 | 350 | World units across one tile of gust noise. Smaller is finer. |
Gusts |
70% | 50% | How unevenly the haze and grains bunch up. 0% is an even fog. |
WindAngle |
0 | 0 | Direction the wind blows towards, in degrees. 0 is east, 90 is north. |
WindSpeed |
140 | 45 | World units a second. |
FallSpeed |
4 | 30 | World units a second the grains sink. |
Turbulence |
5 | 9 | World units the grains swirl off their path. |
GrainColor |
R:219 G:189 B:140 | R:255 G:255 B:255 | Colour of the grains, before the map's lighting. |
GrainCount |
6000 | 5000 | Grains in view at once, up to 40000. 0 draws no grains. |
GrainSize |
1.0 | 1.8 | World units across a grain. |
GrainStreak |
0.06 | 0.02 | Seconds of travel a grain smears along. 0 draws round grains. |
GrainOpacity |
60% | 85% |
A Storm block also takes:
DurationHow long the storm lasts, in milliseconds, with both fades inside it.
FXList FX_SandstormStrike
Storm
Type = SAND
Radius = 350
Duration = 30000
WindAngle = 45
HazeDensity = 1.0
End
End
Object SnowstormEmitter
Draw = W3DStormDraw ModuleTag_Storm
Type = SNOW
Radius = 500
GrainCount = 12000
End
...
End
Notes
- Storms are visual only. They change no vision, damage or speed. They are not saved, so a loaded
game has lost its
FXListstorms, whileW3DStormDrawstorms build up again. - Grains fill a square 640 world units wide around the middle of the view, so
GrainCountsets how thick they look on screen whatever the storm's size. - Sand keeps close to the ground and snow fills the storm's height evenly.
- The haze stops at whatever the scene's depth holds, so it thins in front of tall buildings and hills. Without a readable depth buffer it stops at the terrain alone and draws over objects.
- Storms draw after particles, so effects inside a storm are hazed like the ground under them.
- A
W3DStormDrawstorm dies down while its object is under the shroud. AnFXListstorm ignores the shroud. - At most 8 storms show at once, and further ones do not start.
- Launch with
CONTRA_STORMSHADER=0to turn storms off.
Headlights¶
At night a model shows every mesh whose name holds HEADLIGHT, such as HEADLIGHT01. With this
feature those meshes stay hidden and a shader draws each headlight in their place, as two parts:
- The beam is a soft cone in the air. It dims along its length and towards its edge, and fades out where it meets the ground or a model.
- The pool is the light the lamp throws. It brightens the terrain, models and buildings inside the lamp's cone, by their own colours.
Each headlight takes its place and size from its mesh. The beam runs along the side of the mesh
that is long and leads away from the model's middle. The narrow end of a cone is the lamp, and a
shape with no narrow end has its lamp at the end nearer the model's middle. In both cases
the cone's width gives the beam's width at the far end. A mesh may hold several cones. Each cone
that stands apart draws as a lamp of its own, and cones that lie within half their radius of each
other, such as twin lamps set side by side, draw as one. The models need no INI change, and
headlights still show only at night. An opaque HEADLIGHT mesh, which blends nothing, is a lamp body
rather than light, so it keeps its own look and throws no beam. With RotrHack = Yes, an additive
HEADLIGHT mesh does the same. Rise of the Reds draws lit windows and glows that way. HeadlightPerConeAim = Yes instead gives each cone its own direction, for meshes whose lamps
aim different ways, such as a floodlight rig on a roof. The lamp is the middle of a cone's narrow end, and cones
that aim the same way with lamps within one radius of each other draw as one. A mesh with a lamp that
has no narrow end keeps the rule above.
Needs the Direct3D 9 build and a shader model 3 card. Elsewhere, and with HeadlightShader = No,
the models show their headlight meshes as before. The pool has no shadows, so a lamp also lights
ground that a hill or building hides from it.
The keys live in GameData.ini. All but HeadlightShader, HeadlightShaderForbiddenKindOf, HeadlightPerConeAim and RotrHack reload in cheat builds:
| Key | Default | Meaning |
|---|---|---|
HeadlightShader |
Yes |
No keeps the headlight meshes. Read at launch. |
HeadlightShaderForbiddenKindOf |
none | Objects of any of these kinds keep their headlight meshes, such as STRUCTURE for buildings that use HEADLIGHT meshes as lit windows. Read at launch. GameData.ini only. |
HeadlightColor |
R:255 G:242 B:209 |
Colour of the beam and the pool. |
HeadlightBeamIntensity |
0.35 | Brightness of the beam. 0 draws no beam. |
HeadlightBeamLength |
1.0 | Beam length, in mesh lengths. |
HeadlightBeamWidth |
1.0 | Beam width at the far end, in mesh widths. |
HeadlightBeamFalloff |
1.5 | How fast the beam dims along its length. 1 dims evenly, more dims sooner. |
HeadlightBeamSoftness |
8.0 | World units over which the beam fades into what it touches. |
HeadlightPoolIntensity |
0.8 | Brightness of the pool. 0 draws no pool. |
HeadlightPoolRange |
2.5 | How far the light reaches, in mesh lengths. |
HeadlightPoolAngle |
26 | Degrees from the middle of the light to its edge. |
HeadlightPoolPitch |
11.5 | Degrees the light tilts down from the mesh, so a level lamp reaches the ground. |
HeadlightPoolFalloff |
1.5 | How fast the pool dims with distance. |
HeadlightPoolClampBrightness |
Yes |
Where pools overlap, the ground takes the brightest one alone, so lamps side by side do not burn it white. No stacks them. GameData.ini only. |
HeadlightPerConeAim |
No |
Yes aims each cone of a HEADLIGHT mesh its own way, as above. Read at launch. GameData.ini only. |
RotrHack |
No |
Yes keeps additive HEADLIGHT meshes, such as Rise of the Reds' lit windows, as they are, with no beam. Read at launch. GameData.ini only. |
A model can override any of these for itself. The same keys go in its W3DModelDraw module, or in
a module built on it such as W3DTankDraw, beside OkToChangeModelColor. A key left out takes the
GameData.ini value, so a module names only what differs. HeadlightShader = No there keeps that
model's headlight meshes while the rest of the game uses the shader. It cannot turn the shader on
for one model while GameData.ini has it off. A negative HeadlightPoolPitch tilts the light up.
Module keys are read at launch.
Draw = W3DTruckDraw ModuleTag_01
HeadlightColor = R:190 G:215 B:255
HeadlightPoolIntensity = 1.4
HeadlightPoolAngle = 34
DefaultConditionState
Model = AVOmega
End
End
Planar mirrors¶
Chosen meshes of a model act as level mirrors. They reflect the scene above them: units, buildings, trees and the sky. Suited to polished floors, wet plazas, metal decks, puddles, pools and glass.
- An opaque mesh keeps its texture, lighting and shadows. The reflection blends over it.
- A translucent mesh shows what lies under it, bent by its normal map, below its own texture. The reflection lies over both.
- The reflection's share is
PlanarMirrorReflectivityseen from above and rises towards all of it at a grazing angle. - A
<texture>_nrm.ddsnormal map beside the mesh's texture ripples the reflection and what shows through. Without one the mirror is flat.
The game mirrors the scene in at most two heights each frame, those of the mirrors nearest the middle of the view. Mirrors within half a unit of each other in height share one. A mirror at any other height reflects the sky alone. The mirror's height is the top of the mesh, so the mesh should be flat and level. A mirror that turns up on screen shows the sky for its first frame.
Each height costs one more draw of the scene at half resolution, cut down to the mirrors' part of the screen. Water reflections are separate and cost their own draw.
Needs the Direct3D 9 build and a pixel shader 2.0a card. Elsewhere, with PlanarMirrorShader = No,
and with water reflections turned off in the options (WaterReflections = No in Options.ini), the
meshes draw as before.
Mark the model in its W3DModelDraw module, or a module built on it, beside OkToChangeModelColor:
| Key | Default | Meaning |
|---|---|---|
PlanarMirror |
No |
Yes makes the meshes below mirrors. It wins over FlameShader, ElectricShader and CryoShader on those meshes. |
PlanarMirrorMeshes |
every mesh | Mesh names, without the model's name, such as FLOOR01 POOL. Case does not matter. |
PlanarMirrorOverrideTexture |
No |
Yes draws the meshes as clear glass in place of their texture, whatever the mesh. They show what lies under them, bent by the normal map, with the reflection over it. A mesh drawn with alpha keeps its texture's alpha as its outline. |
The look keys live in GameData.ini. All but PlanarMirrorShader reload in cheat builds:
| Key | Default | Meaning |
|---|---|---|
PlanarMirrorShader |
Yes |
No draws every mirror mesh plain. Read at launch. |
PlanarMirrorReflectivity |
0.35 | Share of the reflection seen from straight above, 0 to 1. |
PlanarMirrorTint |
R:255 G:255 B:255 |
Multiplies the reflection. Darker for tinted glass or dull metal. |
PlanarMirrorDistortion |
0.01 | How far the normal map bends the reflection and what shows through, in screen widths. |
PlanarMirrorFrost |
0 | 0 clear to 1 frosted. Blurs the reflection, and blurs and clouds what shows through glass and translucent mirrors. |
The same four look keys in the model's module override GameData.ini for that model. Module keys
are read at launch.
Glass draws after the opaque scene, from one copy of the screen taken at the first glass or translucent mirror. An object that draws later and stands under the glass does not show through it. A glass mesh takes no shadows or highlights on itself, though it still casts its shadow.
Draw = W3DModelDraw ModuleTag_01
PlanarMirror = Yes
PlanarMirrorMeshes = FLOOR POOL
PlanarMirrorReflectivity = 0.6
DefaultConditionState
Model = CBPlaza
End
End
HQ sky¶
Cloud shadows drift softly over the ground, change shape as they go and never repeat, in place of one tiled cloud texture sliding across the map. Each frame a shader draws the clouds into a map over the ground the camera sees, and terrain, roads, bridges, units and buildings darken from it. Two cloud shapes at unrelated sizes and angles add up to each cloud, a slow warp bends them, and a finer layer frays their edges. Each layer drifts at its own speed, so clouds form and fade instead of sliding as one sheet. Needs the Direct3D 9 build and Cloud shadows on.
HQSky = YesNo brings back the tiled cloud texture. AlsoHQ skyon the Shaders page, greyed out while Cloud shadows is off. NeedsCheckHQSkyinOptionsMenu.wndfor the menu control.
Tuned in the mod's GameData.ini:
SkyCloudSize = 600World units across a typical cloud.SkyCloudCoverage = 0.45Share of the ground in shadow. 0 is a clear sky, 1 overcast.SkyCloudSoftness = 0.25How wide the fade at a cloud's edge is. Low gives crisp edges.SkyCloudShadowStrength = 0.35How dark a thick cloud's shadow is. 0 for none. The default matches the old clouds' darkest.SkyCloudShadowTint = R:235 G:242 B:255The shadow's hue. White gives neutral grey.SkyCloudWindSpeed = 11World units a second the clouds drift. 0 holds them still.SkyCloudWindAngle = 56Degrees the clouds drift towards, 0 along the map's x. The default matches the old clouds.SkyCloudChurn = 0.3How fast shapes change as they drift. 0 slides them as one sheet.SkyCloudBillow = 0.5How far shapes bulge and curl. High values twist them into streaks.SkyCloudDetail = 0.4Ragged detail at the edges. 0 gives smooth blobs.
Notes
- Night keeps the clouds off, as before.
- Trees and the water's reflected sky keep their old look.
CONTRA_SKYCLOUDS=0keeps the tiled texture, to rule the HQ sky out of a rendering fault.
Colour grading¶
A colour table gives a map its look: warm for a desert, cold for snow, muted for a city. After each view's 3D scene is drawn, a shader reads every pixel's colour and replaces it with the colour the table holds for it. The interface, the cursor and the health bars draw afterwards and keep their colours. The grade changes no lighting. It recolours the lit picture, so it applies alike to terrain, units, effects and team colours. Needs the Direct3D 9 build and pixel shader 2.0a.
Set in the mod's GameData.ini for every map, or in the GameData block of a map's map.ini for
that map alone:
The table:
ColorLut = NoneThe table's file name, such aslut_desert.tga.Noneuses no table.ColorLutStrength = 1How much of the table's result is taken. 0 leaves the scene as it is.ColorLutChroma = 1How much of the table's hue is taken. 0 takes only its brightness.ColorLutLuma = 1How much of the table's brightness is taken. 0 takes only its hues, so units stay as bright or dark as they were.
Colour, before the table:
ColorLutBrightness = 1Multiplies the scene.ColorLutContrast = 1Spreads the scene around mid grey. 0 is flat grey.ColorLutSaturation = 1Colourfulness. 0 is black and white.ColorLutTint = R:255 G:255 B:255Colour the scene is multiplied by.ColorLutVibrance = 0Saturates dull colours more than vivid ones, so terrain gains colour and team colours hold. -1 to 1, and negative mutes them.ColorLutTechnicolor = 0Strength of the two-strip Technicolor film look, 0 to 1.
Levels, after the table:
ColorLutBlackPoint = 0Level that becomes black. Raise it to crush the shadows.ColorLutWhitePoint = 1Level that becomes white. Lower it to brighten the highlights.ColorLutGamma = 1Midtone brightness. Above 1 brightens and below 1 darkens.ColorLutOutputBlack = 0What black comes out as. Raise it for the lifted, matte look. The shroud lifts with it.ColorLutOutputWhite = 1What white comes out as. Lower it to dim the highlights.
Finish, last:
ColorLutVignette = 0How dark the view gets towards its edges, 0 to 1.ColorLutVignetteRadius = 2Distance from the view's centre, in half its height, where the vignette reaches full strength. 2 reaches the corners of a 16:9 view.ColorLutGrain = 0Film grain over the scene, new every frame. 0.1 to 0.2 is a light grain.ColorLutDither = 1Noise that breaks up the banding a grade leaves in smooth gradients, in 8 bit colour steps. 0 is off.
Every key but ColorLutStrength, ColorLutChroma and ColorLutLuma works without a table, so a map
can take a small correction alone. The dither draws only while some other key grades the scene.
A map.ini that grades one map:
GameData
ColorLut = lut_snow.tga
ColorLutStrength = 0.8
ColorLutSaturation = 0.9
End
Preset tables, in Art\Textures:
| File | Map style | Look |
|---|---|---|
lut_desert.tga |
Desert | Warm midtones and highlights over cool shadows. |
lut_snow.tga |
Snow | Blue shadows, clean whites and muted colour. |
lut_naval.tga |
Naval | Deep blue-teal shadows and midtones under neutral highlights. |
lut_island.tga |
Island | Vivid colour, lush greens and warm sunlight. |
lut_urban.tga |
Urban | Muted colour with hard contrast. |
lut_future.tga |
Future | Violet shadows, cyan highlights and hard contrast. |
lut_neutral.tga |
None | Changes nothing. The starting point for a new table. |
Seventeen more looks come from the MultiLUT atlas of OtisFX, a ReShade shader pack by Frans Bouma under the MIT licence:
| File | Look |
|---|---|
lut_otis_hollywood.tga |
Teal shadows and warm highlights, as in action films. |
lut_otis_blue.tga |
Strong cold blue cast. |
lut_otis_coollight.tga |
Slight cool cast with soft contrast. |
lut_otis_flatgreen.tga |
Flat and green-grey, a military drab. |
lut_otis_redliftmatte.tga |
Lifted, reddish shadows with a matte finish. |
lut_otis_crossprocess.tga |
Cross-processed film: yellow highlights over blue shadows. |
lut_otis_azurered.tga |
Two tones, warm red over azure. |
lut_otis_vogue.tga |
Pale and clean, with cool shadows. |
lut_otis_sepia.tga |
Brown monochrome, for old footage. |
lut_otis_bw.tga, lut_otis_bwcontrast.tga |
Black and white, at medium and high contrast. |
lut_otis_color1.tga, color2, color5 to color8 |
Six mild colour casts, warm to cool. |
A ReShade lut.png of 1024 by 32 has the same layout, so it works once saved as a TGA.
A table is a 24 or 32 bit TGA strip of N slices, N*N wide and N tall, with N up to 64. The presets
are 1024 by 32. Red runs across a slice, green down it and blue from slice to slice. To make one,
paste lut_neutral.tga beside a screenshot in an image editor, grade both together, and save the
strip alone under a new name in Art\Textures. The game reads the file as it is, so the texture
detail setting never shrinks it.
Notes
- The render tuner's Colour grade tab previews each key on a screenshot and saves the keys into
GameData.inior amap.ini.lut_presets.pybeside it writes the preset tables and splits a MultiLUT atlas. - Vibrance and Technicolor follow the SweetFX shaders of the
same names, and the hue and brightness shares follow ReShade's
LUT.fx. - The dither hides steps up to its own size. A strong contrast or gamma can widen the scene's own
8 bit steps past that, and a higher
ColorLutDithertrades them for visible noise. - A map's value holds until the next map loads. A
map.inithat sets noColorLutkey takes theGameData.iniones. - View filters, such as the black and white one, draw first, and the grade applies over them.
- WorldBuilder shows no grade.
- A file that is missing or has the wrong shape draws no table, and a cheat build names it in
d3d9render.txt. - A loose table saved again under the same name shows within half a second, so a table can be graded with the map running.
CONTRA_COLORLUT=0turns the grade off, to rule it out of a rendering fault.
Shader water¶
Lakes, seas and rivers are shaded per pixel, with refraction, reflection, sun glint, foam and
vertex waves. Its options and Water.ini parameters are on Water.