Swiftless Game Programming Tutorials













Back to OpenGL Tutorial Index

Discuss this Tutorial in the Forum

Well this is gonna be quite the little tutorial. In this opengl tutorial I will be teaching you how to create opengl terrain using heightmaps. You will be learning how to load a RAW file as a heightmap and also texturing with heightmaps. You will also get an idea on how opengl terrain generation and opengl terrain rendering works.

Well this is gonna be quite the little tutorial

--------------------------------------------------
First section: Variables

In this application, we use the variables:
int mapX;
int mapY;
int mapZ;
To hold our X,Y and Z coordinates for our heightmap
during the application.

We use:
const MapWidth = 384;
const MapHeight = 384;
To hold the width and height(length) for our heightmap
these have to be 3 times the size of the width and height
of our RAW file as our RAW file is parsed in intervals
of 3. So our 128 X 128 heightmap is really 384 X 384.

We then set up our texture storage space with:
GLuint texture[10];
I have set up enough storage for 11 textures
for the next installment of terrain generation.

Now the next variable holds all our heights with:
BYTE HeightMap[MapWidth][MapHeight];
I have set it to BYTE as all our data from our RAW
file is read in BYTES as Binary.

---------------------------------------------------
Section 2: Loading the HeightMap Heights

Our first function is called LoadHeightMap
with arguments: (char* Filename, int Width, int Height)
this will be called on startup to read in our HeightMap
and allocate the data accordingly in our HeightMap array.

Within this I have the variable int smoothen, this will be
used later on in a loop to parse the heights and average
them amongst there surrounding heights for smoother
looking terrain.

We also have the variable FILE *File which will be the
file we are opening (heightmap.raw).

Next we set our File to our currently selected filename
and read it with the properties "rb" meaning read-binary.

Then we acctually read the file into our Heightmap array
in intervals of 1 byte per array for as many times as
our files width X height X 3 (remembering our RAW file
is parsed in intervals of 3).

Now that we have all the data within our array, we close
the file.

Next comes the smoothing, to smooth, I have gone through
every height within our array and averaged it out amongst
its surrounding heights. Simple addition and division to
get the average. I have parsed this through 3 times to get
an alright looking terrain.

---------------------------------------------------
Section 3: Displaying the HeightMap

To get the optimum look out of the terrain, I am loading every
fourth height and setting them 4 units apart. If I set them
1 unit apart and call every 1 then the terrain looks jagged.
And if I set them further apart and call less, then it looks
too smooth for me. So you can change these as you see fit.

Now acctually displaying them is simple enough. I am using triangle
strips and am calling a triangle strip for every width and height.
Within this I am also setting our texture coordinates. Self explanatory
if you know about triangle strips.

---------------------------------------------------
Section 4: Optimization

To optimise our terrain to get the best amount of frames
per second, I have added some Culling in the enabling
code to discard faces we dont need (remember to set the front face to CCW
- counter clock wise -as triangle strips set there faces opposite to most
shapes).

Also by calling only every fourth height, I am saving the processing
times and thus also increasing the frames per second.

#include <GL/gl.h>
#include <GL/glut.h>
#include <windows.h>
#include <stdio.h>
#include <math.h>
#include <iostream.h>

int mapX;
int mapY;
int mapZ;

const MapWidth = 384;
const MapHeight = 384;

GLuint texture[10];

BYTE HeightMap[MapWidth][MapHeight];

GLuint LoadTexture( const char * filename, int width, int height )
{
    GLuint texture;
    unsigned char * data;
    FILE * file;

    //The following code will read in our RAW file
    file = fopen( filename, "rb" );
    if ( file == NULL ) return 0;
    data = (unsigned char *)malloc( width * height * 3 );
    fread( data, width * height * 3, 1, file );
    fclose( file );

    glGenTextures( 1, &texture ); //generate the texture with the loaded data
    glBindTexture( GL_TEXTURE_2D, texture ); //bind the texture to it's array
    glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); //set texture environment parameters

    //here we are setting what textures to use and when. The MIN filter is which quality to show
    //when the texture is near the view, and the MAG filter is which quality to show when the texture
    //is far from the view.

    //The qualities are (in order from worst to best)
    //GL_NEAREST
    //GL_LINEAR
    //GL_LINEAR_MIPMAP_NEAREST
    //GL_LINEAR_MIPMAP_LINEAR

    //And if you go and use extensions, you can use Anisotropic filtering textures which are of an
    //even better quality, but this will do for now.
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR );

    //Here we are setting the parameter to repeat the texture instead of clamping the texture
    //to the edge of our shape.
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );

    //Generate the texture with mipmaps
    gluBuild2DMipmaps( GL_TEXTURE_2D, 3, width, height, GL_RGB, GL_UNSIGNED_BYTE, data );
    free( data ); //free the texture
    return texture; //return whether it was successfull
}

void FreeTexture( GLuint texture )
{
  glDeleteTextures( 1, &texture );
}

void LoadHeightMap (char* Filename, int Width, int Height) {

int smoothen;

FILE * File;

File = fopen( Filename, "rb" );

fread( HeightMap, 1, Width * Height * 3, File );

fclose( File );

for (smoothen = 0; smoothen < 3; smoothen++){
for (mapX = 1; mapX < Width; mapX ++){
for (mapZ = 1; mapZ < Height * 3; mapZ++){
mapY = HeightMap[mapX][mapZ];
mapY += HeightMap[mapX-1][mapZ];
mapY += HeightMap[mapX+1][mapZ];
mapY += HeightMap[mapX][mapZ-1];
mapY += HeightMap[mapX][mapZ+1];
mapY += HeightMap[mapX-1][mapZ-1];
mapY += HeightMap[mapX-1][mapZ+1];
mapY += HeightMap[mapX+1][mapZ-1];
mapY += HeightMap[mapX+1][mapZ+1];
mapY = mapY/9;
HeightMap[mapX][mapZ] = mapY ;
}
}
}
}

void DisplayHeightMap (void) {
int Height;

for (mapX = 1; mapX < MapWidth; mapX +=4){
for (mapZ = 1; mapZ < MapHeight * 3; mapZ+=4){
    glBegin(GL_TRIANGLE_STRIP);
    Height = HeightMap[mapX][mapZ];
    glTexCoord2f(0,0);
    glVertex3f(float(mapX),Height,float(mapZ));
    
    Height = HeightMap[mapX][mapZ+4];
    glTexCoord2f(0,1);
    glVertex3f(float(mapX),Height,float(mapZ+4));

    Height = HeightMap[mapX+4][mapZ];
    glTexCoord2f(1,0);
    glVertex3f(float(mapX+4),Height,float(mapZ));

    Height = HeightMap[mapX+4][mapZ+4];
    glTexCoord2f(1,1);
    glVertex3f(float(mapX+4),Height,float(mapZ+4));
    glEnd();
}
}
}

void enable (void) {
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);
    glFrontFace(GL_CCW);
    glCullFace(GL_BACK);
    glEnable(GL_CULL_FACE);    
    glShadeModel (GL_SMOOTH);
    glEnable(GL_TEXTURE_2D);
}

void display (void) {
    glClearColor (0.0,0.0,0.0,1.0);
    glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    enable();
    glTranslatef(30, 0, 30);
    glRotatef(150, 0,1,0);
    glColor3f(1,1,1);
    glBindTexture(GL_TEXTURE_2D, texture[0]);
    DisplayHeightMap();
    glutSwapBuffers();
}

void init (void) {
    texture[0] = LoadTexture("texture.raw", 256, 256);
    LoadHeightMap ("height.raw", 128, 128);
}

void reshape (int w, int h) {
    glViewport (0, 0, (GLsizei)w, (GLsizei)h);
    glMatrixMode (GL_PROJECTION);
    glLoadIdentity ();
    gluPerspective (100, (GLfloat)w / (GLfloat)h, 0.01, 500.0);
    glMatrixMode (GL_MODELVIEW);
}

int main (int argc, char **argv) {
    glutInit (&argc, argv);
    glutInitDisplayMode (GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGBA);
    glutInitWindowSize (500, 500);
    glutInitWindowPosition (100, 100);
    glutCreateWindow ("A basic OpenGL Window");

    init();

    glutDisplayFunc (display);
    glutIdleFunc (display);
    glutReshapeFunc (reshape);

    glutMainLoop ();

    return 0;
}

Download C++ Source Code for this Tutorial

Download Visual Basic Source Code for this Tutorial

Download Heightmap (.RAW file)

Download Heightmap (.BMP file)

 
Site proudly supported by: http://www.cdadc.com
 

Want more information on Game Programming here? Just email me with your question.

CHOLESTEROL CHOLESTROL

cholesterolcholestrol.com Which covers CHOLESTROL / CHOLESTEROL as well as provides many fast WEIGHT LOSS tips and many diet recipes. Here are just a few of the pages covered in more detail:

Cholesterol:
Basics to prevent cardiovascular disease     Symptoms      LOWER CHOLESTEROL NATURALLY Foods, Vitamins, Herbs and Spices that reduce cholestrol     LOW CHOLESTROL, Low Calorie, Low Saturated Fat Recipes     FOOD CHART Cholesterol and saturated fats in foods     ALL ABOUT CHOLESTROL LEVELS Understanding cholestrol levels.     Sample Diet To lower cholesterol.     Menu planner Making a Low Cholesterol Diet much easier.    
Cholesterol and:
Turkey      Egg     Fish Oil and heart health      Red rice yeast     The OLD diet page     

Cholesterol Health, Fitness and Weight Loss Calculators:
FREE DAILY CALORIE INTAKE CALCULATOR, FAT INTAKE CALCULATOR, IDEAL WEIGHT CALCULATOR etc Goals for maximum health: Maximum and minimum weight, daily calorie / kilojoule intake, fat intake, saturated fat intake and, unsaturated fat intake, plus more.     WEIGHT LOSS CALCULATOR BASED ON BMI

REAL FAST WEIGHT LOSS

Index      Our Very Best Program I lost lots of weight, much from my stomach. I also lost my high cholesterol, pre-diabetes, metabolic syndrome and high blood pressure. This program really helped.     Exercise      Diet recipes page 1     Diet recipes page 2

(colesterol.cholesterolcholestrol.com Cuál cubiertas el COLESTEROL así como también proporciona muchas puntas rápidas de la PERDIDA del PESO y muchas recetas de la dieta.)

HEMORRHOIDS

HEMROIDS HEMORROIDS HEMOROIDS HEMEROIDS HEMMOROIDS HEMEROIDS All about them What they are etc, with photos included.     Hemorroides Spanish .     Causes     Bleeding     Home remedies     Treatment overview     Hemorrhoidectomy     Other surgery     Pregnancy and prolapses     Cure     Painful and or Thrombosed

DOWN SYNDROME

Jacob, a child with Down Syndrome and our fight to overcome Down Syndrome, Downs Syndrome, Down's Syndrome, Down Sindrome.     Glyconutrients     Intervention Increasing intelligence and abilities and reducing incapacity.     The Pregnancy Symptoms and Tests     Hypotonia     Altering the symptoms     Life Expectancy     Improving intelligence and lessening the retardation     Treatments     Causes

CHICKEN RECIPES

100's of them Recipes arranged by main word and utterly searchable.      Lots of whole chicken recipes from around the world.

GAME PROGRAMMING

COMPUTER 3D GAME PROGRAMMING TUTORIALS One of the best on the net.     Game Maker     Cube     camera     More camera code     Heightmap     Making fire in photoshop     Creating fog     Fullscreen     Lighting     Tutorials

HISTORY AND LEGENDS

HISTORY AND LEGENDS An extensive web site on the history and legends of Scotland and other places.     Urquhart and Glenmoriston Hundreds of pages on the history of Scotland, with particular reference to the Urquhart and Glenmoriston area.

Our MINOR WEB SITES - Our websites of few pages:

ALZHEIMER'S DISEASE     VASCULAR DEMENTIA     BIOLOGICAL TERRORISM and CLIMATE CHANGE     THE SCOTTISH CLAN URQUHART     DOCUMENTS OF REVOLUTION IDEAOLOGY    
But first, if you want to come back to this website again, just add it to your bookmarks or favorites now! Then you'll find it easy! Also, please consider linking to our site if you are a web master - reciprocal linking is fine.

If you have a page rank of 3 or more, we will be happy to engage a link exchange. Many people have been kind enough to link to us and this is our links page back to them to say thank you: Links We are currently able to offer up to 10 links from different websites and subdomains, in exchange for the same number from you - upto one for each of our web sites and subdomains in return.
Our Privacy Policy can be found at www.cholesterolcholestrol.com/privacypolicy.htm
Copyright © 2000-2007 Donald Shannon Urquhart. All Rights Reserved. Designated trademarks and brands are the property of their respective owners. Use of this Web site constitutes acceptance of our legal disclaimer.