2

Thanks to help of shmuel I made a setup for interpolating a normal in geonodes. Ideally, it would reproduce Blender's smooth shading exactly. So I reproduced the setup in the Shading nodes. In order to access the vertex positions and values, I capture them in geonodes on face domain:

For this to work properly I triangulate first:

Now, the main shading tree is straight-forward, just read the attribute, offload the actual calculations to another tree "Smooth Shading", and use the result:

"Smooth Shading" tree is based on barycentric coordinates:

The "Triangle Area" tree:

This all works very well for most purposes, but isn't perfect, the Mix node is there to easily switch between the two and see the difference:

It's very subtle and not visible when actually used as a normal. And yet there is a difference and it's not some kind of super-subtle difference I got here:

It's more, my approach is a linear interpolation, but here's I think a quadratic interpolation? Which would mean I need to consider also further vertices? Just a guess... You can see it if you pass the normal through Vector Math: Wrap to generate lines. In linear interpolation they are straight, but as seen on the top of the head, the Blender's interpolation smooths the lines:

So what algorithm do you propose to reproduce the smooth shading exactly?

Markus von Broady
  • 36,563
  • 3
  • 30
  • 99

1 Answers1

3

The issue is inside "Smooth shading" node group.

It calculates 3 surfaces from a given point and takes the weighted average of the normals relatively to the whole surface (the sum of the 3).

But this weighted average of 3 normalized vectors is not normalized itself.

Simplified case:

n1 = (1, 0) and n2 = (0, 1)

s1 = 0.5 and s2 = O.5 (s total = 1)

will result in 0.5 * n1 + 0.5 * n2 = (0.5, 0.5) which has not a length of 1.

enter image description here

lemon
  • 60,295
  • 3
  • 66
  • 136
  • 1
    So much trouble, and you fixed it with one well positioned node :D Great, thanks! – Markus von Broady Feb 18 '24 at 09:05
  • It also explains why I didn't see a difference when testing it as an actual normal in the shader - I thought it's just because it's a subtle difference, but instead it's because the normals are normalized by the shader (or otherwise their magnitude doesn't matter in the calculations). – Markus von Broady Feb 18 '24 at 09:19
  • mmm... in fact, if used as normal, it seems there is still an issue... : ( ... something about back facing – lemon Feb 18 '24 at 09:30
  • yes... if backfacing, the normal should be inverted. – lemon Feb 18 '24 at 09:48
  • How so? I'd think if the face is flipped, that is read on the geonodes, so the data is already inverted on the geonodes part storing the data on faces? Is there some problem with interpolation between flipped faces? or maybe the "backface" property simply doubles the flipping and that's why I should detect it and flip again? – Markus von Broady Feb 18 '24 at 09:55
  • 1
    face corners are not "doubled" per face depending on front/back facing, or am I wrong? Another way to say that is "back facing is just a point of view... so impossible to know that in gn" (except calculating from the cam, of course). – lemon Feb 18 '24 at 10:01
  • I forgot the "backfacing" doesn't tell you some kind of an attribute of a face, rather, as you point it, it tells you your "view" - from which side you look at it. So it all makes sense now. Just last addition from me: the normalization has to be applied only in case of interpolating normals. When interpolating something else e.g. color, the custom group "Smooth Shading" works as it should. So you were correct to position the "Normalize" node outside the custom group. – Markus von Broady Feb 18 '24 at 11:21
  • 1
    Well in fact, I placed it here just because it was more simple... without taking any other consideration into account. But thanks for the precisions. – lemon Feb 18 '24 at 11:47