<p>I see mainly three ways of computing normals for a generated shape.</p>
<h1>Analytic normals</h1>
<p>In some cases you have enough information about the surface to generate the normals. For example, the normal of any point on a sphere is trivial to compute. Put simply, when you know the derivative of the function, you also know the normal.</p>
<p>If your case is narrow enough to allow you to use analytic normals, they will probably give the best result in terms of precision. The technique doesn't scale too well though: if you also need to handle cases where you cannot use analytic normals, it may be easier to keep the technique that handles the general case and drop the analytic one altogether.</p>
<h1>Vertex normals</h1>
<p>The cross product of two vectors gives a vector perpendicular to the plane they belong to. So getting the normal of a triangle is straightforward:</p>
<pre><code>vec3 computeNormal(vec3 a, vec3 b, vec3 c)
{
    return normalize(crossProduct(b - a, c - a));
}
</code></pre>
<p>Moreover, in the above example, the length of the cross product is proportional to the area inside <em>abc</em>. So the smoothed normal at a vertex shared by several triangles can be computed by summing up the cross products and normalizing as a last step, thus weighting each triangle by its area.</p>
<pre><code>vec3 computeNormal(vertex a)
{
    vec3 sum = vec3(0, 0, 0);
    list&lt;vertex&gt; adjacentVertices = getAdjacentVertices(a);
    for (int i = 1; i &lt; adjacentVertices; ++i)
    {
        vec3 b = adjacentVertices[i - 1];
        vec3 c = adjacentVertices[i];
        sum += crossProduct(b - a, c - a);
    }
    if (norm(sum) == 0)
    {
        // Degenerate case
        return sum;
    }
    return normalize(sum);
}
</code></pre>
<p>If you are working with quads, there is a nice trick you can use: for a quad <em>abcd</em>, use <code>crossProduct(c - a, d - b)</code> and it will handle nicely cases where the quad is in fact a triangle.</p>
<p>Iñigo quilez wrote a few short articles on the topic: <a href="http://www.iquilezles.org/www/articles/normals/normals.htm" rel="noreferrer">clever normalization of a mesh</a>, and <a href="http://iquilezles.org/www/articles/areas/areas.htm" rel="noreferrer">normal and area of n sided polygons</a>.</p>
<h1>Normals from partial derivatives</h1>
<p>Normals can be computed in the fragment shader from the partial derivatives. The math behind is the same, except this time it is done in screen space. This article by Angelo Pesce describes the technique: <a href="http://c0de517e.blogspot.jp/2008/10/normals-without-normals.html" rel="noreferrer">Normals without normals</a>.</p>

CC BY-SA 3.0
2015-10-06T04:19:45.657Z
There is a fourth way, artist supplied normals ;)
joojaa
CC BY-SA 3.0
2015-10-06T05:09:13.187Z
@joojaa: I assume you are referring to normal maps? I've never heard of manually authored normals otherwise.
Julien Guertault
CC BY-SA 3.0
2015-10-06T07:30:19.340Z
No, manually authored normals. It sometimes happens that your artist knows more about how the normals should behave than the programmers models do. It is sometimes a bit problematic to the calculation engines if they assume normals come from underlying calculations. But certainly it happens and you save lot of time in mathematical modeling.
joojaa
CC BY-SA 3.0
2016-08-29T14:06:57.273Z
These are sometimes referred to as "explicit normals" (3ds max and maya terminology).
Dusan Bosnjak 'pailhead'
CC BY-SA 3.0
2015-10-06T02:53:06.210Z
2015-10-14T11:43:16.537Z
2020-06-18T08:32:12.800Z
Julien Guertault
<p>You simply dont want fully smooth results. While the commented method by Nathan Reed: "Calculate each vertex to face normal, sum them, normalize sum", generally works it sometimes fails spectacularly. But that is of no importance here, we can use that method by adding a rejection clause to it.</p>

<p>In this case you simply want certain parts not to be smoothed against certain other parts. You want selective hard edges. So for example the flat top and bottom is separate form the triangle strip on the side, as is each flat area.</p>

<p><a href="https://i.sstatic.net/JLntk.png" rel="noreferrer"><img src="https://i.sstatic.net/JLntk.png" alt="Image we are after"></a></p>

<p><strong>Image 1</strong>: The result you want.</p>

<p>In effect you only want to average the vertices of the curved area all others can use the normal they get form their triangle alone. So you are better of thinking of the mesh as 9 separate regions that are handled without the others.</p>

<p><a href="https://i.sstatic.net/ityq6.png" rel="noreferrer"><img src="https://i.sstatic.net/ityq6.png" alt="Showing mesh and normals]"></a></p>

<p><strong>Image 2</strong>: Image showing the mesh structure and the normals. </p>

<p>You can certainly automatically deduce this by not including normals that are outside certain angle from the primary vertexes normal. Pseudocode:</p>

<pre><code>For vertex in faceVertex:
    normal = vertex.normal
    For adjVertex in adjacentVertices:
        if anglebetween(vertex.normal, adjVertex.normal )  &lt; treshold:
            normal += adjVertex.normal
    normal = normalize(normal)
</code></pre>

<p>That works, but you can simply avoid all of this at creation time because you understand that separate planes are working differently. So only the curved sides need normal direction merging. And in fact you can just directly calulate them from the underlying mathematical shape.</p>

CC BY-SA 3.0
2015-10-02T06:01:39.200Z
2015-10-02T08:59:22.163Z
2015-10-02T08:59:22.163Z
joojaa
<p>I have a class that generates a 3D shape based on inputs from the calling code. The inputs are things like length, depth, arc, etc. My code generates the geometry perfectly, however I am running into trouble when calculating the surface normals. When lit, my shape has very bizarre coloring/texture from the incorrect surface normals that are being calculated. From all my research I believe my math is correct, it seems that something is wrong with my technique or method.</p>

<p>At a high level how does one go about programmatically calculating the surface normals for a generated shape? I am using Swift/SceneKit on iOS for my code but a generic answer is fine.</p>

<p>I have two arrays that represent my shape. One is an array of 3D points that represents the vertices that make up the shape. The other array is a list of indexes of the first array that map the vertices into triangles. I need to take that data and generate a 3rd array that is a set of surface normals that aid in the lighting of the shape. (see <a href="https://developer.apple.com/library/prerelease/ios/documentation/SceneKit/Reference/SceneKit_Constants/index.html#//apple_ref/c/data/SCNGeometrySourceSemanticNormal" rel="noreferrer"><code>SCNGeometrySourceSemanticNormal</code> in SceneKit`</a>)</p>

<p>The list of vertices and indexes is always different depending on the inputs to the class so I cannot pre-calculate or hard code the surface normals.</p>

CC BY-SA 3.0
2015-10-02T01:23:41.690Z
Need more context. Are you trying to calculate analytic normals for a parametric surface? An implicit surface? Or do you want to calculate the normals from a generic triangle mesh? Or something else?
Nathan Reed
CC BY-SA 3.0
2015-10-02T01:42:12.217Z
Thanks, I added more detail. To answer your question I need to calculate normals from a generic triangle mesh. Though to be clear that mesh is different depending on the inputs. My shape is a 3D arrow, as an example here is a screenshot of it 2 different forms (i.e. radial, and linear). The class changes the width, depth, length, arc, and radius of the mesh as requested. http://cl.ly/image/3O0P3X3N3d1d You can see the odd lighting I am getting with my poor attempts at solving this.
joshwbrick
CC BY-SA 3.0
2015-10-02T01:58:22.140Z
The short version is: calculate each vertex normal as the normalized sum of the normals of all the triangles that touch it. However, this will make everything smooth, which may not be what you want for this shape. I'll try to expand into a full answer later.
Nathan Reed
CC BY-SA 3.0
2015-10-02T02:03:42.117Z
Smooth is what I am going for!
joshwbrick
CC BY-SA 3.0
2015-10-02T02:42:44.147Z
I implemented my understanding of your short answer and the result is better, but still a bit off. http://cl.ly/image/2T3k2R1Z0V25/o I am going for the smooth look of the cube in that screenshot. On the right is all the shape points along with the surface normals as my code as calculated them.
joshwbrick
CC BY-SA 3.0
2015-10-02T07:03:06.370Z
In most cases, if you calculate the vertex positions analytically, you can also calculate the normals analytically. For a parametric surface, the normals are the cross product of the two gradient vectors. Calculating the average of triangle normals is just an approximation, and often results in visually much poorer quality. I would post an answer, but I already posted a detailed example on SO (http://stackoverflow.com/questions/27233820/providing-normals-with-triangle-strips-and-fans-for-opengl-gouraud-shading/27244693#27244693), and I'm not sure if we want replicated content here.
Reto Koradi
CC BY-SA 3.0
2015-10-13T22:17:45.723Z
Since you are using SceneKit, would `SCNShape` be useful to you? It can create a 3D mesh with normals and texture coordinates by extruding a Bézier path.
mnuages
<lighting><geometry><mesh>
How to Calculate Surface Normals for Generated Geometry
joshwbrick
# How to Calculate Surface Normals for Generated Geometry

(Asked by: username_0 on 2015-10-02)

I have a class that generates a 3D shape based on inputs from the calling code. The inputs are things like length, depth, arc, etc. My code generates the geometry perfectly, however I am running into trouble when calculating the surface normals. When lit, my shape has very bizarre coloring/texture from the incorrect surface normals that are being calculated. From all my research I believe my math is correct, it seems that something is wrong with my technique or method.

At a high level how does one go about programmatically calculating the surface normals for a generated shape? I am using Swift/SceneKit on iOS for my code but a generic answer is fine.

I have two arrays that represent my shape. One is an array of 3D points that represents the vertices that make up the shape. The other array is a list of indexes of the first array that map the vertices into triangles. I need to take that data and generate a 3rd array that is a set of surface normals that aid in the lighting of the shape. (see [`SCNGeometrySourceSemanticNormal` in SceneKit`](https://developer.apple.com/library/prerelease/ios/documentation/SceneKit/Reference/SceneKit_Constants/index.html#//apple_ref/c/data/SCNGeometrySourceSemanticNormal))

The list of vertices and indexes is always different depending on the inputs to the class so I cannot pre-calculate or hard code the surface normals.

**Tags:** lighting, geometry, mesh

> **Comments:**
> **username_1**: Need more context. Are you trying to calculate analytic normals for a parametric surface? An implicit surface? Or do you want to calculate the normals from a generic triangle mesh? Or something else?  
> **username_0**: Thanks, I added more detail. To answer your question I need to calculate normals from a generic triangle mesh. Though to be clear that mesh is different depending on the inputs. My shape is a 3D arrow, as an example here is a screenshot of it 2 different forms (i.e. radial, and linear). The class changes the width, depth, length, arc, and radius of the mesh as requested. http://cl.ly/image/3O0P3X3N3d1d You can see the odd lighting I am getting with my poor attempts at solving this.  
> **username_1**: The short version is: calculate each vertex normal as the normalized sum of the normals of all the triangles that touch it. However, this will make everything smooth, which may not be what you want for this shape. I'll try to expand into a full answer later.  
> **username_0**: Smooth is what I am going for!  
> **username_0**: I implemented my understanding of your short answer and the result is better, but still a bit off. http://cl.ly/image/2T3k2R1Z0V25/o I am going for the smooth look of the cube in that screenshot. On the right is all the shape points along with the surface normals as my code as calculated them.  
> **username_2**: In most cases, if you calculate the vertex positions analytically, you can also calculate the normals analytically. For a parametric surface, the normals are the cross product of the two gradient vectors. Calculating the average of triangle normals is just an approximation, and often results in visually much poorer quality. I would post an answer, but I already posted a detailed example on SO (http://stackoverflow.com/questions/27233820/providing-normals-with-triangle-strips-and-fans-for-opengl-gouraud-shading/27244693#27244693), and I'm not sure if we want replicated content here.  
> **username_3**: Since you are using SceneKit, would `SCNShape` be useful to you? It can create a 3D mesh with normals and texture coordinates by extruding a Bézier path.  

---

## 2 answers

### Answer by username_5 on 2015-10-02. Score: 11 | Accepted answer

You simply dont want fully smooth results. While the commented method by username_1 username_1: "Calculate each vertex to face normal, sum them, normalize sum", generally works it sometimes fails spectacularly. But that is of no importance here, we can use that method by adding a rejection clause to it.

In this case you simply want certain parts not to be smoothed against certain other parts. You want selective hard edges. So for example the flat top and bottom is separate form the triangle strip on the side, as is each flat area.

[![Image we are after](https://i.sstatic.net/JLntk.png)](https://i.sstatic.net/JLntk.png)

**Image 1**: The result you want.

In effect you only want to average the vertices of the curved area all others can use the normal they get form their triangle alone. So you are better of thinking of the mesh as 9 separate regions that are handled without the others.

[![Showing mesh and normals]](https://i.sstatic.net/ityq6.png)](https://i.sstatic.net/ityq6.png)

**Image 2**: Image showing the mesh structure and the normals.

You can certainly automatically deduce this by not including normals that are outside certain angle from the primary vertexes normal. Pseudocode:

```
For vertex in faceVertex:
    normal = vertex.normal
    For adjVertex in adjacentVertices:
        if anglebetween(vertex.normal, adjVertex.normal )  < treshold:
            normal += adjVertex.normal
    normal = normalize(normal)

```

That works, but you can simply avoid all of this at creation time because you understand that separate planes are working differently. So only the curved sides need normal direction merging. And in fact you can just directly calulate them from the underlying mathematical shape.


---

### Answer by username_4 on 2015-10-06. Score: 12

I see mainly three ways of computing normals for a generated shape.

# Analytic normals

In some cases you have enough information about the surface to generate the normals. For example, the normal of any point on a sphere is trivial to compute. Put simply, when you know the derivative of the function, you also know the normal.

If your case is narrow enough to allow you to use analytic normals, they will probably give the best result in terms of precision. The technique doesn't scale too well though: if you also need to handle cases where you cannot use analytic normals, it may be easier to keep the technique that handles the general case and drop the analytic one altogether.

# Vertex normals

The cross product of two vectors gives a vector perpendicular to the plane they belong to. So getting the normal of a triangle is straightforward:

```
vec3 computeNormal(vec3 a, vec3 b, vec3 c)
{
    return normalize(crossProduct(b - a, c - a));
}

```

Moreover, in the above example, the length of the cross product is proportional to the area inside *abc*. So the smoothed normal at a vertex shared by several triangles can be computed by summing up the cross products and normalizing as a last step, thus weighting each triangle by its area.

```
vec3 computeNormal(vertex a)
{
    vec3 sum = vec3(0, 0, 0);
    list<vertex> adjacentVertices = getAdjacentVertices(a);
    for (int i = 1; i < adjacentVertices; ++i)
    {
        vec3 b = adjacentVertices[i - 1];
        vec3 c = adjacentVertices[i];
        sum += crossProduct(b - a, c - a);
    }
    if (norm(sum) == 0)
    {
        // Degenerate case
        return sum;
    }
    return normalize(sum);
}

```

If you are working with quads, there is a nice trick you can use: for a quad *abcd*, use `crossProduct(c - a, d - b)` and it will handle nicely cases where the quad is in fact a triangle.

Iñigo quilez wrote a few short articles on the topic: [clever normalization of a mesh](http://www.iquilezles.org/www/articles/normals/normals.htm), and [normal and area of n sided polygons](http://iquilezles.org/www/articles/areas/areas.htm).

# Normals from partial derivatives

Normals can be computed in the fragment shader from the partial derivatives. The math behind is the same, except this time it is done in screen space. This article by Angelo Pesce describes the technique: [Normals without normals](http://c0de517e.blogspot.jp/2008/10/normals-without-normals.html).

> **Comments:**
> **username_5**: There is a fourth way, artist supplied normals ;)  
> **username_4**: @username_5: I assume you are referring to normal maps? I've never heard of manually authored normals otherwise.  
> **username_5**: No, manually authored normals. It sometimes happens that your artist knows more about how the normals should behave than the programmers models do. It is sometimes a bit problematic to the calculation engines if they assume normals come from underlying calculations. But certainly it happens and you save lot of time in mathematical modeling.  
> **username_6**: These are sometimes referred to as "explicit normals" (3ds max and maya terminology).  

---

