How to create textures for use with the Ogre Terrain Component |
Table of contents
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
- Get ShaderMap CL from http://www.shadermap.renderingsystems.com/ (Link no longer works, try http://shadermap.com/home/)
- Create a bat file with the following contents:
Copy to clipboardCD "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. - Generate the maps by running the bat script, once for each texture.
- Use the following C++ code to combine the images:
Copy to clipboardOgre::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"); - Get the nVidida texture tools (DDS Utilities) and convert the output textures to dds.
- Done.
PixPlant
PixPlant is powered by Ogre and is a highly recommended texture tool!
- Fire up PixPlant and File->Load Texture->dirt.jpg
- 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.
- File->Save All 3D Material Maps..
- You should now have four different textures:
Copy to clipboarddirt_DIFFUSE.png dirt_DISP.png dirt_NORMAL.png dirt_SPECULAR.png - 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):
- Right click on the layer you want to add an alpha channel.
- Go to Layer->Mask->Add Layer Mask...
- Add a grayscale copy of the layer or a blank image, whatever fits your needs. You can later paste something else.
- 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.