OpenGL Terrain Generation - An Introduction

IntroductionNOTE: For the HTML version of thisproperly. As you can see below, the code for
article with graphics and downloads please visit thegenerating and rendering the terrain is very short.
following link: have always been interested inTo give an overview, the first thing that happens
computer graphics and their applications. Datais for the windows to get created, and then we
representation and visualization is one of the maininitialize OpenGL, and read in the BMP file and
areas of HCI (Human Computer Interaction), andassign it to the 2D array we discussed above.
the better you make the interaction between aThen, the texture is applied to the surface of the
machine and a human, the more productivity willmesh, and the scene rendered to the
be generated by both the human and thescreen.Without further ado, the following listing is
machine. I had some experience with OpenGLthe the portion of the code which initializes and
during my undergraduate studies while attendinggenerates the terrain:.
the California Polytechnic University. Unfortunately,.
I never got a chance to pursue the more.
advanced features of the OpenGL library, given// InitializeTerrain()
my time and work responsibilities.You can find// desc: initializes the heightfield terrain data
more about OpenGL at There are also a bunch ofvoid InitializeTerrain()
good literature available on the topic of Computer{// loop through all of the heightfield points,
Graphics and OpenGL that you can refer forcalculating// the coordinates for each pointfor (int
further advancements. Please check thez = 0; z < MAP_Z; z++){for (int x = 0; x <
Background/Reference section for a list of someMAP_X; x++){terrain[x][z][0] =
reference material that I have used, in general,float(x)*MAP_SCALE;terrain[x][z][1] =
for computer graphics.The following project is a(float)imageData[(z*MAP_Z+x)*3];terrain[x][z][2] =
very simple example demonstrating how to-float(z)*MAP_SCALE;}}
generate a terrain based on a bitmap file. The}
objective of the project is to generate a three.
dimensional terrain based on some data file. Please.
note, that this could have been any data file, but.
for the purpose of our example, we are going toThe code above is the implementation of what
be using a 32x32 dimensional bitmap file. We couldwe discussed about applying MAP_SCALE, which
have easily used a text file, and defined logic forallows us to scale the terrain to our likings. So, it
each word or letter to represent it graphically.Thebasically assigns the vertex coordinates for each
project also contains a good Windows frameworkgrid location, the MAP_SCALE factor, which is
that can be used for your other OpenGLmultiplying it with the grid location index based on
applications. The current project allows you tothe coordinate element. It extends along the X
rotate the camera using your mouse.Once again,and Z-axis, with the Y-Axis representing the
this is a simple approach to terrain generation,terrain height.The function is called after the
which can be a very difficult task in complexbitmap has been loaded into the memory from
environments.Background/Referencethe Initialize() function..
Since Computer Graphics is kind of an advanced.
topic, it is necessary to have at least some king.
of understanding and exposure to the concepts// Render
and theories in the field. However, this does not// desc: handles drawing of scene
mean that you will not be able to use thevoid Render()
following code or understand it. I have made it as{radians = float(PI*(angle-90.0f)/180.0f);//
simple as possible, and hopefully, it will give you acalculate the camera's position// multiplying by
good start, or some additional source ofmouseY makes the// camera get closer/farther
information that you can use for your projects.away with mouseYcameraX = lookX +
Also, please note that you will need to have asin(radians)*mouseY;cameraZ = lookZ +
good understanding of C/C++ programming.Somecos(radians)*mouseY;cameraY = lookY +
books I have used for learning Computer GraphicsmouseY / 2.0f;// calculate the camera look-at
and OpenGL programming:Books I used whilecoordinates// as the center of the terrain
attending the California Polytechnic University:maplookX = (MAP_X*MAP_SCALE)/2.0f;lookY =
OpenGL Programming Guide, or better know as150.0f;lookZ = -(MAP_Z*MAP_SCALE)/2.0f;//
the Red Book.clear screen and depth
Computer Graphics Using OpenGL, 2nd Edition.bufferglClear(GL_COLOR_BUFFER_BIT |
Books I used while attending the CaliforniaGL_DEPTH_BUFFER_BIT);glLoadIdentity();// set
Lutheran University:the camera positiongluLookAt(cameraX, cameraY,
OpenGL: A Premier, 2nd Edition.cameraZ,lookX, lookY, lookZ, 0.0, 1.0, 0.0);// set
Interactive Computer Graphics: A Top-Downthe current texture to the land
Approach Using OpenGL, 4th Edition.What is atextureglBindTexture(GL_TEXTURE_2D, land);//
Terrain?we are going to loop through all// of our terrain's
Some background information on a terrain anddata points,// but we only want to draw one
their uses in a game application: A terrain in antriangle// strip for each set along the x-axis.for
environment is one of the most critical(int z = 0; z < MAP_Z-1;
components in the scene that is being rendered. Itz++){glBegin(GL_TRIANGLE_STRIP);for (int x =
could easily be the largest 3D object in the0; x < MAP_X-1; x++){// for each vertex, we
project. Rendering the terrain can become acalculate// the grayscale shade color,// we set
daunting task, taking the most time to render in athe texture coordinate,// and we draw the
scene. To keep the terrain engine running in realvertex.// draw vertex 0glColor3f(terrain[x][z][1]
time can be a difficult task, and it requires some255.0f,terrain[x][z][1]/255.0f,terrain[x][z][1]
thought out processes and modeling for it to be255.0f);glTexCoord2f(0.0f,
sufficient.To be effective, the terrain needs to0.0f);glVertex3f(terrain[x][z][0],terrain[x][z][1],
meet a number of requirements, many of whichterrain[x][z][2]);// draw vertex
can be contradicting each other. A terrain should1glTexCoord2f(1.0f, 0.0f);glColor3f(terrain[x+1][z][1]
appear to be continuous to the end user, yet the255.0f,terrain[x+1][z][1]/255.0f,terrain[x+1][z][1]
mesh should be simplified or culled where possible,255.0f);glVertex3f(terrain[x+1][z][0],
to reduce the load on the graphics card.In aterrain[x+1][z][1],terrain[x+1][z][2]);// draw vertex
gaming system, for example, some engines draw2glTexCoord2f(0.0f, 1.0f);glColor3f(terrain[x][z+1][1]
the terrain just beyond the point a player can255.0f,terrain[x][z+1][1]/255.0f,terrain[x][z+1][1]
reach, and then use a terrain drawn onto a255.0f);glVertex3f(terrain[x][z+1][0],
skybox to simulate hills or mountains in theterrain[x][z+1][1],terrain[x][z+1][2]);// draw vertex
distance. The terrain should appear realistic to the3glColor3f(terrain[x+1][z+1][1]
setting for the environment, yet this can be255.0f,terrain[x+1][z+1][1]
taxing on the video card, and a balance needs to255.0f,terrain[x+1][z+1][1]
be maintained. Detail textures are often used255.0f);glTexCoord2f(1.0f,
close to the camera, allowing the areas further][1],terrain[x+1][z+1][2]);}glEnd();}// enable
off to be rendered more quickly.What is a HeightblendingglEnable(GL_BLEND);// enable read-only
Map?depth bufferglDepthMask(GL_FALSE);// set the
The first thing required for terrain rendering is ablend function// to what we use for
representation of the terrain's shape. While theretransparencyglBlendFunc(GL_SRC_ALPHA,
are a number of structures that can be used toGL_ONE);// set back to normal depth buffer
perform the job, the most widely used is themode (writable)glDepthMask(GL_TRUE);// disable
height map. Others include: NURBS, which can beblendingglDisable(GL_BLEND);glFlush();// bring
maintained through a number of control points,backbuffer to foregroundSwapBuffers(g_HDC);
and voxels, which allow for overhangs and}
caves.There is one drawback to a height map,.
and that is, for every point on the XZ-plane,.
there can only be one height value. You can see.
that this limits the representation of overhangsThe first thing you see in the Render() function is
and caves by a height map. This can bethe conversion of the angle into radians, by using
overcome by using two separate models.Anotherthe formula: radians = float(PI*(angle-90.0f)
drawback is that height maps take a large180.0f);. This makes it easier to compute the
amount of memory, as each height must becameraX, cameraY, and cameraZ positions using
represented. On the other hand, height maps lendthe sin() and cos() functions.The next block of
themselves to the creation of regular meshescode sets the look-at coordinates of the camera
easily. It is also easy to determine the height atat the center of the terrain. Then, we clear the
any given location, which is useful for collisionscreen and depth buffer using
against the terrain as well as laying dynamicglClear(GL_COLOR_BUFFER_BIT |
shadows onto the terrain.A height map isGL_DEPTH_BUFFER_BIT);. We set the camera
represented by a 2D array of values, where forposition based on the camera (X, Y, Z) values and
any point (X, Y, Z), the X and Z are the indexesthe look-at we computed.We then bind the
into the array, and the value of the array is the Ytexture using the
value which is equivalent to the height value.TheglBindTexture(GL_TEXTURE_2D, texture);
following is an example of such afunction. This tells OpenGL that we are going to
representation:int height[5][5] ={use that particular texture to apply to our
{ 0, 0, 1, 1, 2 },surfaces that will be drawn.So far, all the code
{ 0, 1, 2, 2, 3 },was just to setup the camera position and bind
{ 0, 1, 3, 2, 3 },the texture, the next block of code is what
{ 0, 1, 2, 1, 2 },actually draws the terrain and applies the texture
{ 0, 0, 1, 1, 1 } };The Approach!to the surface. We have two for loops which go
There are many advanced algorithms tothrough the 2D array we have created that
generate terrains; I am using a very simplestores the terrain data, and as we discussed
solution for the purpose of this project.In aearlier, we process four vertices at a time. In the
nutshell, I used a 32 x 32 grayscale bitmap toprocess, we calculate the grayscale shade color,
represent a height-field that is used to generatewe set the texture, and then we draw the
the terrain. The terrain itself is divided into a gridvertex.That is pretty much all you need to do to
of height values, the result of which is a meshgenerate a terrain, given a 24-bit bitmap file.Points
representing the terrain in the scene.We create aof Interest
grid of vertices that are spaced evenly apart butIf you are reading this, you most likely are
have varying heights, based on the height-fieldinterested in computer graphics and want to learn
data. The color value of each bit is used tomore about the techniques available to do really
determine the height value of each grid location; incool stuff. Computer graphics can be very
this case, for a 24-bit grayscale bitmap, thecomplex in theory, but thanks to libraries such as
values for the color range from 0 to 255.OnceOpenGL, the implementation of complex models
the bitmap has been read and the values loaded inscenes can be done easily. Upon writing this
memory, we have the data needed to representarticle, I got the latest issue of Dr. Dobb's Journal
the terrain. We also use a variable called a(June 2006, Issue No. 385), and to my surprise,
MAP_SCALE to allow us to scale the map up orthere is an article about OpenGL and Mobile
down. This is a scale factor; we use this to setDevices. It is under the name of OpenGL ES and
the distance between each height vertex. Thisit is a subset of OpenGL 1.3. That will make it
allows us to increase or decrease the size of thepossible to do real time 3D graphics on hand-held
terrain.When we actually assign the vertexdevices. Imagine the kind of nice looking
coordinates for each grid location, we need toapplications/games that can be developed for
apply the MAP_SCALE factor, which is multiplyingyour PDA or cell phones! Not all the functionality is
it with the grid location index based on theavailable due to the limitations of the hand-held
coordinate element, i.e.:Terrain[X][Z][0] =hardware. But I assume, in the near term future,
Float(X)*MAP_SCALE;you will be able to create as fascinating graphics
Terrain[X][Z][1] = (float)on the handhelds as you can on your regular
imageData[(Z*MAP_SCALE+X)*3];desktop machines.On another note, I am going to
Terrain[X][Z][2] = Float(Z)*MAP_SCALE;start working on a new article which will describe
The terrain map is represented in a grid of heightthe LoadBitmapFile(char *filename,
values, which is internally stored in a 2D array ofBITMAPINFOHEADER *bitmapInfoHeader) function.
vertex coordinates. It extends along the X andI am looking forward to hearing your comments
Z-axis, with the Y-Axis representing the terrainand input, for future articles.About Vahe
height.To render the terrain map, we useKaramianI have been programming since the age
GL_TRIANGLE_STRIP for each row of gridof 15. Started with BASIC on Apple II computers
values along the Z-axis. To render the terrainthen moved on to Pascal. I wrote the game of
correctly, we need to specify the point in aTetris using both languages on Apple II. At the
specific order.This requires us to start at the endage of 16 I got my first computer, and I started
of the row and move along the positive X-axis bytransferring the code over to Quick Basic. I then
drawing the vertices in a Zmoved into C/C++ and have been developing in
pattern:(*)==========>(*)///////////C/C++ until about 2 years ago when I switched
(*)=========>(*) ....Using the Codeover to C#.My interests are in the field of
I will only list the code that deals with the terrainComputer Graphics and Computer Vision. I am
generation here. There is more code in theworking on my graduate degree emphasizing on
project that you can look at. It is wellComputer Vision. I will try to be writing more
documented, so you shouldn't have any problems.articles in this field for future submissions.Currently
The solution was compiled using MS Visual StudioI am employed at a BioTech company in
2003, so you should be able to compile and run itCalifornia, and I work on interesting projects
easily. You will need to have the OpenGL librariesranging in many areas, except Computer Vision
and DLL, which I will also provide as a download Hence my graduate emphasis on the
option just in case you do not have them. Makesubject.You can find more C/C++ samples on my
life a little easier so you do not have to searchsite. There is a lot of good code for
for them online.So the majority of the code is forundergraduate Computer Science students.
preparing the windows to render the scene