Is it possible to create fake round edges for hard surfaces using only shader graph?
Meaning, no additional edges or other pre made geometry.
Here’s an example of what I’m talking about:
It’s widely used in offline renderers (For example, V-ray and Corona both have built-in features for such cases), but seems to be a very hard thing for a game engine to do.
Do come back and share your progress. I’m interested in this too.
If it helps I have a piece of the jigsaw:
I can generate meshes from a halfedge data structure (which knows about non-triangular faces
I can use this extra info (whether an edge is “real” or not) and store it in a spare UV channel
I’ve got a shader graph that can use this info to determine “distance from an edge”. I’ve used this for various effects such as true hidden line wireframe shaders etc.
I have a feeling that this same edge info could do the bevelling. The normals should be fairly easy but I’m not sure how you’d change the actual profile - i.e. set the opacity of a pixel when viewing a corner from the side so you can see past it.
I mean, once you’re getting to the point of generating special data for the mesh, you could just generate a normal map that would work even better with a lot less hassle.
The TLDR version of the original question is no. It is not possible to do with only Shader Graph. It requires data that the GPU does not give to the shaders about the mesh, so this isn’t limited to Shader Graph but real time rendering in general, hence why it’s not something you see in game engines.
Many offline renderers can do this because they have full control over what mesh data the renderer does or doesn’t have, and information about adjacent faces and their normals are the kind of thing they’ve choosen to let their “shaders” have access to. Technically you can bake a lot of that information into meshes, as @andybak was alluding to above, but that has to be done using a c# script or in an external application.
Which again, using a normal map would end up being much easier to implement and faster to render.
As I mentioned above the normals are the easy bit. Whether you generate normal maps in advance or store edge adjacency in the vertices and do it on the fly - this gets you part of the way there (which one is easier probably depends on what else you’re doing with your maps).
The bit I can’t wrap my head around is the model’s profile. i.e. corners should not look sharp when viewed from the side and edges should be slightly inset.
Is this actually necessary or would softening the edges with normals be sufficient? It might depend on the amount of bevel and what kind of meshes you’re using it on.
Except for one thing: fillet radius is now fixed. It equals the distance between the edge and the supporting loop. And I can’t use it per material also, since it affects the whole mesh. Not very useful for meshes with more than one material where onle some of them are supposed to have fake round edges.
So, I wonder if it’s possible to use curvature data from Vertex Color to simulate round edges and get some control over their radius?
I can use “Normal from Height” node to get some sort of chamfers:
Now I can (!) control the radius, but it lacks roundness (I get chamfers instead of fillets).
I can modify Vertex Color in many ways, but I always end up with fillets “protruding” from the surface of geometry (like shown in the screenshot below). Like some sort of planks were attached to the edges of the cube. Or with chamfers. Or with a weird mix of both.
I can’t get nice and even round edges. And of course there are hard edges of the geometry itself visible through the fake ones (I went back to importing normals instead of calculating them from angle before using Vertex Color).
Is it possible to use this curvature information from vertex colors to create the kind of round edges I want and hide hard edges (at least to some degree) at the same time?
I’m actually really interested in that hard edges version of the shader you created in SG. For some reason i’m not able to achieve this with normal from height. Would you please share your file?
I’m using URP, is this maybe the reason it’s not working?