Jump to content
  • Advertisement
Sign in to follow this  
Waaayoff

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.

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

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)

30685371.png




Back side

90201617.png



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;
}



Thanks for your help.

Share this post


Link to post
Share on other sites
Advertisement
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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

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.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!