One answer is in Blender, the other in Unity.
One says smooth is faster which goes against all I know. But then he says ‘Because it runs on the GPU’ which makes me think there is a difference between the authoring tool and the realtime engine way of handling polygons (while Blender requires to have all the normal data loaded on all vertices at all time, is it the case too for Unity or not?).
In order to get smooth outlines when I’m doing cel shading, I generally smooth my entire models and bake hard edges into the normal maps. I can’t say I’ve ever noticed a significant difference in performance between the two, though I typically deal with lower poly stuff (1000-5000 triangles). ymmv but I honestly doubt the performance difference is ever really going to matter.
The first link answers the question. Either way the same number of tris are being rendered, but there’s a difference in the number of vertices. With smooth edges adjacent tris can share vertices more often because the position, UV and normal are all the same. With hard edges the different normals force a separate vert for each tri. Shared verts (and/or the calculations performed on them) can be cached for a performance advantage. Separated verts can not, and also increase the vert count.
On early hardware the story may have been different. Normals may have been calculated per triangle based on vertex position, and verts may have been submitted as tris were drawn.
This is where I am lost:
While you say that Flat shading increases vertex count, smooth shading increases the amount of normals per face. So doesn’t smooth shading end up being more expensive?
Then there’s the fact both Zbrush and Blender sculpting are more performant with Smooth Shading disabled.
So that makes me think: is there a difference with rendering for realtime graphics versus rendering for modeling?
There’s a difference between different approaches to realtime rendering, period. ZBrush isn’t even GPU bound as far as I remember.
No, the amount of vertex normals per triangle is always 3. Unity doesn’t store “face normals”. But with smooth shading the amount of vertices that can be shared accross adjacent triangles is better, as has been explained already.
Usually this won’t be very noticable, but if one method allows you to still make use of dynamic batching, and the other one doesn’t, AND you actually have a good usecase for dynamic batching, then it can actually make a huge difference. That’s a very specific edgecase though.
The catch is that Unity never uses per face normals. It only ever uses per vertex normals, which makes flat shading require separate verts so that each triangle gets it’s own three normals.
The hit from vertex data is minuscule compared to the act of rendering the triangle. If anything it will hurt the bus more than it will be GPU, and even then it probably won’t be noticed. Doubling the vert count is still nothing compared to a couple of 4K textures.
If you achieve flat shading by adjusting “smooth angle” in 3d editor, then flat shaded model will have more vertices than a smooth-shaded ones.
Basically… a completely flat shaded model created this way most likely will have number of vertices equal to number of faces * 3.
However, if you achieve flat shading by calculating face normal within geometry shader, then it will not be necessary to increase number of vertices, and flat shaded model could have same number of vertices as a smooth shaded one.
Either way, I’d expect performance difference to be negligible between two methods.
Also, in addition to that both OpenGL and Direct3D had a flag to toggle smooth and flat shading without altering underlying geometry. This flag is (IIRC) completely inaccessible from unity.
You can have several normals per vertex, by storing them as texture coordinates. You can also store random data per vertex as vertex coordinates. Or as vertex colors.
No. Worrying about performance here smells like a premature optimization to me.
Chamfering is used to avoid “impossibly sharp” look on objects.
This is me right now:
It sounds like something simple to associate but I never stopped to think about it.
As a final question, is the mesh smoothing algorithm baked into the mesh once, or something that is calculated every frame? As in ‘is the calculation of the interpolation of vertices/edges performed every frame’?
Do you want a lesson on how lighting works? The short answer is that “smoothing” is a trick on how a surface should be lit, as in from what angle is light hitting the object at this point.
What I want to know is, for example in a deforming or animated object, because the angles between faces are constantly changing, does the smoothing interpolation get constantly recalculated along with normals?
And in the case of an object able to be animated but that is currently static, is it still calculated every frame?
It may sound like I am going too far with these ‘premature optimization’ questions but that has to do with that misinformed post in the OP that said you could get 4x more polycount for the same performance if you don’t use smoothing groups.
There is no physical smoothing. The polygons are still flat. They only look rounded because of lighting, which is what uses the normals to determine how much luminance it gets at any given point in the triangle.
No. Because modern GPUs performance comes down to bandwidth 9 times out of 10. People on the internet need to stop wasting time dithering over problems 5 years ago.
Artists have been doing chamfered edges for years. It’s for aesthetics… if by “worth it in terms of performance” you mean that people would add millions of verts to otherwise simulate it then no because it’s not an actual optimisation, but simply used regardless because it catches light better even for perfect cubes. It simply looks great. It also removes some artefacts… so many considerations before doing it just for perf. I think they started doing this long before star citizen and friends though.
The answer is to understand that vertex data are interpolated to create triangles, normal are simply interpolated too on a face to create smoothness, ie to introduce discontinuity (flatness) you need to duplicate the data, aka you duplicate the vertices.
Normal and vertices are transformed when rotating an objects, skinning is just a special case where the mesh is rotated differently in different parts.
No. Smoothing is never recalculated. Smoothing algorithm simply determines which faces share the same vertex (and normal) and that information is used to compute vertex normal. Once the normal is calculated - by the mesh exporter - it is stored within the vertex and is NEVER recalculated, no matter what you do, even if you’re running code on an ancient GPU (Dx9 and Pre-DX9) without Hardware T&L support (meaning vertex transformation is done on CPU).
Likewise even in case of Skinned Meshes, and even in case said mesh is calculated on CPU (Unity actualy uses CPU skinning by default), normal is never recalculated using smoothing information. It can be transformed/normalized, but it is never recalculated.
One of the reasons for “never recalculating the normal” is (aside from recalculation being pointless) that vertex/edge split doesn’t only happne on faces faces that are not in the same smoothing group, but also between faces that have different materials or different UV coordinates. If (“a.uv != b.uv” || “a.normal != b.normal” || “a.face.material != b.face.material”) upon export those vertices will be split and will be turned into separate vertices. Meaning the game mesh actually doesn’t have all the data required for proper normal recalculation. So, no recalculation ever happen.
–edit–
To explain it a bit better, in-game mesh format is different from mesh format used within editors.
Basically, an object within a game has array of vertices, and array of indices. A vertex may contain position, normal, uv coordinates, color, etc. All vertices have the same format, meaning if one of them have vertex colors, they all have a vertex color, if one of them has texture coordinates, they all have texture coordinates, etc. Vertices within that array are usually unique and upon export all vertices which are fully equal to each other (a.position == b.position; a.uv == b.uv, etc. are ALL true), they’re stored as one element, and are referred as the same indexx.
Which means that upon export smoothing group data (if present) is lost, AND if vertices are in the same smoothing group, BUT have different UV coordinates, they’ll be turned into separate vertices within mesh array. Because of this you can’t reliably recalculate vertex normal even if you want.