Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice
  3. Dismiss Notice

Question Clamping 2D Sprite-Lit Shading (Toon Shading)

Discussion in 'Universal Render Pipeline' started by Armadous, Feb 7, 2021.

  1. Armadous

    Armadous

    Joined:
    Apr 6, 2013
    Posts:
    7
    I've come up against a wall trying to create toon style shading inside the feature rich URP 2D lighting package. Shaded regions have hard edges and are a uniform color. Like this https://www.pinterest.com/pin/584834701599501394

    My understanding of shaders and the render pipeline is minimal and I've been hacking at this mostly in ignorance. Any guidance, even if its that I've gone about this in the worst way possible is greatly appreciated. I concluded that shader graph wouldn't allow me to modify how color was computed from the normal map so tried modifying the 2D shaders.

    This is the modification I made to LightingUtility.hlsl
    Code (csharp):
    1. lightColor = lightColor * lerp(1, .5, step(dot(dirToLight, normalUnpacked), 0.65));
    My art style is pixel 2.5D and I intend to hand paint the normal maps. For that reason I have restricted myself to a discreet set of normal colors. Here is my normal pallet and I have manual colored the shading I expect given a light slight to the right and above the surface.

    mspaint_ZCoJiCFU3q.png

    What I actually get is not what I expected. Shadow lines appear across planer normal regions. I believe this comes from the angle to the light source being unique to each pixel. Thus coplanar pixels can be split by the shading.

    Unity_soJibf5NBv.png

    I believe the solution is to instead compute the distance from the origin of the lit object to the light source however I can find no way to know the object origin of a pixel in the shader and compute all shading from that point instead.

    The same issue, just illustrated using an actual asset (a post standing vertically). The smoothly shaded circle on the right is just another test surface that uses a uniform normal map of a sphere.
    Unity_Xtw2b7WSv0.png

    mspaint_FUmblE9xeU.png

    As I mentioned, I know basically nothing about writing shaders and I'm quite out of my depth. Any help is appreciated.
     
  2. Armadous

    Armadous

    Joined:
    Apr 6, 2013
    Posts:
    7
    After doing a little more experimenting, I'm pretty confident the shading artifacts are coming from needing to compute light angles per object, and not per pixel.

    oiJE53bzyV.gif

    If I remove the pixel location from the direction to light computation, and place objects at 0,0, the stylized normal face lighting looks perfect. The obvious issue being I can't place all of my game objects at the origin.

    How do I "bake" the object position into all of my pixels? Or better yet, how do I not have to do that to achieve this effect?