- Home /
Rendering hard edges via vertex shader
Is there any way to use a vertex shader to draw all edges as hard even though they have been imported from Maya as soft? I'd like to have a hard edge look to my geometry but I would prefer that the vertices not be split into multiple vertices. Seems as though a vertex shader could work but I'm completely new to writing them. I've read some of the docs on this but would appreciate guidance in how something like this might be achieved.
Answer by Bunny83 · Dec 08, 2014 at 01:10 PM
As @tanoshimi said a vertex shader just processes each vertex once. So each vertex will have exactly one normal vector. If that vertex is shared by multiple faces / triangles they will be smooth at this point. A vertex shader can't change this.
However there are ways to get the actual face normal by using the partial derivative functions ddx and ddy in the fragment shader. With those you are able to get two tangent vectors at the current screenspace point which describe your surface plane. Take the crossproduct and normalize it and you have the normal vector of the flat surface. However the derivative functions are quite demanding. You literally are calculating the normal for each fragment.
Something like that:
// in the cg fragment shader
float3 x = ddx(IN.pos); // IN.pos is the screen space vertex position
float3 y = ddy(IN.pos);
float3 normal = normalize(cross(x, y));
It all comes down to if your target platform supports the derivative functions and how they perform on that platform. In most cases it's more performant to split the vertices.
Sounds like I'll need to split the vertices anyway. Very insightful Bunny83 :) Thank you.
Alternatively, you could calculate the face normals for each triangle in the mesh.triangles array and assign this to each vertex using an otherwise unused vertex attribute (tangent, say). Then create a shader with a custom lighting model that uses this "face normal" value in place of the vertex normal.
It depends how often you'd need to recalculate the normals. Is your mesh dynamic?
Answer by tanoshimi · Dec 05, 2014 at 01:05 PM
I don't think you want a vertex shader - simply try on the "model" tab of the import settings to set "Normals" to "Calculate", and "Smoothing Angle" to 0"
Thank you for your response, but it's not quite what I'm looking for. I'm trying to prevent unity from splitting vertices when displaying hard edges. Whether I make edges hard in $$anonymous$$aya, or use the approach that you recommended, Unity continues to split the vertices, as it needs 3 normals to correctly display the hard edge.
However, if Unity can take a smoothed mesh from $$anonymous$$aya and and render it as hard edged when imported, I would assume there is a solution that will do this at runtime - hence the mention of vertex shader. Becuase I'm doing vertex manipulation at runtime, I would prefer to only modify a single vertex ins$$anonymous$$d of having to keep track of 3 at time.
I'm still hoping someone has some advice on how to make this happen. Does anyone have thoughts on an approach to try?
I'm pretty sure flat shading requires the duplication of vertices to make them all share the same normal so that interpolation remains constant across a face. Vertex shaders cannot create new primitives - they can only modify existing vertices.
If you really wanted to do this at runtime, you could probably do so with a geometry shader, but that would limit you to DX11 platforms, and the shader would be doing more work and still have to render the same duplicated vertices at the end of the process.
Your answer
![](https://koobas.hobune.stream/wayback/20220613173225im_/https://answers.unity.com/themes/thub/images/avi.jpg)