How to interpolate vertex normals?

15,784

Solution 1

First of all, you are not computing vertex normals. You are computing face normals. This is step 1 in the process of computing vertex normals.

The next step is not interpolating anything. What you do is compute the (unnormalized) face normal for each face attached to a vertex. Then add them all together and normalize the result. That is the vertex normal.

How you determine which faces are attached to a vertex is another matter. In your case, because you're building this data via marching cubes, it shouldn't be too difficult to generate or retrieve the triangles from adjacent cubes. But if you're pass the generation step and just have a bag of triangles, then you're going to need an appropriate mesh topology data structure. Winged-edge or Quad-edge are both good choices.

Solution 2

What are a, b and c?

If they're the vertices of a triangle, then you are computing the normal for the triangle, not for any particular vertex. The assumption in that case, is that the entire triangle is flat. This is called flat shading.

If, on the other hand, you wish to interpolate the surface normal across the interior of a triangle (used in Gouraud shading), then you need to have three different normals at the three vertices to begin with. This is a bit less trivial, but still easy. One way is to average the normals of all triangles that share a vertex in order to obtain the normal at that vertex. This obviously requires connectivity information (or you need to extract it somehow).

Once you have three different normals (say na, nb, nc), then the normal at any interior point can be computed via barycentric coordinates. Let the vertices be va, vb, vc and the interior point's barycentric coords be α and β. Then, the interior point v and its normal n are given by:

v = α*va + β*vb + (1 - α - β)*vc
n = α*na + β*nb + (1 - α - β)*nc

This interpolated normal (n) should be used for Gouraud shading.

Share:
15,784
Floyd Barber
Author by

Floyd Barber

Updated on June 04, 2022

Comments

  • Floyd Barber
    Floyd Barber almost 2 years

    I am trying to render a 3D model (from volvis.org) with Gouraud shading using the marching cubes algorithm. So far I have the normals for each vertex with:

    GetNormalForVertex(vertex &b, vertex &a, vertex &c) {
        u.X = a.X - b.X;
        u.Y = a.Y - b.Y;
        u.Z = a.Z - b.Z;
        v.X = c.X - b.X;
        v.Y = c.Y - b.Y;
        v.Z = c.Z - b.Z;
    
        return  Cross(u,v);
    }
    

    I can see a nice flat shading when its rendered. Now, far as I know I need to interpolate those vertex normals to find normal at the intersection point to get Gouraud shading. How could I interpolate the vertex normals?

    • D-rk
      D-rk about 11 years
      with a shader ? or how do you want to achieve this?
    • Floyd Barber
      Floyd Barber about 11 years
      It can be a shader (is faster right?)
  • Floyd Barber
    Floyd Barber about 11 years
    Yes a, b and c are the vertices of a triangle and I compute the normals for each vertex with the function GetNormalForVertex. How can I get the shared vertices if I have an array of triangle structs?
  • Rahul Banerjee
    Rahul Banerjee about 11 years
    That's what I meant when I wrote "this is a bit less trivial". I refer you to @Nicol's answer above.
  • Floyd Barber
    Floyd Barber about 11 years
    Ok Nicol thanks a lot for the clarification, I will work on that. Regards!