Search Unity

Question How to fadeout outside edges (from camera perspective) of a material applied to a 3D object?

Discussion in 'Shader Graph' started by vidocco, May 25, 2023.

  1. vidocco

    vidocco

    Joined:
    Jul 19, 2019
    Posts:
    5
    Hi!

    I'm working on a sort-of "outline" material for 3D objects (similar to the many "toon shader" outlines posted everywhere) using shader graph and URP. The main difference between my version and the standard "toon" version is that I need to "fade-out" the edges the further away they are from the given object (example for reference, I want to imitate the white outline that surrounds the soldier in the center).

    For now, I've created a material that multiplies the vertex positions of an object by a float, renders only back faces and uses the `Render Objects` feature of the render pipeline to apply this to a specific layer. This results in a perfect and straight outline appearing behind the object in the scene. I'm currently using unity 2023.3.1, so I tried using a "Full Screen Shader" for this, but it currently does not (seem to) support an effect being applied to only specific layers/objects, which I need to do since the effect is only going to be applied to specific objects.

    To generate the alpha-fade I'm using the distance node between the fragment position and another position (tried using object center and bounds min/max), plugging that into a smoothstep node (with public floats for edges 1/2) and using that as the alpha in the shader. I'm using a perspective camera but it does not rotate or change it's FOV (always pinned at a 35º angle), it's a top-down strategy game, so luckily I have quite a bit of control over viewing angles (for instance, back of the object will very rarely be seen).

    The issue with this "fading" is that it should happen on a "2D" plane, which is making "applying the gradient" kind of complicated (since it's still a 3D object). My first attempt consisted on using a lot of logic/branching to detect if a specific fragment should be faded or not depending on it's depth; this worked for the most part but led to a space appearing between the bottom-x fade and the sides of the object (which really killed the "2D" effect).

    My current attempt consists on trying to "2D-ify" the 3D shape by using the screen position of a fragment, transforming bounds min/max into screen position too and applying same distance/smooth step logic described above. The issue with this is that the depth of each fragment/bounds causes the distance to shift massively depending on the zoom level of the camera (which is a feature we have in the game).

    My "ideal" solution would be rendering a quad with a single color behind the game object that adapts/distorts to the edges of the object from the camera's perspective, but I have no clue of how to go about doing this in a shader/material (and would rather avoid using computing power for this effect, since there's a lot of shapes that will have this effect applied).

    I've been at this for a few days now and running out of ideas, any suggestions/pointers/ideas would be hugely appreciated.