5. Terrain Textures
Jump To:
heightfield.h Source
heightfield.cpp Source
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. 14. |
#include <windows.h>
class SwiftHeightField { int hmHeight; public: }; |
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. 14. 23. 32. 41. 50. |
#include <stdio.h> #include <gl\gl.h> #include “jpeg.h” bool SwiftHeightField::Create(char *hFileName, const int hWidth, hmHeight = hHeight; void SwiftHeightField::Render(void){ glBindTexture(GL_TEXTURE_2D, tID[0]); for (int hMapZ = 0; hMapZ < hmHeight; hMapZ++){ glTexCoord2f((float)hMapX / hmWidth, (float)hMapZ / hmHeight); glVertex3f(hMapX, hHeightField[hMapX][hMapZ], hMapZ); glEnd(); |
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. 15. 24. 33. 42. 51. 60. 69. 78. 87. 96. 105. 114. 123. |
#include <GL/glew.h>
#include <GL/gl.h> #include <math.h> #include <windows.h> #include <string.h> #include “heightfield.h” #pragma comment(lib,“glew32.lib”) float xpos = 851.078, ypos = 351.594, zpos = 281.033, xrot = 758, yrot = 238, float lastx, lasty; float bounce; SwiftHeightField hField; void camera (void) { int posZ = (int)zpos; glTranslated(–xpos,–ypos,–zpos); void display (void) { glClearColor (0.0,0.0,0.0,1.0); glLoadIdentity(); glutSwapBuffers(); void Init (void) { glDepthFunc(GL_LEQUAL); void mouseMovement(int x, int y) { int diffy=y–lasty; yrot += (float) diffx; void keyboard (unsigned char key, int x, int y) { yrotrad = (yrot / 180 * 3.141592654f); xpos += float(sin(yrotrad)) * cScale; ypos –= float(sin(xrotrad)) ; } yrotrad = (yrot / 180 * 3.141592654f); xpos –= float(sin(yrotrad)) * cScale; ypos += float(sin(xrotrad)); } yrotrad = (yrot / 180 * 3.141592654f); zpos += float(sin(yrotrad)) * cScale; yrotrad = (yrot / 180 * 3.141592654f); zpos –= float(sin(yrotrad)) * cScale; } void reshape (int w, int h) { glMatrixMode (GL_PROJECTION); glMatrixMode (GL_MODELVIEW); int main (int argc, char **argv) { glutInit(&argc, argv); glutInitWindowSize(500, 500); Init(); glutReshapeFunc(reshape); glutMainLoop (); |
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