5
$\begingroup$

From what I heard, vertex normals are calculated by averaging the face normals of all the faces that share a particular vertex, perhaps by giving extra weightage to the normals from faces of large area

However, I noticed quite the peculiar case when I made Blender display vertex normals for a circle without any face:

enter image description here

Though there are no face normals to calculate the vertex normals from, Blender still displays vertex normals. The moment I give those verts a face, the normals change directions. How did Blender display vertex normals in the above pic if there are no faces to calculate the face normals from?

$\endgroup$
4
  • 1
    $\begingroup$ it looks like the normals of vertices without faces will point toward the opposite direction of the origin of the object, you'll see if you move your circle in Edit mode $\endgroup$
    – moonboots
    Jul 3, 2021 at 8:36
  • $\begingroup$ @moonboots Very interesting, how exactly does it calculate distance to the origin? Alsoso, isthis behavior deliberately hardcoded or is this how vertex normals work in general? $\endgroup$
    – Hash
    Jul 3, 2021 at 8:41
  • $\begingroup$ mmh not sure what the distance has to do with your question. About your second question, vertex normal always take into account the face(s) it is part of, if it is part of a face, actually I never realized how it worked without face until now $\endgroup$
    – moonboots
    Jul 3, 2021 at 8:55
  • 1
    $\begingroup$ blender.stackexchange.com/a/10727/2217 $\endgroup$
    – David
    Jul 4, 2021 at 22:25

2 Answers 2

11
$\begingroup$

The direction of the vertices' normals will depend on the face the vertices are part of:

enter image description here

If the vertices are not part of any face it looks like their normals will point towards the opposite direction of the object's origin:

enter image description here

$\endgroup$
13
  • 1
    $\begingroup$ How does it exactly evaluate a normal such that it points towards the origin at all times like in your gif file? As in, fundamentally what does it do to generate a normal that 'passes' through the origin? Is there a specific algorithm or formula for that? $\endgroup$
    – Hash
    Jul 3, 2021 at 10:30
  • $\begingroup$ I guess your question is too complicated for me, I hope someone will answer ;) $\endgroup$
    – moonboots
    Jul 3, 2021 at 10:49
  • $\begingroup$ nice animation!! +1 $\endgroup$
    – Chris
    Jul 3, 2021 at 11:43
  • $\begingroup$ it's french cancan but with vertices $\endgroup$
    – moonboots
    Jul 3, 2021 at 11:46
  • 7
    $\begingroup$ @Hash the formula is, object space vertex position, normalized. Vector from one point to another point is P1 minus P2, and P2 here-- the origin-- is at 0,0,0. $\endgroup$
    – Nathan
    Jul 3, 2021 at 15:22
5
$\begingroup$

vertex normals are calculated by averaging the face normals of all the faces that share a particular vertex

While that's conceptually what's going on, it's not necessarily how it's implemented. It's actually kind of backwards. I can't speak to implementation details of Blender specifically, but in (polygon-based) computer graphics in general, the basic underlying building block is the vertex. Besides position, vertices can carry additional data, e.g., UV coordinates, a vertex color, a weight, and a normal vector. So the normals are associated with the vertices themselves.

Polygons are generally all built out of triangles (it's just that some edges may be hidden; e.g. a quad is two triangles with a hidden shared edge). So they are represented just as groups of 3 vertices. There isn't, like, a special "surface" primitive in the computer. It's just the 3 vertices that define the surface, and pretty much all other data can be derived or interpolated from the data carried by those vertices. It's used to determine where the polygon is, if a ray intersects it or not, where the intersection point is on the surface, where to sample a texture to place a color somewhere on the surface, etc. And it's used to interpolate the normals and adjust shading accordingly.

If the normals all point in the same direction, then the polygon appears flat. For proper shading, these normals should be, well, normal to the surface; again, you can determine this direction from vertices, by using the cross-product operation.

If you have two polygons next to each other, and they are angled, the three vertex normals of one polygon will point in one direction, and those of the other polygon will point in a different direction, and you'll get that faceted look.

If you instead make the normals at the "connected" side match up, you get smooth shading. The usual way to do that is to find some kind of an average.

enter image description here

Note that with this approach, the vertices aren't truly shared, they just happen to be in the same place. There is also a way to create and render models where vertices along a common edge can truly be shared, but that doesn't affect this overall process.

Everything beyond that (things like n-gons, face normals, etc.) is likely an abstraction provided for you by Blender; a more user-friendly "facade" that lets you work in terms of concepts that are more natural, rather than with the raw underlying representation.

So, the circular shape you asked about is, under the hood, likely represented in a very similar way, except that now instead of polygons you just have edges, which are encoded as pair of vertices - and these vertices are the same underlying primitives used for full 3D, polygon-based models, and carry the same data (after all, you can extrude shapes, etc).

The problem is, to determine the direction of a normal, you need something to define a plane, and you need 3 non-collinear points to do that, but each edge has only 2, which is probably why they just make them point away from the objects pivot point (the [0,0,0] point in object's local coordinates), as moonboots demonstrated.

How does it exactly evaluate a normal such that it points towards the origin at all times like in your gif file? As in, fundamentally what does it do to generate a normal that 'passes' through the origin? Is there a specific algorithm or formula for that? [Additional question by the OP, from a comment to another answer.]

Technically it points away from the origin (and away from the vertex). It's not very complicated; to get a vector directed from one point to another all you need to do is subtract the positions of the two points, i.e. [vertex] - [some other point]. You just subtract the individual components of the two vectors. This will give you a vector starting at [some other point] and ending at [vertex]. The order of operations is important; if you subtract them the other way around, the vector will point in the other direction.

You can then rescale the resulting vector as you see fit (this is just a mutiplication by a number), and sort of move it so that it starts at the vertex, for display purposes. Since in this case the other point is the origin, which is in local (object) space [0,0,0], you are subtracting the zero vector, which just gives you the original vertex position you started with - so you don't really need to calculate anything, you just take the position data from the vertex itself and rescale it, to make all normals be the same length.

When you have a proper face (or, rather, a triangle), then you can subtract the vertex positions in the same way to get two vectors that lie along two edges, and then use the cross product operation to produce a third vector that's perpendicular to both (and thus to the surface of the triangle).

enter image description here

$\endgroup$
13
  • $\begingroup$ Thanks for the detailed explanation. When you say "If you instead make the normals at the "connected" side match up, you get smooth shading. The usual way to do that is to find some kind of an average", is it not worthwhile to distinguish split normals from normals, as they are 2 different things? $\endgroup$
    – moonboots
    Jul 4, 2021 at 6:19
  • $\begingroup$ Maybe disambiguate your last illustration :) .. if we're looking down on abc, which is kind of what it feels like, with the normal sticking up like a flagpole.. then Normal is Side2 x Side1, not Side1 x Side2. $\endgroup$
    – Robin Betts
    Jul 4, 2021 at 8:22
  • $\begingroup$ @Filip Milovanović I am confused by this paragraph specifically: 'to get a vector directed from one point to another all you need to do is subtract the positions of the two points, i.e. [vertex] - [some other point' I tried using an online vector plotter to visualize it, but when I did that, the resultant vector does not result in a vector starting at some-other-point and ending at vertex? Also in the last portion of your answer, why does subtracting vector positions of a polygon yield us vectors lying on the 2 edges exactly? Im struggling to understand the intuition $\endgroup$
    – Hash
    Jul 4, 2021 at 11:29
  • $\begingroup$ @Hash There's a mathematical detail I glossed over 'cause I thought it would complicate things; we think of vectors as having a starting point and an endpoint, but mathematically, a vector only has a magnitude and a direction (that is, it's only defined by the endpoint, and there's no starting point - all vectors are taken to start at [0, 0, 0], just arrows emanating form the origin). So when you do the subtraction you get a vector of the right length and orientation, but emanating from the origin. You can then sort of mentally move it to where you need it, keeping its orientation. $\endgroup$ Jul 4, 2021 at 21:51
  • $\begingroup$ @Hash See for example this demo of how vector subtraction works; basically you negate (flip) one vector, and then you add that to the other; note that the resultant can be moved to the gap to exactly complete the triangle. Keep in mind that, in accordance to the mathematical definition mentioned previously, all this moving around is just a visual aid. $\endgroup$ Jul 4, 2021 at 21:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.