Ogre Terrain Textures        
Textures How to create textures for use with the Ogre Terrain Component

Introduction

The default material generator of the Ogre Terrain Component uses two textures per layer:
Normal_height and Diffuse_specular.
It's important to have the textures in the right format, otherwise the terrain is not going to look right.

The following shows different ways to create a working set of terrain textures.


ShaderMap CL

  1. Get ShaderMap CL from http://www.shadermap.renderingsystems.com/ (Link no longer works, try http://shadermap.com/home/)
  2. Create a bat file with the following contents:
    CD "C:\Program Files\ShaderMap CL 1.2.2"
    
    START /WAIT shadermap.exe cdiff "<texture_directory>\<texture_name>" -disp (60,100,12,xy) -norm (100,200,xy,0) -spec (100,-50,52,xy) -v

    Replace the directory and texture name with what you want to generate maps for.
  3. Generate the maps by running the bat script, once for each texture.
  4. Use the following C++ code to combine the images:
    Ogre::Image combined;
    
       combined.loadTwoImagesAsRGBA("moos1.jpg", "moos1_SPEC.bmp", 
          Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::PF_BYTE_RGBA);
       combined.save("moos1_diffusespecular.png");
    
       combined.loadTwoImagesAsRGBA("moos1_NORM.tga", "moos1_DISP.bmp", 
          Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::PF_BYTE_RGBA);
       combined.save("moos1_normalheight.png");
  5. Get the nVidida texture tools (DDS Utilities) and convert the output textures to dds.
  6. Done.


PixPlant

PixPlant is powered by Ogre and is a highly recommended texture tool!

  1. Fire up PixPlant and File->Load Texture->dirt.jpg
  2. Adjust the Intensity value of the Specular channel - too much will make the terrain look weird. -80 is about right, but it depends on the source texture, naturally.
  3. File->Save All 3D Material Maps..
  4. You should now have four different textures:
    dirt_DIFFUSE.png
    dirt_DISP.png
    dirt_NORMAL.png
    dirt_SPECULAR.png
  5. Use the code from previous section to combine the textures into Diffuse_specular, Normal_height textures.

The Gimp

You work on the layer mask. It's like an alpha channel but with a different name BUT gimp doesn't see it as an alpha channel until you apply it.

Therefore, on the image you're already working, go to the Layer window (if you don't have it, menu Windows->Dockable Windows->Layers):

  1. Right click on the layer you want to add an alpha channel.
  2. Go to Layer->Mask->Add Layer Mask...
  3. Add a grayscale copy of the layer or a blank image, whatever fits your needs. You can later paste something else.
  4. Once you're finished, click on Layer->Mask->Apply Layer Mask. This will turn the layer mask into the alpha channel.


I prefer opening the file in the regular way (not "Open as Layers").
To work on individual channels (except alpha, you work on it as a "mask") I recommend using the channel window (Windows->Dockable Windows->Channels) and selecting one channel allows you to work on one channel at a time (including copy-pasting)

If you need DDS support, you can try the GIMP DDS plugin, but it has basic support and you may be better off with a dedicated tool.


NetPBM utilities

The NetPBM utilities are a set of over 200 very simple command line utilities to perform manipulations on images. The programs use a common data format but provide converters to change to and from most image formats in use today. The power of the package is that you can use the programs in concert to perform any desired transformation (such as creating the combined textures or dicing images files for the paging manager). The utilities have been ported to most *nix variants, Mac, and Windows.

A makefile is available that automates the process of creating textures. Support is available here


ImageMagick

Also the ImageMagick commandline tools can be used to combine the textures. This replaces the C++ sample for combining the textures, instead a batch script could be written that would do something like this:

#Join diffuse and specular
convert dirt_DIFFUSE.png -channel R -separate dirt_R.png
convert dirt_DIFFUSE.png -channel G -separate dirt_G.png
convert dirt_DIFFUSE.png -channel B -separate dirt_B.png
convert dirt_R.png dirt_G.png dirt_B.png dirt_SPECULAR.png -channel RGBA -combine dirt_diffusespecular.png

# Join normal and height/displacement
convert dirt_NORMAL.png -channel R -separate dirt_NORMAL_X.png
convert dirt_NORMAL.png -channel G -separate dirt_NORMAL_Y.png
convert dirt_NORMAL.png -channel B -separate dirt_NORMAL_Z.png
convert dirt_NORMAL_X.png dirt_NORMAL_Y.png dirt_NORMAL_Z.png dirt_DISP.png -channel RGBA -combine dirt_normalheight.png

Note that both dirt_SPECULAR.png and dirt_DISP.png are greyscale (single channel) images.
dirt_DIFFUSE.png and dirt_NORMAL.png are should both be three-channel RGB images.
More information about separating and combining color channels with ImageMagick can be found in this article.

The resulting textures (dirt_diffusespecular.png and dirt_normalheight.png) will still need to be converted into .dds format afterwards. This can be done with commandline tools like Crunch, DevIL libraries, or the NVIDIA commandline texture tools.


Using this approach I constructed the following reusable bash script for generating my terrain textures

#!/bin/bash

##
# Stitch textures together into _diffusespecular and _normalheight
# terrain textures.
# As input you need 4 png images, each without alpha.
#  - an RGB (3 channel) diffuse image
#  - a greyscale (1 channel) specular map image
#  - an RGB (3 channel) normal map image
#  - a greyscale (1 channel) height map image
# Make sure those 4 images are of the same dimensions.
##

## SETUP ##
CRUNCH_PATH=~/projects/crunch/crnlib/crunch		# path to crunch executable
	# You can get crunch from http://code.google.com/p/crunch/
###########

function stitchTextures {
	diffuseRGB=$1
	specularA=$2
	normalRGB=$3
	heightA=$4
	
	outputName=$5
	##############

	echo "stitching $diffuseRGB, $specularA and $normalRGB, $heightA together into" $outputName"_diffusespecular.png and" $outputName"_normalheight.png."
	
	##############
	
	# Join diffuse and specular
	convert $diffuseRGB -channel R -separate $outputName"_diffuse_R.png"
	convert $diffuseRGB -channel G -separate $outputName"_diffuse_G.png"
	convert $diffuseRGB -channel B -separate $outputName"_diffuse_B.png"
	convert $specularA -negate $outputName"_specular_A.png" # for some reason I need to invert alpha
	convert $outputName"_diffuse_R.png" $outputName"_diffuse_G.png" $outputName"_diffuse_B.png" $outputName"_specular_A.png" -channel RGBA -combine $outputName"_diffusespecular.png"

	# Join normal and height/displacement
	convert $normalRGB -channel R -separate $outputName"_normal_X.png"
	convert $normalRGB -channel G -separate $outputName"_normal_Y.png"
	convert $normalRGB -channel B -separate $outputName"_normal_Z.png"
	convert $heightA -negate $outputName"_height_A.png"
	convert $outputName"_normal_X.png" $outputName"_normal_Y.png" $outputName"_normal_Z.png" $outputName"_height_A.png" -channel RGBA -combine $outputName"_normalheight.png"
	
	# Remove temporary files
	rm $outputName"_diffuse_R.png"
	rm $outputName"_diffuse_G.png"
	rm $outputName"_diffuse_B.png"
	rm $outputName"_specular_A.png"
	rm $outputName"_normal_X.png"
	rm $outputName"_normal_Y.png"
	rm $outputName"_normal_Z.png"
	rm $outputName"_height_A.png"
	
	# Convert to DDS using crunch
	$CRUNCH_PATH -file $outputName"_diffusespecular.png" -fileformat dds -dxt5
	$CRUNCH_PATH -file $outputName"_normalheight.png" -fileformat dds -dxt5
		# DXT compression types:
		# 	DXT1 	0 or 1 bit alpha
		# 	DXT2 	Explicit 4-bit alpha, color data is premultiplied by alpha *
		# 	DXT3 	Explicit 4-bit alpha, not premultiplied
		# 	DXT4 	Interpolated alpha, color data is premultiplied by alpha *
		# 	DXT5 	Interpolated alpha, not premultiplied
		#
		# * means less frequently used
		# Because we need full alpha channel for terrain, we need either 
		# DXT3 or DXT5. DXT5 is recommended.
	
	# Create Ogitor terrainTex thumbnail
	convert $diffuseRGB -geometry 128x128 $outputName"_diffuse.png"
}

##
# Shorthand function call
##
function stitch {
	namePrefix=$1
	
	stitchTextures $namePrefix"_diffusemap.png" $namePrefix"_specular.png" $namePrefix"_normal.png" $namePrefix"_heightmap.png" $namePrefix
}

### MAIN ###
	# add the textures you want to build here

stitch jungle_4
stitch sand_1

To make it work you need to have 4 .png source files, as explained in the header of the script. Just make sure none of them contain an alpha channel and that they have the correct number of channels (3 or 1). For example for building the "jungle_4" texture you would need the files jungle_4_diffusemap.png, jungle_4_normal.png, jungle_4_specular.png and jungle_4_heightmap.png.

I like using this script because I find it a lot easier to work with separate PNGs, without alpha channel and merge them later into a DDS texture, as PNGs are easier to view, edit and distribute, and they are lossless.
Just make sure you have both imageMagick and Crunch installed to use it.


Todo

  • Make a command-line tool which takes four textures: name_DIFFUSE, name_DISP, name_NORMAL and name_SPECULAR as input and produces a set of terrain textures.
  • Same as previous, but featuring a GUI and/or a batch mode - maybe even calling ShaderMap CL to generate the four source textures from input textures.