About Textured Smooth Terrain Surfaces...

Hi Everyone,

I am trying to get a good looking textured smooth terrain surface on my Opengl application. I applied triangle_strip,texture-mapping and normals to the terrain but it looks like this,
http://picasaweb.google.com/muratgozu/OpenglIssues# (non-smooth)

How can I get a smooth textured terrain surface like this,
http://picasaweb.google.com/muratgozu/OpenglIssues# (smooth)?

I am using 257x257 Height-map for the terrain heights and 128x128 rock BMP for texture mapping. I am using a scale factor 200 to enlarge the terrain. But my terrain looks like crisp shape and you can see the rectangle areas. What should I do to get a smooth surface?

Thanks
Murat Gozu

Your lighting model is not precise enough. OpenGL simply requires vertex normals to make smooth lighting transitions.

First, you’ll have to compute each face’ normal. Let’s assume you have a triangle ABC. Chosse two sides : AB and BC. Take their product ( can’t remember the english term right now, but it’s not the dot product, it’s the other one ), and you’ll get a vector that is perpendicular to both of them : the normal of the triangle. Renormalize it.

Then you need vertex normals. It doesn’t really makes sense mathematically, but think of it as the interpolation of the faces normals.
For each vertex, just take the average of the normals of every face to which the vertex belongs. You can now destroy faces normals and use your vertex normals using glNormal or by binding it to your VBO.

Take their product ( can’t remember the english term right now, but it’s not the dot product, it’s the other one )

It is “cross product”. :slight_smile:

hey, are you definiing the nature of the terrain manually by vertices? I want to learn how to make terrain like you have. How is it done? Do we need a game engine ?

your texture coordinates look wrong.
also looks like flat shading is used.
for fixed function pipeline:
glShadeMode(GL_SMOOTH); // activate linear interpolation across triangle vertices

baconbeastnz > Like redbarm said, the terrain is built from a height map which is no more than a gray scale texture. To create the terrain, you just need to create a grid, generate texture coordinates for each vertex and fetch texture color at these coordinates. This would give you the vertex elevation.

_NK47 > this is clearly a normal problem. glShadeModel(GL_SMOOTH); would just enables color interpolation in a triangle, which is the default state.

ok I see I see. So in creating a massive world like in WoW. Would the tools developer make a program which allows a ‘level creator’ to make the terrain entirely from a GUI?

And the complexity behind the program which generates the terrain, would just be using heightmaps?

@redbarm
just for checking maybe glEnable(GL_NORMALIZE) would help.
better to generate normals on your own though.

@baconbeastnz
not all terrains are generated from heightmaps. those are all static as long as the image is static.
you can use also diamond-square alogrithm to produce slightly random ones or just load a model file.

And no, the complexity of terrain rendering is not reduced to heightmaps. A basic terrain can be generated from this kind of map but generally, there are behind, many complex algorithms to manage for example level of detail (LOD), texture mapping like megatexturing and others.

Taking, the WoW 3D engine as an example, you can see that terrain geometry in the background is moving (morphing) because the engine adapts the geometry complexity related to the distance from the viewer.
More general information here.

About the terrain morphing, read from page 51 of
http://s08.idav.ucdavis.edu/olick-current-and-next-generation-parallelism-in-games.pdf
it’s very interesting, and I guess not too hard to make with terrains. (but for generic meshes it can be hell, I guess)

Ah, and about recomputing normals, I guess this will be mathematically OK:


#define NUM_VERTS 4225
#define NUM_TRIANGLES 3000
vec3 vertices[NUM_VERTS]; // initialized with your mesh data
int triangles[NUM_TRIANGLES*3]; // initialized with your mesh data, indices into vertices[]

vec3 normals[NUM_VERTS];  // we will be computing this
int  numTrisPerNormal[NUM_VERTS];

void ComputeNormals(){
	int i;
	for(i=0;i<NUM_VERTS;i++){
		normals[i] = vec3(0,0,0);
		numTrisPerNormal[i]=0;
	}
	for(i=0;i<NUM_TRIANGLES;i++){
		int index0 = triangles[i*3+0];
		int index1 = triangles[i*3+1];
		int index2 = triangles[i*3+2];
		vec3 v0 = vertices[index0];
		vec3 v1 = vertices[index1];
		vec3 v2 = vertices[index2];
		
		vec3 edge1 = v0 - v1;
		vec3 edge2 = v2 - v1; // or is it = v1-v2
		
		vec3 norm = cross(edge1,edge2);
		norm.normalize();
		normals[i]+=norm;
	}
	for(i=0;i<NUM_VERTS;i++){
		int num = numTrisPerNormal[i];
		if(num){
			normals[i] /= num;
			normals[i].normalize();
		}else{
			normals[i] = vec3 (0,1,0); // just in case
		}
	}
}

thanks guys.

very interesting stuff…

Hi Again Everyone,

Thank you very much for your help. I have been working for 3 days for calculating the “normal vectors” and finally created a code. Yeah with this the scene really improves a lot.
Look at this,
http://picasaweb.google.com/muratgozu/OpenglIssues# (using with vertex normals )

But still, you can see the shapes of the triangles on the surface. Although I used the glShadeModel(GL_SMOOTH), it is not smooth and flat shading continues. Look at the wired shape of the surface,
http://picasaweb.google.com/muratgozu/OpenglIssues# (my surface wired shape)

Anyway, I tried creating a surface with the program, 3DMax, then exported to my code. Look at this,
http://picasaweb.google.com/muratgozu/OpenglIssues# (surface created eith 3dmax)
As you see the the wired shape of the surface is so smooth.It looks like created with curves.

Which method or algorithm can we use to make the flat shaded surface smoother, and approach to a curve shape?

Thanks

BTW your links are all the same.
Smooth saheding is achived by sending the same normal to al vertices that are at the same place.
let’s say you have 2 triangles :
tri1 : vert1 vert2 vert3
tri2 : vert4 vert5 vert6

lets say the vertices 2 and 4 are joined, same for 3 and 6, to make a smooth shaded quad.
Then you must send the same normal n2 for verts 2 and 4.
And the same normal n3 for verts 3 and 6.