Before we get started, class, will all students please make sure they've downloaded EasyGen (
http://digilander.libero.it/ilbanca/files/EasyGen_v142.zip) for me? Thanks, that's a big help. Also, take some time to familiarize yourself with the EasyGen 3D view controls before going any further with this tutorial; they are pretty much like Radiant, but there are a few subtle differences. If you play around with it for two minutes, you'll figure it out.
Some EasyGen (
http://digilander.libero.it/ilbanca/files/EasyGen_v142.zip) setup guidelines:• When it asks you for the "Work mod" path, enter the path to your "gamedata/base" directory (for default install of JK2: "c:\program files\lucasarts\star wars jk ii jedi outcast\gamedata\base")
• Ignore the "Bitmaps" "Export folders" path
• Put the path to your "gamedata/base/textures" in for the "Bitmaps" "Import folder" (for default install of JK2: "c:\program files\lucasarts\star wars jk ii jedi outcast\gamedata\base\textures\")
• Set the "Player size" to "32 32 64"
• Make sure the "Texture load filter" is set to "jpg;tga"1. Create your heightmap in the bitmap-creation software of your choosing. I'm partial to Photoshop, but if that particular app is beyond your means, I'm sure any number of cheaper alternatives will give you decent results (maybe). Here are the particulars:• The heightmap needs to be 33x33 pixels (yes, that small--each pixel of this heightmap corresponds to a terrain vertex in EasyGen)
• The heightmap must be an 8-bit, greyscale .bmp Bitmap file.
• 50% grey is "sea level," zero elevation. Darker pixels are lower elevation, and brighter pixels are higher. Who would have guessed?
• Save your heightmap into your base/textures/<yourmap>/ directorySo anyway, here's how my heightmap turned out for this little test map I started this thread for:
http://www4.ncsu.edu/~rlcordes/heightmap.bmpJust) a little unimpressive, yeah? Well, brace yourself: the sparks, now waking from their long winter naps, are preparing to fly.
2. Fire up EasyGen (
http://digilander.libero.it/ilbanca/files/EasyGen_v142.zip) and pick, from the "File" menu, "Import -> Heightmap (.bmp)"
http://www4.ncsu.edu/~rlcordes/easyGen0.jpg)
In the next little window that pops up, hit the "Browse..." button and navigate to base/textures/<yourmap>/ (where you saved the .bmp heightmap you created in step one). After you've chosen your heightmap, notice the "Terrain height" field: it defaults to "256," which is pretty low. Set this to "1024" and hit "Ok." You should see something like this:
http://www4.ncsu.edu/~rlcordes/easyGen1.jpg)
3. Now it's time to add textures; from the "Textures" menu in EasyGen (
http://digilander.libero.it/ilbanca/files/EasyGen_v142.zip), choose the "Add folder..." option (it's the first one):
http://www4.ncsu.edu/~rlcordes/easyGen2.jpg)
Now browse to the textures directory of your choosing; for this example map, I used the "Yavin" texture set. Loading the textures in EasyGen (
http://digilander.libero.it/ilbanca/files/EasyGen_v142.zip) takes even longer than in Radiant, so be prepared to wait. You'll know it's ready when you can hit the "Alphamap" tab and things look like this:
http://www4.ncsu.edu/~rlcordes/easyGen3.jpg)
4. Click the first black square in that color palette area and choose a non-black color. Then scroll down the texture browser (on the left) and choose what texture you want that color to represent. Now, choose "Texture" from the "View" menu and things will start looking like this:
http://www4.ncsu.edu/~rlcordes/easyGen4.jpg)
5. Click the next black square in the palette, pick a new color and a new texture. Now we're ready to start painting. Make sure your newest color/texture is selected in the palette, then you can use ctrl+shift+leftMouse to paint that texture onto your terrain:
http://www4.ncsu.edu/~rlcordes/easyGen5.jpg)
6. Click the next black square in the palette, pick a new color and a new texture. Paint as many different textures onto your terrain as you like, but be warned: quake will alpha-blend at most two textures on any given triangle. If you try and blend more than two textures on one triangle, it will show up as black in EasyGen (
http://digilander.libero.it/ilbanca/files/EasyGen_v142.zip), so it's easy to see the areas you need to go back and fix:
http://www4.ncsu.edu/~rlcordes/easyGen6.jpg)
When you get this, you'll need to re-paint your textures until you've only got two blends happening on any given triangle.
7. Once you've got your textures set up how you want them, it would be a good time to Save your project in EasyGen (
http://digilander.libero.it/ilbanca/files/EasyGen_v142.zip). Just in case the power goes out, you can load up your .egn file and not have lost all this work.
8. Now is the time to export the whole shebang:
http://www4.ncsu.edu/~rlcordes/easyGen7.jpg)
Then, in the next window, set your options like this (everywhere I wrote "tutorial," put whatever your project is called):
http://www4.ncsu.edu/~rlcordes/easyGen8.jpg)
Save the .pcx file into the "gamedata/base/" directory, and save the metashader into the "base/scripts/" directory. This will need to be moved into the "base/shaders/" directory in a little bit, but right now EasyGen (
http://digilander.libero.it/ilbanca/files/EasyGen_v142.zip) only wants you to put it into the scripts folder. Set the remaining options up like I've got them (I assume you're using q3map2 (
http://www.shaderlab.com/q3map2/2.5/q3map_2.5.6_win32_x86.zip) to compile), and you're good to go. Hit "Continue >>>" and away we go--just save it as whatever.map in the "base/maps/" folder, and we're done with this part.
9. Move your .shader file from the "base/scripts/" folder to the "base/shaders" folder, and then open your .shader file in Notepad (or whatever text editor you prefer). It should look something like this:textures/tutorial/terrain_0
{
q3map_lightmapsamplesize 64
q3map_lightmapaxis z
q3map_texturesize 512 512
q3map_tcGen ivector ( 128 0 0 ) ( 0 128 0 )
{
map textures/yavin/greenblock.jpg
}
{
map $lightmap
blendFunc GL_DST_COLOR GL_ZERO
tcGen lightmap
}
}
textures/tutorial/terrain_1
{
q3map_lightmapsamplesize 64
q3map_lightmapaxis z
q3map_texturesize 512 512
q3map_tcGen ivector ( 128 0 0 ) ( 0 128 0 )
{
map textures/yavin/rock3.jpg
}
{
map $lightmap
blendFunc GL_DST_COLOR GL_ZERO
tcGen lightmap
}
}
textures/tutorial/terrain_2
{
q3map_lightmapsamplesize 64
q3map_lightmapaxis z
q3map_texturesize 512 512
q3map_tcGen ivector ( 128 0 0 ) ( 0 128 0 )
{
map textures/yavin/lighturth.jpg
}
{
map $lightmap
blendFunc GL_DST_COLOR GL_ZERO
tcGen lightmap
}
}
textures/tutorial/terrain_3
{
q3map_lightmapsamplesize 64
q3map_lightmapaxis z
q3map_texturesize 512 512
q3map_tcGen ivector ( 128 0 0 ) ( 0 128 0 )
{
map textures/yavin/stone.jpg
}
{
map $lightmap
blendFunc GL_DST_COLOR GL_ZERO
tcGen lightmap
}
}
textures/tutorial/terrain_0to1
{
q3map_lightmapsamplesize 64
q3map_lightmapaxis z
q3map_texturesize 512 512
q3map_tcGen ivector ( 128 0 0 ) ( 0 128 0 )
{
map textures/yavin/greenblock.jpg
}
{
map textures/yavin/rock3.jpg
alphaGen vertex
blendFunc GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
}
{
map $lightmap
blendFunc GL_DST_COLOR GL_ZERO
tcGen lightmap
}
}
textures/tutorial/terrain_0to2
{
q3map_lightmapsamplesize 64
q3map_lightmapaxis z
q3map_texturesize 512 512
q3map_tcGen ivector ( 128 0 0 ) ( 0 128 0 )
{
map textures/yavin/greenblock.jpg
}
{
map textures/yavin/lighturth.jpg
alphaGen vertex
blendFunc GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
}
{
map $lightmap
blendFunc GL_DST_COLOR GL_ZERO
tcGen lightmap
}
}
textures/tutorial/terrain_0to3
{
q3map_lightmapsamplesize 64
q3map_lightmapaxis z
q3map_texturesize 512 512
q3map_tcGen ivector ( 128 0 0 ) ( 0 128 0 )
{
map textures/yavin/greenblock.jpg
}
{
map textures/yavin/stone.jpg
alphaGen vertex
blendFunc GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
}
{
map $lightmap
blendFunc GL_DST_COLOR GL_ZERO
tcGen lightmap
}
}
textures/tutorial/terrain_1to2
{
q3map_lightmapsamplesize 64
q3map_lightmapaxis z
q3map_texturesize 512 512
q3map_tcGen ivector ( 128 0 0 ) ( 0 128 0 )
{
map textures/yavin/rock3.jpg
}
{
map textures/yavin/lighturth.jpg
alphaGen vertex
blendFunc GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
}
{
map $lightmap
blendFunc GL_DST_COLOR GL_ZERO
tcGen lightmap
}
}
textures/tutorial/terrain_1to3
{
q3map_lightmapsamplesize 64
q3map_lightmapaxis z
q3map_texturesize 512 512
q3map_tcGen ivector ( 128 0 0 ) ( 0 128 0 )
{
map textures/yavin/rock3.jpg
}
{
map textures/yavin/stone.jpg
alphaGen vertex
blendFunc GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
}
{
map $lightmap
blendFunc GL_DST_COLOR GL_ZERO
tcGen lightmap
}
}
textures/tutorial/terrain_2to3
{
q3map_lightmapsamplesize 64
q3map_lightmapaxis z
q3map_texturesize 512 512
q3map_tcGen ivector ( 128 0 0 ) ( 0 128 0 )
{
map textures/yavin/lighturth.jpg
}
{
map textures/yavin/stone.jpg
alphaGen vertex
blendFunc GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
}
{
map $lightmap
blendFunc GL_DST_COLOR GL_ZERO
tcGen lightmap
}
}
textures/tutorial/terrain.vertex
{
{
map textures/yavin/greenblock.jpg
rgbGen vertex
}
}This is OK, and will work (sort-of), but some tweeking is needed if you want your terrain to get lightmapped. We want to change it to look like this:textures/tutorial/baseterrain
{
q3map_lightmapsamplesize 8
q3map_lightmapsampleoffset 8
q3map_lightmapaxis z
}
textures/tutorial/terrain_0
{
q3map_baseshader textures/tutorial/baseterrain
{
map textures/yavin/greenblock.jpg
rgbGen identity
tcMod scale 0.1 0.1
}
{
map $lightmap
blendFunc GL_DST_COLOR GL_ZERO
tcGen lightmap
rgbGen identity
}
}
textures/tutorial/terrain_1
{
q3map_baseshader textures/tutorial/baseterrain
{
map textures/yavin/rock3.jpg
rgbGen identity
tcMod scale 0.05 0.05
}
{
map $lightmap
blendFunc GL_DST_COLOR GL_ZERO
tcGen lightmap
rgbGen identity
}
}
textures/tutorial/terrain_2
{
q3map_baseshader textures/tutorial/baseterrain
{
map textures/yavin/lighturth.jpg
rgbGen identity
tcMod scale 0.075 0.075
}
{
map $lightmap
blendFunc GL_DST_COLOR GL_ZERO
tcGen lightmap
rgbGen identity
}
}
textures/tutorial/terrain_3
{
q3map_baseshader textures/tutorial/baseterrain
{
map textures/yavin/stone.jpg
rgbGen identity
tcMod scale 0.1 0.1
}
{
map $lightmap
blendFunc GL_DST_COLOR GL_ZERO
tcGen lightmap
rgbGen identity
}
}
textures/tutorial/terrain_0to1
{
q3map_baseshader textures/tutorial/baseterrain
{
map textures/yavin/greenblock.jpg
rgbGen identity
alphaGen vertex
tcmod scale 0.1 0.1
}
{
map textures/yavin/rock3.jpg
rgbGen identity
alphaGen vertex
tcmod scale 0.05 0.05
blendFunc GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
}
{
map $lightmap
blendFunc GL_DST_COLOR GL_ZERO
tcGen lightmap
rgbGen identity
}
}
textures/tutorial/terrain_0to2
{
q3map_baseshader textures/tutorial/baseterrain
{
map textures/yavin/greenblock.jpg
rgbGen identity
alphaGen vertex
tcmod scale 0.1 0.1
}
{
map textures/yavin/lighturth.jpg
rgbGen identity
alphaGen vertex
tcmod scale 0.075 0.075
blendFunc GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
}
{
map $lightmap
blendFunc GL_DST_COLOR GL_ZERO
tcGen lightmap
rgbGen identity
}
}
textures/tutorial/terrain_0to3
{
q3map_baseshader textures/tutorial/baseterrain
{
map textures/yavin/greenblock.jpg
rgbGen identity
alphaGen vertex
tcmod scale 0.1 0.1
}
{
map textures/yavin/stone.jpg
rgbGen identity
alphaGen vertex
tcmod scale 0.1 0.1
blendFunc GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
}
{
map $lightmap
blendFunc GL_DST_COLOR GL_ZERO
tcGen lightmap
rgbGen identity
}
}
textures/tutorial/terrain_1to2
{
q3map_baseshader textures/tutorial/baseterrain
{
map textures/yavin/rock3.jpg
rgbGen identity
alphaGen vertex
tcmod scale 0.05 0.05
}
{
map textures/yavin/lighturth.jpg
rgbGen identity
alphaGen vertex
tcmod scale 0.075 0.075
blendFunc GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
}
{
map $lightmap
blendFunc GL_DST_COLOR GL_ZERO
tcGen lightmap
rgbGen identity
}
}
textures/tutorial/terrain_1to3
{
q3map_baseshader textures/tutorial/baseterrain
{
map textures/yavin/rock3.jpg
rgbGen identity
alphaGen vertex
tcmod scale 0.05 0.05
}
{
map textures/yavin/stone.jpg
rgbGen identity
alphaGen vertex
tcmod scale 0.1 0.1
blendFunc GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
}
{
map $lightmap
blendFunc GL_DST_COLOR GL_ZERO
tcGen lightmap
rgbGen identity
}
}
textures/tutorial/terrain_2to3
{
q3map_baseshader textures/tutorial/baseterrain
{
map textures/yavin/lighturth.jpg
rgbGen identity
alphaGen vertex
tcmod scale 0.075 0.075
}
{
map textures/yavin/stone.jpg
rgbGen identity
alphaGen vertex
tcmod scale 0.1 0.1
blendFunc GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
}
{
map $lightmap
blendFunc GL_DST_COLOR GL_ZERO
tcGen lightmap
rgbGen indentity
}
}
textures/tutorial/terrain.vertex
{
{
map textures/yavin/greenblock.jpg
rgbGen vertex
}
}
textures/common/terrain
{
q3map_terrain
surfaceparm nodraw
surfaceparm nolightmap
surfaceparm nomarks
}You'll need to twiddle with the "tcMod scale" lines to get your textures looking how you want them, exactly, but this shader file should now be good to go. I hope you can see how to apply these changes to the shader files EasyGen (
http://digilander.libero.it/ilbanca/files/EasyGen_v142.zip) generates.
10. Open up the .map file you created in step eight in Radiant. Select the terrain entity (it's just a func_group, so do whatever you need to do to select all the brushes--in GtkRadiant (
http://www.qeradiant.com) it's ctrl+alt+click) and open the entity inspector by hitting the "n" key. Make sure you've got your terrain entity set up like this: just make sure the name of the .pcx file in the entity inspector matches the name of the .pcx file you created with EasyGen (
http://digilander.libero.it/ilbanca/files/EasyGen_v142.zip), and make sure that the "shader" line matches the name of your shader file (it should be yourmap/terrain). Finally, make sure that you didn't forget to add the "textures/common/terrain" code to yourmap.shader. Now, save this map as a prefab and import it into whatever map you're working on.
11. Compile with q3map2 and you're good to go--you might want to use the -shadeangle switch (I usually use 120) to make sure your terrain is as smooth as possible. Good luck!