Something's wrong with my terrain's normals

Started by
8 comments, last by paic 18 years, 9 months ago
Hi, here is a screenshot of my terrain (without the texture so you can see the problem better) As you see, we can see the grid. I don't know why. This is the code I use to compute each vertex normal :

D3DXVECTOR3 normal;
float h0 = height[x][y + 1] - height[x][y - 1];
float h1 = height[x + 1][y] - height[x - 1][y];
D3DXVECTOR3 cross(-h1 * resolution, 2 * resolution, -h0 * resolution);
D3DXVec3Normalize(&normal, &cross);



where resolution is the space between 2 vertices (in the horizontal plane) ... At first, I thought it was because I took 2 vectors aligned on the grid, but the problem is the same when I take the diagonals, and even when I compute the average of both ! I've read some posts here on gamedev and a good one on flipcode, but they don't seem to have this kind of problem :/ So if anyone has a suggestion ... ^^ [Edited by - paic on June 29, 2005 2:43:32 AM]
Advertisement
Well, this what I've done before...

You need to calculate the face normals first, this can be done using a simple cross product. Once done, each of the vertex normals is the average of the 6 surrounding faces, as the structure of the mesh is:



Sort of anyway.

So essentially, calculate the normal of each of those triangles, then average them to get the normal for the centre vertex.

EDIT: Argh! Damn ASCII art doesn't want to work, newlines keep getting removed. Replaced with bad photoshop art instead.
If at first you don't succeed, redefine success.
Quote:Original post by python_regious
Well, this what I've done before...

Actualy paic's method with finite differences/sobel is generaly better.

Your normals are just OK. The problem comes form the way your grid is divided in triangles. Since normal is interpolated across each triangle the result is actually correct but the visual result is quite weird. You might get better looking results if you use grid like this:
*--*--*--*..| /|\ | /||/ | \|/ |*--*--*--*..|\ | /|\ || \|/ | \|*--*--*--*..
You should never let your fears become the boundaries of your dreams.
Quote:Original post by _DarkWIng_
Quote:Original post by python_regious
Well, this what I've done before...

Actualy paic's method with finite differences/sobel is generaly better.

Your normals are just OK. The problem comes form the way your grid is divided in triangles. Since normal is interpolated across each triangle the result is actually correct but the visual result is quite weird. You might get better looking results if you use grid like this:
*--*--*--*..| /|\ | /||/ | \|/ |*--*--*--*..|\ | /|\ || \|/ | \|*--*--*--*..


Yes thats right plus then you are only computing 4 face normals for each vertex so the computation of the normals will be a little faster (though not much of an issue as it is a precomputation, but never hurts!) Plus you don't have to tesselate the mesh this way, you can tesselate it in you usual manner (probably with triangle strips) and just use the setup that _DarkWIng_ shows above for computing the normals.

Quote:Original post by _DarkWIng_
Actualy paic's method with finite differences/sobel is generaly better.


Yeah I figured he was doing something like that.
If at first you don't succeed, redefine success.
As _DarkWIng_ said. However you probably don't need to worry too much about this as as soon as you slap a texture down on the landscape you won't be able to see the grid like pattern any more. The eye is good at exagerating changes in colour and you've got pretty much the worst case there - as soon as your texture breaks up the large flat gradients it'll all go away.
hi, thx for the replies

_DarkWing_ : I'll try the grid setup you just mentioned, thx. But you also mentioned finite differences/sobel ... what's that ? I know sobel filter (the basics) but I only heard about finite differences. How those 2 things can be used to compute normals ????

python_regious : That would be good for a precomputation, but I also have to compute them on the fly (only a few normals each frame, related to geometry clipmap)

OrangyTang : I really don't like leaving it like that. Plus, I use geometry mipmap, and on the transition area between 2 clipmaps, I need to interpolate normals, and I currently still have some pop ups there. I'm pretty sure the problem might be solved (at least partially) by correcting these artefacts.

Edit : Ok, I tried to generate my grid like DarkWing said ... but I must be making something wrong :/ I use a big triangle strip. Here's the code to generate it :

for (int y = minY; y < maxY; y++){   // add the second vertex to add the degenerated triangle   // between each "lines". When y == minY, this could be   // skipped.   index[i++] = (y + (minX % 2)) * m_ClipMapSize + minX;   for (int x = minX; x <= maxX; x++)   {      index[i++] = (y + (x % 2)) * m_ClipMapSize + x;      index[i++] = (y + ((x + 1) % 2)) * m_ClipMapSize + x;   }   // add the first vertex to add the degenerated triangle   // between each "lines". When y == maxY - 1, this could   // be skipped   index[i++] = (y + ((maxX + 1) % 2)) * m_ClipMapSize + maxX;}


I am totally blind or this isn't the way to generate a strip with _DarkWing_'s setup ?

Edit2 : I was totally blind ^^

[Edited by - paic on June 29, 2005 4:42:23 AM]
Quote:Original post by paic
_DarkWing_ : I'll try the grid setup you just mentioned, thx. But you also mentioned finite differences/sobel ... what's that ? I know sobel filter (the basics) but I only heard about finite differences. How those 2 things can be used to compute normals ????

The way you are computing normals now is derived from finite differences/sobel operator.

One way or soloving this is not to use per-vertex normals but a big normal-map texture (one texel = one vertex). This solves trnasition of geometry mipmaps very smoothly.
You should never let your fears become the boundaries of your dreams.
Arf, I justed posted when you did ^^
I already thought about using normal maps, but at the time, I discarded that choice ... I don't remember why though -__-
Well, I'll try to see if I can implement that quickly, but before, I want to generate the grid setup you mentioned ! Because using a normal map won't solve the artefacts of the screenshot at all. It will just allow me to use a more accurate way of computing normals (as I wouldn't need any more runtime computation)

Eidt : I remember why I didn't want to use normal maps : That would force me to do the lighting in the pixel shader, and as I want my program to run even on quite low end machines, I didn't want to use too much pixel shaders.
Oups, I just realize that generating such a grid setup with triangle strips is impossible ^^'''
I'll try the normal map now then ^^

This topic is closed to new replies.

Advertisement