Featured Posts

8. Bump Mapping in GLSL8. Bump Mapping in GLSL Introduction Bump mapping is essential in todays computer games, and computer graphics in general. Would you like to know the best thing about it? It is extremely simple to implement. Bump mapping works...

Read more

Swiftless GLSL Shader DeveloperSwiftless GLSL Shader Developer Swiftless GLSL Shader Developer   Version 0.1a Currently Swiftless GLSL Shader Developer is in it's first public release, and is currently in alpha status, meaning it is not complete and may contain...

Read more

Wordpress Optimization Wordpress Website Optimizations Introduction Wordpress itself is a fairly wonderful tool. Since switching to it, I find it is a lot quicker to make changes to my website and it is also quicker to get...

Read more

36. OpenGL Framebuffers36. OpenGL Framebuffers Introduction Frame buffers are one of those mythical things that we have all heard of, but many beginner OpenGL developers avoid because there is not much information about them, and they can be confusing...

Read more

1. Terrain Class1. Terrain Class Terrain is one of those things that so far, hasn't been perfectly recreated in computer graphics. But it is almost there! Looking over a beautiful landscape can be one of the most amazing feelings in the...

Read more

  • Prev
  • Next

5. Terrain Textures

Posted on : 25-03-2010 | By : Swiftless | In : Terrain

Tags: , , , ,

4

Jump To:

heightfield.h Source
heightfield.cpp Source

main.cpp Source
Download

Heightfield.H File:

Another nice little adjustment to our heightfield.h file. We just need to assign a variable to hold our textures :-) I am calling this tID and at this point, is an array with just 2 positions, for now we will just be working with tID[0], but later on when we add normal mapping, we will be working with tID[1]:

// unsigned int tID[2];

Now lets move onto our heightfield.cpp file :-)

1.
2.
3.
4.

5.
6.
7.
8.
9.
10.
11.
12.
13.

14.
15.
16.

  #include <windows.h>

class SwiftHeightField {
    
private:
    

int hmHeight;
    
int hmWidth;
    

    
unsigned int tID[2];
    

public:
    
bool Create(char *hFileName, const int hWidth, const int hHeight);
    

    
void Render(void);
    

    
BYTE hHeightField[1024][1024];

};

Heightfield.CPP File:

The first change here that you will need to pay attention to, is the incorporation of jpeg.h. Just like in the ‘Loading a JPEG texture’ tutorial (coming soon), we will be using the IJG jpeg library to load our textures. So after we add the line:

// include "jpeg.h"

We need to load in our texture. I am doing this after we load in our heightfield, in our Create function. So I am adding the line:

// SwiftTextureJpeg(tID, "texture.jpg", 0);

Where texture.jpg is the texture that will stretch over our terrain. Next is where our texturing comes into play. Just like texturing any other primitive shape in OpenGL, we need to enable texturing and bind our texture. So in our Render function, right before anything else, I am adding the lines:

// glEnable(GL_TEXTURE_2D);

// glBindTexture(GL_TEXTURE_2D, tID[0]);

Which will enable texturing and then bind are texture respectively. To finish off this, we need to disable texturing when we are done with our terrain, so we call:

// glDisable(GL_TEXTURE_2D);

At the end of our Render function. Now we need to take a look at our texture coordinates. At the moment, we have no texture coordinates, so in this tutorial we are going to dynamically compute them on the fly. This sounds really technical but it isn’t really. At the X = 0 coordinate on the map, our U coordinate for our texture is 0, and at the X = Width coordinate, our U coordinate for our texture is X / Width.

So at:
X = 0, U = 0;

Z = 0, V = 0;

X = 1024, U = 1; (X / Width = 1024 / 1024 = 1)
Z = 1024, V = 1; (Z / Height = 1024 / 1024 = 1)

Taking this into practice, our rendering code will now look like this:

// glTexCoord2f((float)hMapX / hmWidth, (float)hMapZ / hmHeight);
// glVertex3f(hMapX, hHeightField[hMapX][hMapZ], hMapZ);

// glTexCoord2f((float)hMapX / hmWidth, (float)(hMapZ + 1) / hmHeight);
// glVertex3f(hMapX, hHeightField[hMapX][hMapZ + 1], hMapZ + 1);

// glTexCoord2f((float)(hMapX + 1) / hmWidth, (float)hMapZ / hmHeight);
// glVertex3f(hMapX + 1, hHeightField[hMapX + 1][hMapZ], hMapZ);

// glTexCoord2f((float)(hMapX + 1) / hmWidth, (float)(hMapZ + 1) / hmHeight);

// glVertex3f(hMapX + 1, hHeightField[hMapX + 1][hMapZ + 1], hMapZ + 1);

And that is all we need to change in our heightfield.cpp file. :-)

1.
2.
3.
4.

5.
6.
7.
8.
9.
10.
11.
12.
13.

14.
15.
16.
17.
18.
19.
20.
21.
22.

23.
24.
25.
26.
27.
28.
29.
30.
31.

32.
33.
34.
35.
36.
37.
38.
39.
40.

41.
42.
43.
44.
45.
46.
47.
48.
49.

50.
51.
52.
53.

  #include <stdio.h>
#include <glgl.h>

#include “jpeg.h”
#include “heightfield.h”

bool SwiftHeightField::Create(char *hFileName, const int hWidth, 
const int hHeight){
    

hmHeight = hHeight;
    
hmWidth = hWidth;
    

    
FILE *fp;
    

    
fp = fopen(hFileName, “rb”);
    

    
fread(hHeightField, 1, hWidth * hHeight, fp);
    

    
fclose(fp);
    

    
SwiftTextureJpeg(tID, “texture.jpg”, 0);
    

    
return true;
}

void SwiftHeightField::Render(void){
    
glEnable(GL_TEXTURE_2D);
    

glBindTexture(GL_TEXTURE_2D, tID[0]);
    

    
for (int hMapX = 0; hMapX < hmWidth; hMapX++){
        

for (int hMapZ = 0; hMapZ < hmHeight; hMapZ++){
            
glBegin(GL_TRIANGLE_STRIP);
            

glTexCoord2f((float)hMapX / hmWidth, (float)hMapZ / hmHeight);
            

glVertex3f(hMapX, hHeightField[hMapX][hMapZ], hMapZ);
            

            
glTexCoord2f((float)hMapX / hmWidth, (float)(hMapZ + 1) / hmHeight) ;

            
glVertex3f(hMapX, hHeightField[hMapX][hMapZ + 1], hMapZ + 1);
            

            
glTexCoord2f((float)(hMapX + 1) / hmWidth, (float)hMapZ / hmHeight);

            
glVertex3f(hMapX + 1, hHeightField[hMapX + 1][hMapZ], hMapZ);
            

            
glTexCoord2f((float)(hMapX + 1) / hmWidth, (float)(hMapZ + 1) / hmHeight);

            
glVertex3f(hMapX + 1, hHeightField[hMapX + 1][hMapZ + 1], hMapZ + 1);
            

glEnd();
        
}
    
}
    

    
glDisable(GL_TEXTURE_2D);
}

Main.CPP File:

And guess what?! No changes need to be made to our main.cpp file :-)

Check out the next tutorial on rendering the heightfield using VBO’s (Vertex Buffer Objects) for speed optimizations here :-)

If you have any questions, just email me at swiftless@gmail.com

1.
2.
3.
4.
5.

6.
7.
8.
9.
10.
11.
12.
13.
14.

15.
16.
17.
18.
19.
20.
21.
22.
23.

24.
25.
26.
27.
28.
29.
30.
31.
32.

33.
34.
35.
36.
37.
38.
39.
40.
41.

42.
43.
44.
45.
46.
47.
48.
49.
50.

51.
52.
53.
54.
55.
56.
57.
58.
59.

60.
61.
62.
63.
64.
65.
66.
67.
68.

69.
70.
71.
72.
73.
74.
75.
76.
77.

78.
79.
80.
81.
82.
83.
84.
85.
86.

87.
88.
89.
90.
91.
92.
93.
94.
95.

96.
97.
98.
99.
100.
101.
102.
103.
104.

105.
106.
107.
108.
109.
110.
111.
112.
113.

114.
115.
116.
117.
118.
119.
120.
121.
122.

123.
124.
125.
126.
127.
128.
129.

  #include <GL/glew.h>

#include <GL/gl.h>
#include <GL/glext.h>
#include <GL/GLUT.h>

#include <math.h>

#include <windows.h>
#include <stdio.h>

#include <string.h>
#include <fstream>
#include <assert.h>

#include “heightfield.h”

#pragma comment(lib,“glew32.lib”)

float xpos = 851.078, ypos = 351.594, zpos = 281.033, xrot = 758, yrot = 238,
 angle=0.0;

float lastx, lasty;

float bounce;
float cScale = 1.0;

SwiftHeightField hField;

void camera (void) {
    
int posX = (int)xpos;
    

int posZ = (int)zpos;
    

    
glRotatef(xrot,1.0,0.0,0.0);
    
glRotatef(yrot,0.0,1.0,0.0);
    

glTranslated(-xpos,-ypos,-zpos);
}

void display (void) {
    

glClearColor (0.0,0.0,0.0,1.0);
    
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    

glLoadIdentity();
    
camera();
    

    
hField.Render();
    

    

glutSwapBuffers();
}

void Init (void) {
    
glEnable(GL_DEPTH_TEST);
    

glDepthFunc(GL_LEQUAL);
    

    
hField.Create(“heightfield.raw”, 1024, 1024);
}

void mouseMovement(int x, int y) {
    
int diffx=x-lastx;
    

int diffy=y-lasty;
    
lastx=x;
    
lasty=y;
    
xrot += (float) diffy;
    

yrot += (float) diffx;
}

void keyboard (unsigned char key, int x, int y) {
    

    
if (key == ‘w’)
    
{
        
float xrotrad, yrotrad;
        

yrotrad = (yrot / 180 * 3.141592654f);
        
xrotrad = (xrot / 180 * 3.141592654f);
        

xpos += float(sin(yrotrad)) * cScale;
        
zpos -= float(cos(yrotrad)) * cScale;
        

ypos -= float(sin(xrotrad)) ;
        
bounce += 0.04;
    

}
    

    
if (key == ‘s’)
    
{
        
float xrotrad, yrotrad;
        

yrotrad = (yrot / 180 * 3.141592654f);
        
xrotrad = (xrot / 180 * 3.141592654f);
        

xpos -= float(sin(yrotrad)) * cScale;
        
zpos += float(cos(yrotrad)) * cScale;
        

ypos += float(sin(xrotrad));
        
bounce += 0.04;
    

}
    

    
if (key == ‘d’)
    
{
        
float yrotrad;
        

yrotrad = (yrot / 180 * 3.141592654f);
        
xpos += float(cos(yrotrad)) * cScale;
        

zpos += float(sin(yrotrad)) * cScale;
    
}
    

    
if (key == ‘a’)
    
{
        
float yrotrad;
        

yrotrad = (yrot / 180 * 3.141592654f);
        
xpos -= float(cos(yrotrad)) * cScale;
        

zpos -= float(sin(yrotrad)) * cScale;
    
}
    

}

void reshape (int w, int h) {
    
glViewport (0, 0, (GLsizei)w, (GLsizei)h);
    

glMatrixMode (GL_PROJECTION);
    
glLoadIdentity ();
    
gluPerspective (60, (GLfloat)w / (GLfloat)h, 1.0, 1000.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);
    
glutKeyboardFunc(keyboard);
    
glutPassiveMotionFunc(mouseMovement);
    

glutMainLoop ();
    
return 0;
} 

Download:

Download heightfield.h Source Code for this Tutorial

Download heightfield.cpp Source Code for this Tutorial

Download main.cpp Source Code for this Tutorial

Download heightfield.raw for this Tutorial

Download texture.jpg for this Tutorial

Download jpeg.h Source Code for this Tutorial

Download jpeg.cpp Source Code for this Tutorial

Downlaod jpeglib.zip for this Tutorial

VN:F [1.9.3_1094]
Please rate so I know where to improve the site. 1 means needs a lot of improvement, 10 means perfect. If you leave a low rating, please state why. I don't want people just coming to bash the site.
Rating: 10.0/10 (2 votes cast)
VN:F [1.9.3_1094]
Rating: 0 (from 0 votes)
5. Terrain Textures, 10.0 out of 10 based on 2 ratings

Related posts:

  1. 4. Terrain Triangle Strips
  2. 3. Terrain Rendering
  3. 7. Terrain Level Of Detail
  4. 2. Terrain Loading
  5. 6. Terrain Vertex Buffer Objects

Comments (4)

Hey,

If you are having problems with libjpeg, make sure you download and include the jpeg.h and jpeg.cpp files above, I forgot to add them into the code sections and they are required as they are the interface between the application and libjpeg.

If you are still having problems with libjpeg specifically, I will refer you to http://www.ijg.org/ where there are newer versions.

I didn’t have any problems placing the libjpeg library and headers into my compiler directories (Windows with Visual Studio), and getting everything to run.

@Toychickenofthinking, If it cannot open the include file, then you either have it in the wrong directory, or are not referencing it correctly in jpeg.h.

Cheers,
Swiftless

VN:F [1.9.3_1094]
Rating: 0.0/5 (0 votes cast)
VN:F [1.9.3_1094]
Rating: 0 (from 0 votes)

oh finally, i tried other format (TGA) and it is run

VA:F [1.9.3_1094]
Rating: 0.0/5 (0 votes cast)
VA:F [1.9.3_1094]
Rating: 0 (from 0 votes)

Hi, i’m still newbie on opengl. Btw, after following your tutorial i experienced compile error with jpeglib. I can’t solve it, can you help me identify what actually happened?

Compiler: Default compiler
Building Makefile: “C:\Users\Oscar\Documents\Tugas\Grafkom\FinalProject\Makefile.win”
Executing make…
make.exe -f “C:\Users\Oscar\Documents\Tugas\Grafkom\FinalProject\Makefile.win” all
g++.exe -c heightfield.cpp -o heightfield.o -I”C:/Dev-Cpp/lib/gcc/mingw32/3.4.2/include” -I”C:/Dev-Cpp/include/c++/3.4.2/backward” -I”C:/Dev-Cpp/include/c++/3.4.2/mingw32″ -I”C:/Dev-Cpp/include/c++/3.4.2″ -I”C:/Dev-Cpp/include”

In file included from C:/Dev-Cpp/include/c++/3.4.2/backward/iostream.h:31,
from C:/Dev-Cpp/include/jpeglib.h:41,
from jpeg.h:1,
from heightfield.cpp:3:
C:/Dev-Cpp/include/c++/3.4.2/backward/backward_warning.h:32:2: warning: #warning This file includes at least one deprecated or antiquated header. Please consider using one of the 32 headers found in section 17.4.1.2 of the C++ standard. Examples include substituting the header for the header for C++ includes, or instead of the deprecated header . To disable this warning use -Wno-deprecated.
In file included from jpeg.h:1,
from heightfield.cpp:3:
C:/Dev-Cpp/include/jpeglib.h:630: error: `boolean’ does not name a type
C:/Dev-Cpp/include/jpeglib.h:646: error: `boolean’ does not name a type

C:/Dev-Cpp/include/jpeglib.h:696: error: `boolean’ does not name a type
C:/Dev-Cpp/include/jpeglib.h:790: error: `boolean’ does not name a type
C:/Dev-Cpp/include/jpeglib.h:806: error: `boolean’ does not name a type
C:/Dev-Cpp/include/jpeglib.h:857: error: `boolean’ does not name a type
C:/Dev-Cpp/include/jpeglib.h:858: error: `boolean’ does not name a type
C:/Dev-Cpp/include/jpeglib.h:859: error: `boolean’ does not name a type
C:/Dev-Cpp/include/jpeglib.h:860: error: `boolean’ does not name a type
C:/Dev-Cpp/include/jpeglib.h:874: error: `boolean’ does not name a type
C:/Dev-Cpp/include/jpeglib.h:884: error: `boolean’ does not name a type
C:/Dev-Cpp/include/jpeglib.h:900: error: `boolean’ does not name a type
C:/Dev-Cpp/include/jpeglib.h:950: error: `boolean’ does not name a type
C:/Dev-Cpp/include/jpeglib.h:974: error: `boolean’ does not name a type
C:/Dev-Cpp/include/jpeglib.h:975: error: `boolean’ does not name a type
C:/Dev-Cpp/include/jpeglib.h:978: error: `boolean’ does not name a type
C:/Dev-Cpp/include/jpeglib.h:979: error: `boolean’ does not name a type
C:/Dev-Cpp/include/jpeglib.h:981: error: `boolean’ does not name a type

C:/Dev-Cpp/include/jpeglib.h:984: error: `boolean’ does not name a type
C:/Dev-Cpp/include/jpeglib.h:987: error: `boolean’ does not name a type
C:/Dev-Cpp/include/jpeglib.h:988: error: `boolean’ does not name a type
C:/Dev-Cpp/include/jpeglib.h:989: error: `boolean’ does not name a type
C:/Dev-Cpp/include/jpeglib.h:1076: error: `boolean’ does not name a type
C:/Dev-Cpp/include/jpeglib.h:1077: error: `boolean’ does not name a type
C:/Dev-Cpp/include/jpeglib.h:1088: error: `boolean’ does not name a type
C:/Dev-Cpp/include/jpeglib.h:1095: error: `boolean’ does not name a type
C:/Dev-Cpp/include/jpeglib.h:1098: error: `boolean’ does not name a type
C:/Dev-Cpp/include/jpeglib.h:1256: error: ISO C++ forbids declaration of `boolean’ with no type
C:/Dev-Cpp/include/jpeglib.h:1256: error: expected `;’ before ‘(‘ token

C:/Dev-Cpp/include/jpeglib.h:1267: error: `boolean’ does not name a type
C:/Dev-Cpp/include/jpeglib.h:1273: error: ISO C++ forbids declaration of `boolean’ with no type
C:/Dev-Cpp/include/jpeglib.h:1273: error: expected `;’ before ‘(‘ token
C:/Dev-Cpp/include/jpeglib.h:1275: error: ISO C++ forbids declaration of `boolean’ with no type
C:/Dev-Cpp/include/jpeglib.h:1275: error: expected `;’ before ‘(‘ token
C:/Dev-Cpp/include/jpeglib.h:1311: error: `boolean’ has not been declared
C:/Dev-Cpp/include/jpeglib.h:1311: error: ISO C++ forbids declaration of `pre_zero’ with no type
C:/Dev-Cpp/include/jpeglib.h:1317: error: `boolean’ has not been declared
C:/Dev-Cpp/include/jpeglib.h:1317: error: ISO C++ forbids declaration of `pre_zero’ with no type
C:/Dev-Cpp/include/jpeglib.h:1324: error: `boolean’ has not been declared
C:/Dev-Cpp/include/jpeglib.h:1324: error: ISO C++ forbids declaration of `writable’ with no type
C:/Dev-Cpp/include/jpeglib.h:1329: error: `boolean’ has not been declared

C:/Dev-Cpp/include/jpeglib.h:1329: error: ISO C++ forbids declaration of `writable’ with no type
C:/Dev-Cpp/include/jpeglib.h:1352: error: ISO C++ forbids declaration of `boolean’ with no type
C:/Dev-Cpp/include/jpeglib.h:1352: error: typedef `boolean’ is initialized (use __typeof__ instead)
C:/Dev-Cpp/include/jpeglib.h:1352: error: `jpeg_marker_parser_method’ was not declared in this scope
C:/Dev-Cpp/include/jpeglib.h:1352: error: expected `,’ or `;’ before ‘(‘ token
C:/Dev-Cpp/include/jpeglib.h:1554: error: `jpeg_marker_parser_method’ has not been declared
C:/Dev-Cpp/include/jpeglib.h:1554: error: ISO C++ forbids declaration of `routine’ with no type

make.exe: *** [heightfield.o] Error 1

Execution terminated

VA:F [1.9.3_1094]
Rating: 0.0/5 (0 votes cast)
VA:F [1.9.3_1094]
Rating: 0 (from 0 votes)

Awesome tutorial, just like your OpenGL tutorials :) I couldn’t figure out what to do with the jpeglib.zip file. I inserted the header and library into the project file -also tried to add them to the VC/include/GL, and lib sections- but I keep getting the error “Cannot open include file: ‘jpeglib.h’: No such file or directory.” how can I solve this ? Thanks.

VA:F [1.9.3_1094]
Rating: 0.0/5 (0 votes cast)
VA:F [1.9.3_1094]
Rating: 0 (from 0 votes)

Write a comment

Improve the web with Nofollow Reciprocity.