Jump to content
  • Advertisement
Sign in to follow this  
XVincentX

Normal from normal?

This topic is 3622 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

Hello. I would ask something about normals. Usually, beyond vertices positions, we store in our structs also normals. Suppose i need to compute the normal to a face, i usually use this code
float3 GetNormal( float3 A, float3 B, float3 C )
{
	float3 AB = B - A;
	float3 AC = C - A;
	return normalize( cross(AB,AC) );
}

With A,B,C the 3 vertices. But after i thought: <<"Why have i to compute normals in this way, if i've got normals information in vertex structure?">> So, how can i obtain the normal from normal vertices informations?

Share this post


Link to post
Share on other sites
Advertisement
its probaly a lot simpler to do it the way you are already doing it, you have to add all normals of the face's vertices and find the average.

Share this post


Link to post
Share on other sites
Quote:
Original post by staticVoid2
its probaly a lot simpler to do it the way you are already doing it, you have to add all normals of the face's vertices and find the average.

'Find' the average?

Face_normal = (A.normal + B.normal + C.normal) / 3

Nothing difficult about that.

There is, however, a subtle difference. The OP's way calculates the face's normal from the geometry, but this wouldn't look good, for instance, with a curved surface. By averaging the vertex normals you ensure the face normal follows the curvature of the surface. So the latter is the preferred way, in most cases.

Share this post


Link to post
Share on other sites
Thank you for the answer, now it's more clear.

But why, from geometry, i may have issues with curved surface? Can you explain me it?

Share this post


Link to post
Share on other sites
A sphere is approximated with triangles and can obviously never be entirely round. If you were to light every triangle according to its face normal, you'd see a faceted sphere. To avoid this, the vertices have their normals pointing outward as a true sphere normal. Then, the lighting is calculated at the three vertices, which produces three different colors and then interpolated over the triangle, to give a much smoother look.

Also see this lighting tutorial. Scroll down to "Smooth shading".

The point is that the vertex normals are the 'true' normals at those points. And the face normal should be the 'true' normal as well, and the best you can get is to interpolate the true normals of the vertices of the face. If you just take the cross product of AB and AC, you'll get the normal pointing straight out of the face, as defined by the geometry, but that's not necessarily the 'true' normal that it's meant to have.

Of course, this depends on what you need the normal for. There might be cases where you really just want to know the geometric normal.

Share this post


Link to post
Share on other sites
Quote:
Original post by Mike nl
Face_normal = (A.normal + B.normal + C.normal) / 3


The normal will not be unit length if you do this.

Do this instead:

Face_normal = normalize(A.normal + B.normal + C.normal)

Share this post


Link to post
Share on other sites
not to mention it doesnt give correct results
cause u cant really add normals

normalize(vec3(-1,0,0)+vec3(1,0,0));

but for most cases it looks ok enuf

Share this post


Link to post
Share on other sites
Quote:
Original post by zedz
not to mention it doesnt give correct results
cause u cant really add normals

normalize(vec3(-1,0,0)+vec3(1,0,0));

but for most cases it looks ok enuf


So? Is there a "definitive" method to get normals from normal information in vertices?

Share this post


Link to post
Share on other sites
If you think of the problem as finding the interpolated normal at some point within the triangle, then you would find the barycentric coordinates of that point and use those as weights when combining your normals from the vertices. It so happens that at the centroid of the triangle, the barycentric coordinates happen to be (1/3, 1/3, 1/3) - which is the average.

So basically I'm saying that the correct answer is indeed
normalize( 1/3*A.normal + 1/3*B.normal + 1/3*C.normal)
which is equilavent to
normalize(A.normal + B.normal + C.normal).

You are correct, zedz, that you cannot simply add normals - but in this case we're doing an interpolation that just so happens to simplify to simple addition.:) And incidentally your example won't work because it is a very malformed triangle. If you correctly interpolate the normals across that triangle - for per-pixel lighting for example - incorrect results would also be generated (ie normalize(0) at the centroid, probably resulting in a white or black pixel if running on a GPU).

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.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!