Public Group

# Terrain normals causing diamond-shaped artifacts?

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

## Recommended Posts

I get diamond shaped artifacts when i calculate my terrain normals and apply lighting. I don't know why but they only appear on the backside of a hill, not the front, I checked to see if the normals are being correctly by setting all vertex heights to zero, and i get a correct normal (0, 1, 0).

Front side - no problems (that i know of)

Back side

And here's how i calculate my normals:

//===================================================================================================== // Calculate terrain normals //===================================================================================================== void Framework::CalculateNormals() { struct Vertex { D3DXVECTOR3 pos; D3DXVECTOR3 nor; }; Vertex* pVertices = (Vertex*)mTerrain->mVertices; for (int j = 0; j < mTerrain->mLength; j++) { for (int i = 0; i < mTerrain->mWidth; i++) { int count = 0; D3DXVECTOR3 sum(0, 0, 0); int triPerWidth = (mTerrain->mWidth-1) * 2; // bottom faces if (j > 0) { int index = (j-1) * triPerWidth + (i-1)*2; // bottom left 1 and bottom left 2 if (i > 0) { sum += CalcFaceNormal(index); sum += CalcFaceNormal(index + 1); count += 2; } // bottom right face if (i < mTerrain->mWidth-1) { sum += CalcFaceNormal(index + 2); count += 1; } } // upper faces if (j < mTerrain->mLength-1) { int index = j * triPerWidth + (i-1)*2 + 1; // upper left if (i > 0) { sum += CalcFaceNormal(index); count += 1; } // upper right 1 and upper right 2 if (i < mTerrain->mWidth-1) { sum += CalcFaceNormal(index + 1); sum += CalcFaceNormal(index + 2); count += 2; } } // Calculate the average and normalize sum /= count; D3DXVECTOR3* result = &pVertices[j * mTerrain->mWidth + i].nor; D3DXVec3Normalize(result, &sum); } } mTerrain->UpdateVertexBuffer(mRenderer); } //===================================================================================================== // Calculate the normal for the triangle with the given index //===================================================================================================== D3DXVECTOR3 Framework::CalcFaceNormal(int Index) { D3DXVECTOR3 Normal; struct Vertex { D3DXVECTOR3 pos; D3DXVECTOR3 nor; }; Vertex* pVertices = (Vertex*)mTerrain->mVertices; USHORT* pIndices = (USHORT*)mTerrain->mIndices; Vertex* v0 = &pVertices[ pIndices[Index*3+0] ]; Vertex* v1 = &pVertices[ pIndices[Index*3+1] ]; Vertex* v2 = &pVertices[ pIndices[Index*3+2] ]; D3DXVECTOR3 edge1 = v0->pos - v1->pos; D3DXVECTOR3 edge2 = v0->pos - v2->pos; D3DXVec3Cross(&Normal, &edge1, &edge2); return Normal; }

##### Share on other sites
I disabled lighting and instead returned the normal as the pixel colour, and the artifacts are still there. So that rules out all the lighting calculations as the culprit.

Also it turns out that the front side has the same artifacts, only they're harder to see.

##### Share on other sites
Those artifacts look "correct"; if one vert has too different a lighting result than the others in a quad, you're going to notice the interpolation, which will make the choice of triangulation visible.

One possible fix is to smooth the normals -- e.g. after calculating all of the vertex normals, calculate a new set of normals by, for each vert averaging the original normals in the surrounding area.

##### Share on other sites
So for a vertex i have to first average the adjacent face normals, then average the averaged adjacent vertex normals?

##### Share on other sites
I did what you said but the terrain is too smooth now. The normals in the first screenshot look perfect except for those diamonds. Is there any other way to get rid of them?

##### Share on other sites
You can use different weights during the smoothing process to achieve a balance between too-smooth and not-smooth-enough.

In terms of image processing, you're basically implementing a blur filter - which has endless variations.

##### Share on other sites
Hello

There's a generic solution that is to ponderate the normals with the triangle areas (more a triangle is big, more it contributes to the per-vertex normal).

I've implemented this like that :
- computation of unormalized per-face normal (so that its norm is 2*Area(triangle)) [see cross product properties]
- then simply average these normals according to adjacency data (the ponderation is already done) (and normalize the obtained normal) to get desired per-vertex normal

Here's a good documentation on the 'per-vertex normal' subject : http://www.emeyex.co...rtexNormals.pdf

Nico

1. 1
2. 2
3. 3
Rutin
15
4. 4
5. 5

• 13
• 26
• 10
• 11
• 9
• ### Forum Statistics

• Total Topics
633730
• Total Posts
3013579
×