Jump to content
  • Advertisement
Sign in to follow this  
Shamino

OpenGL Terrain Texturing

This topic is 4510 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Alright, I've been looking around for 2 days now looking at articles that are half done.. There really isn't any really good material on texturing a heightmap in opengl. I want some code snippets, not just a theory, I've read all of the theory, seen all of the procedural explainations, they stink. Can someone please attempt to walk me through texturing a terrain, with like, 1 texture? I'm not worried about two textures or more, I'm not worried about blending yet, just someone give me some insight as to how to do this.. Not a theoretical explaination! :) Please and thank you.

Share this post


Link to post
Share on other sites
Advertisement
I'm going to assume your map is made of quads, stored as a grid of vertices, say, a Vector3D class: grid[MAX_COLS][MAX_ROWS]
I'm also assuming that, if we're looking from the origin to your map, we're looking into the negative Z axis, with X as width, and Y as height.
For now, let's say your texture is stored at GLuint* texture

To draw a textured map, start iterating through the vertex grid




glBindTexture(GL_TEXTURE_2D, *texture); // bind the texture before you draw anything
glBegin(GL_QUADS);
for(int col = 0; col < MAX_COLS - 1; col++)
{
for(int row = 0; row < MAX_ROWS - 1; row++)
{

glTexCoord2f(1.0f, 1.0f); glVertex3f(grid[col + 1][row].x, grid[col + 1][row].y, grid[col + 1][row].z); // the top right corner
glTexCoord2f(0.0f, 1.0f); glVertex3f(grid[col][row].x, grid[col][row].y, grid[col][row].z); // the top left corner
glTexCoord2f(0.0f, 0.0f); glVertex3f(grid[col][row + 1].x, grid[col][row + 1].y, grid[col][row + 1].z); // bottom left
glTexCoord2f(1.0f, 0.0f); glVertex3f(grid[col + 1][row + 1].x, grid[col + 1][row + 1].y, grid[col + 1][row + 1].z); // bottom right


}
}
glEnd();



First off, note that you only iterate to MAX_COLS -1, because you're going to be looking 1 element away from your current position, so you do cover the entire grid.

Second, the order in which you're listing the vertices may seem weird, but listing them in counter-clockwise order makes it so OpenGL properly determines which side is GL_FRONT and which is GL_BACK

That code is basically what I'm using in my GL World terrain engine (Here) simplified a bit. Also, if you're using lighting, don't forget to specify the normals.

Share this post


Link to post
Share on other sites
Thanks alot for that lil snippet, here is my rendering code..


void RenderHeightMap(BYTE pHeightMap[]) // This Renders The Height Map As Quads
{
int X = 0, Y = 0; // Create Some Variables To Walk The Array With.
int x, y, z; // Create Some Variables For Readability

if(!pHeightMap) return; // Make Sure Our Height Data Is Valid

if(bRender) // What We Want To Render
glBegin( GL_QUADS ); // Render Polygons
else
glBegin( GL_LINES ); // Render Lines Instead

for ( X = 0; X < (MAP_SIZE-STEP_SIZE); X += STEP_SIZE )
for ( Y = 0; Y < (MAP_SIZE-STEP_SIZE); Y += STEP_SIZE )
{
// Get The (X, Y, Z) Value For The Bottom Left Vertex
x = X;
y = Height(pHeightMap, X, Y );
z = Y;

// Set The Color Value Of The Current Vertex
SetVertexColor(pHeightMap, x, z);

glVertex3i(x, y, z); // Send This Vertex To OpenGL To Be Rendered (Integer Points Are Faster)

// Get The (X, Y, Z) Value For The Top Left Vertex
x = X;
y = Height(pHeightMap, X, Y + STEP_SIZE );
z = Y + STEP_SIZE ;

// Set The Color Value Of The Current Vertex
SetVertexColor(pHeightMap, x, z);

glVertex3i(x, y, z); // Send This Vertex To OpenGL To Be Rendered

// Get The (X, Y, Z) Value For The Top Right Vertex
x = X + STEP_SIZE;
y = Height(pHeightMap, X + STEP_SIZE, Y + STEP_SIZE );
z = Y + STEP_SIZE ;

// Set The Color Value Of The Current Vertex
SetVertexColor(pHeightMap, x, z);

glVertex3i(x, y, z); // Send This Vertex To OpenGL To Be Rendered

// Get The (X, Y, Z) Value For The Bottom Right Vertex
x = X + STEP_SIZE;
y = Height(pHeightMap, X + STEP_SIZE, Y );
z = Y;

// Set The Color Value Of The Current Vertex
SetVertexColor(pHeightMap, x, z);

glVertex3i(x, y, z); // Send This Vertex To OpenGL To Be Rendered
}
glEnd();

glColor4f(1.0f, 1.0f, 1.0f, 1.0f); // Reset The Color



We are rendering the terrain with quads, I think we're already looping through each quad individually, so I'm guessing that this wouldn't be too difficult to implement what you just gave me in this bit of code, I'll give it a shot.

Share this post


Link to post
Share on other sites
If you know how to stretch a texture across a quad, then it is relatively straightforward to stretch it across a mesh. Both simply assign texture coordinates in the range 0.0 to 1.0 to the vertices. Two corners opposite each other in the single quad will have (0.0,0.0) and (1.0,1.0) respectively. The same thing with the terrain mesh. All of the vertices inbetween are in between 0.0 and 1.0.

Eg, the single quad would look something like this for the U and V texture coordinates


(0.0,1.0)-----(1.0,1.0)
| |
| |
| |
| |
| |
| |
(0.0,0.0)-----(1.0,0.0)


For a 5x5 mesh it would look like this:

0 1 2 3 4
0 (0.00,1.00)-----(0.25,1.00)-----(0.50,1.00)-----(0.75,1.00)-----(1.00,1.00)
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
1 (0.00,0.75)-----(0.25,0.75)-----(0.50,0.75)-----(0.75,0.75)-----(1.00,0.75)
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
2 (0.00,0.50)-----(0.25,0.50)-----(0.50,0.50)-----(0.75,0.50)-----(1.00,0.50)
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
3 (0.00,0.25)-----(0.25,0.25)-----(0.50,0.25)-----(0.75,0.25)-----(1.00,0.25)
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
4 (0.00,0.00)-----(0.25,0.00)-----(0.50,0.00)-----(0.75,0.00)-----(1.00,0.00)


So your render routine simply need to calculate the appropriate texture coordinate for the vertex it is currently processes. I do it like this:



terrain.size = 5;

// texture corrdinate variables
float a,b,c;

// render heightmap mesh
for ( int row = 0; row < (terrain.size-1); row++ ) { // X axis

// draw triangle strip
glBegin(GL_TRIANGLE_STRIP);

for ( int col = 0; col < terrain.size; col++ ) { // Z axis

// caclulate texture coordinates for this vertex
a = (float)row/(terrain.size-1);
b = (float)col/(terrain.size-1);
c = (float)(row+1)/(terrain.size-1);

// set first vertex normal
glNormal3f(terrain.CNormal[row][col].x,terrain.CNormal[row][col].y,terrain.CNormal[row][col].z);

// set texture coordinates for first vertex
if ( terrain.textureMode ) {
glMultiTexCoord2fARB( GL_TEXTURE0_ARB, a, b );
glMultiTexCoord2fARB( GL_TEXTURE1_ARB, a*terrain.detailRepeat, b*terrain.detailRepeat);
}

// draw first vertex
glVertex3f( (terrain.CPoint[row][col].x+terrain.step)*terrain.scale,
(terrain.CPoint[row][col].y+terrain.step)*terrain.scale,
(terrain.CPoint[row][col].z+terrain.step)*terrain.scale);

// set second vertex normal
glNormal3f(terrain.CNormal[row+1][col].x,terrain.CNormal[row+1][col].y,terrain.CNormal[row+1][col].z);

// set second vertex texture coordinates
if ( terrain.textureMode ) {
glMultiTexCoord2fARB( GL_TEXTURE0_ARB, c, b );
glMultiTexCoord2fARB( GL_TEXTURE1_ARB, c*terrain.detailRepeat, b*terrain.detailRepeat );
}

// draw second vertex
glVertex3f( (terrain.CPoint[row+1][col].x+terrain.step)*terrain.scale,
(terrain.CPoint[row+1][col].y+terrain.step)*terrain.scale,
(terrain.CPoint[row+1][col].z+terrain.step)*terrain.scale);
}

glEnd();
}




I use a triangle strip since they require less vertices to render. If you wanted to repeat the same texture for each quad, then you would simply use the coordinates for the single quad.

hth
F451

Share this post


Link to post
Share on other sites
I thought no matter what the tex coords were always

(1.0, 1.0) - Top Right
(0.0, 1.0) - Top Left
(0.0, 0.0) - Bottom Left
(1.0, 0.0) - Bottom Right

So no matter what the vertices we're working with are, we just need to know which one is the top right, top left, bottom left, and bottom right, then we can just set the tex coords accordingly..

For the top right vertice, we just do this...

Oh wait I just saw you said if you want to repeat a texture just repeat the coords for each quad...

That's what I'm gonna do :)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!