How to interpolate vertex normals?
Asked Answered
O

2

6

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?

Ootid answered 25/3, 2013 at 21:4 Comment(2)
with a shader ? or how do you want to achieve this?Homorganic
It can be a shader (is faster right?)Ootid
E
12

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.

Eponymy answered 26/3, 2013 at 3:20 Comment(1)
Ok Nicol thanks a lot for the clarification, I will work on that. Regards!Ootid
P
11

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.

Pegeen answered 25/3, 2013 at 21:32 Comment(2)
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?Ootid
That's what I meant when I wrote "this is a bit less trivial". I refer you to @Nicol's answer above.Pegeen

© 2022 - 2024 — McMap. All rights reserved.