Creating Attractive Satellite-style Textures

This is the final, fully-textured hillshaded map image.

This post is going to be a short overview of a method for creating a plausibly-realistic and visually attractive satellite-view of a habitable planet.

First, I run tectonics.js until I find an attractive arrangement of continental features. Or… just, you know, continents. In Photoshop or GIMP, I create selections of high elevations and areas that appear to be highlands in the bedrock shader to serve as masks in later manipulations.

In Wilbur, I began by loading a selection of the land areas and slightly feathering it. With this selection, I added some low relief with Filter>Calculate Height Field… set to Hetero Terrain type and Replace operation. Then I loaded and feathered each of the other masks one by one and added additional relief using the add operation of Calculate Height Field. Each time I will change the random seed and increase the sphere radii. Somewhere between the lowest highlands and the higher mountains, I will change the type of the fractal from heteroterrain to Ridged Multifractal, so that the higher elevations will be more craggy.

Finally, I will load an image of the plates shader from tectonics.js to serve as a guide to placing additional mountains. Unless you paid close attention to the movements of the features as tectonics.js was running, you’ll have to simply choose some of the plate boundaries as areas to place additional mountains and hills. These can be added by creating feathered selections and applying calculated fractals as above.

I painted in additional details with the raise and lower tools, and then applied an iterative process of basin fill, erosion and noise to complete the elevation map. Save this set of elevations as a BT and a PNG Surface. You’ll also want a flat seas version, so Filter>Height Clip… Min: sea level(probably zero), Max: higher than the highest mountain on the map(Which you can find using Window>Histogram…). Also save this flattened seas elevation set as a BT and a PNG.

Now comes the real meat of this post: using the best features of Wilbur and Photoshop/GIMP to create a realistic-looking planetary surface texture.

The latitude shader in Wilbur still doesn’t work terribly well as of version 1.86, so I won’t be using that. Besides, I have come up with a method to use the much more powerful compositing tools of any good image processing app.

To do the ice maps, start with the elevations map in meters with seas flattenned, use Filter>Mathematical>Wilbur Scale(Multiply)… by an appropriate lapse rate(for Earth, with elevations in meters -0.0065ºC/m works). For Earth, this should result in a variation in temperature due to altitude of about 0 to -56K.  Next add in a sea level temperature variance. In Wilbur select Filter>Calculate Height Field… type: Math Function, operation: Add, expression: cos(asin(y)), sphere center: xyz(-1,-1,-1), sphere radii: xyz(2,2,2), spherical evaluation: checked(as always), surface scaling: to range: about 30 to -25 to allow room for some random variation. Extremes of mean annual temperature on Earth work out, after some very cursory research, to 35ºC to -26ºC as adjusted for sea level. Similarly cursory research showed that while mean annual temperatures are effected by altitude, and while the variations around that mean get much wider with distance inland and latitude, the means largely aren’t sensitive to distance from the sea. So as I’m just working out mean annual temperatures, I don’t need to take raw distances from the ocean into account. In order to add a little random variation, I ran a heteroterrain fractal with spherical radius of 8, only 4 octaves, and a scaling of 5 to -2.

A map of temperatures on this planet. I seem to be using too much noise, and the lack of definition of continental areas makes me think that I do not have enough midrange elevations. Red is hottest, down to yellows, greens and black. The sharp line between black and light blue is at 0ºC. Blues darken through purples towards black at the coldest temperatures.

I used an unshaded version of this map with a different color scheme to show a spatial distribution of mean annual temperature. I thought the image was effective, but I’m not happy with the amount of noise and it showed that the hypsometric distribution was not altogether satisfactory. Still working on that! I also think I might have done better with a ridged multifractal here.

With this temperature map, Select>From Terrain>Height Range… to create ice masks. For a  persistent snow and land ice mask, set the maximum to 0.0ºC. Salt water freezes at a lower temperature. For this mask, set the maximum to -13ºC. When applying ice and snow layers in your image editor, place the land ice layer above most everything else, but below any relief shading layer. I placed the sea ice layer above the hillshade to lighten it a bit. When I did this, I simply used the black and white masks directly, selecting the black areas with magic wand and deleting them. It might be better and certainly more flexible to use these masks as layer masks on some kind of nicely-textured ice color layers. I haven’t tried that yet, but it seems like a worthwhile experiment.

I got a lot of information from examining the shader code in tectonics.js, which I would find useful in shading my own model. For bedrock coloring, the modeller uses a gradient from mafic rock(RGB(50,45,50)) to felsic rock(RGB(190,180,185), based on height. For this, I used the original flattened seas elevation map with a two color altitude shader in Texture>Shader Setup… The colors would be the mafic color near sea level with felsic at higher altitudes. In retrospect I could have added noise to the elevation map for variety, but I didn’t this time. I also played with the colors a bit to make it more aesthetic to my eye.

The sediment color map is a latitude map generated as described above using the Math Function method of the calculate height field filter. I again used a two color gradient with a peat color of RGB(100,85,60) for the cold polar areas and a sand color of RGB(245,215,145) as we get into warming areas. This was based solely on latitude. I could have used the temperature map with a different noise seed, but instead I ignored altitude.

What tectonics.js refers to as mineral fraction, basically describes the amount of sediment covering the underlying bedrock. I used a straight flat seas elevation map with a two color gradient, ranging from white at sea level to black at the highest points. I used this in my image editor as a layer mask for the sediment color layer placed above the existing bedrock color layer generated above. Again, I could have used some additional noise to add variety to this, but I decided to keep things kind of simple.

Next, I created a vegetation color layer. Although tectonics.js uses a single jungle color of RGB(30,50,10) everywhere, simply varying the alpha strength over the underlying sediment and rock layers, I used a latitude-based temperature model as described above, with a two color gradient of a darker, more saturated variation on the jungle color at low latitudes and a lighter, greyer variation for high latitudes. I could have, and probably should have used the full latitude-altitude model, but I got lazy.

Rather than using a latitude based model, taking precipitation and temperature into account to build the vegetation mask, I decided to hand paint it, based on the satellite view map derived from tectonics.js. I’m thinking that, once again, the modelling process would result in a more interesting and possibly more plausible texture, but its a bit more complicated to derive a plausible precipitation map(the simulator uses k1 + k2cos(6lat) + k3(1-lat/90) – k4dist_to_cont_edge*sin(lat), complicated and the user has to work out values for k1, k2, k3 and k4, for the sake of simplicity, k4 can probably be set to 0.0) and the prospect of combining the temperature and precipitation maps(again, figuring out weights) was daunting. I also wanted a small positive altitude element to the precipitation, with varying strength depending on latitude. For now, I’ll just paint this in. Later, I might come up with something less uninteresting…

I started by creating a layer mask for my vegetation color layer. I filled the mask with black. Next I loaded a seamask selection. Make sure Sea White is not checked when generating the mask using Texture>Gray Maps>Sea Mask…, or if you’re using an already-generated white sea mask, simply invert the selection. We want our strokes constrained to the land area. Next fill in the land area with white.

Now, paint the broad strokes into the layer mask using a large, soft brush in multiply mode and a very light gray color. This will be to reduce the vegetation in the polar areas, and then to roughly follow the latitudes where most of the desert areas lie. If you were working in Wilbur, this would be around 30º N and S, but your image editing app probably won’t show such nice geographic coordinates.

I also painted out the mask in areas under ice, though with much less success. Ice-covered areas should really have no vegetation at all. Also high mountains should have reduced vegetation, although in desert areas, the might get a little more due to orogenic precipitation.

Next, using progressively smaller and darker multiply brushes, paint out the desert and less vegetated areas in more detail. Finally, using a river flow map from Wilbur as a guide stroke along the rivers in a smallish very dark gray screen brush. This will show floodplain areas that are considerably more lush in otherwise less vegetated areas, but will have little perceptible effect in heavily forested or jungle areas. Rather than hand-painting the areas around rivers, one could directly apply a green-shaded layer controlled by a blurred copy of the river flow map.

I created fully shaded flat maps with rivers shown clearly as in the image at the top of the page. For use in texturing a globe for 3d renderings, hide the river and hillshade layers and save the resulting image. This will be shaded in the rendering using a bump map or normal map derived from the elevations map. Typically, I would save the elevations from Wilbur as a BT and then use GDAL to convert it to a nice 32-bit tiff, but for those without gis tools or the willingness to learn them(GDAL is free, by the way), you can simply save it as a 16-bit PNG Surface directly from Wilbur(unfortunately, at least in Cycles, 16-bit PNGs don’t seem to work well, so use your favorite graphics editor to convert to tiff).


Good modelers can make excellent photorealistic imagery with the Blender Internal Renderer, but I can’t do much better than cartoonish. The render proved disappointing, but darn quick.


The Cycles rendering took a lot longer, but my skills with Cycles are still growing. In any case, I really should have upsampled the underlying texture images much earlier in the process.

The process is still very much a work in progress, but it’s leading in a direction I find very promising. A few notes.

• Upsample the textures. A lot.

•• Probably start with low-res, and heavily blurred masks. Add noise and apply erosion, then resample. Do this in multiple steps, upsampling both the masks and the heightfield, then adding noise and erosion. Erosion may be too slow at high resolutions, but hopefully 8192×4096 or perhaps 16384×8192 will be sufficient to avoid artifacting in the final render.

• Figure out how to create precipitation models analytically, rather than by hand.

• Create vegetation masks from temperature, precipitation, river flow and distance imagery.

Hopefully, the next try will be good enough for a final model…

Thank you for reading this,
The Astrographer

This entry was posted in Mapping, Planetary Stuff, Projects, World Building and tagged , , , , , , , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s