Search Unity

Hair shader with Kajiya-Kay specularity and proper sorting

Discussion in 'Shaders' started by panta, Jan 25, 2013.

  1. panta

    panta

    Joined:
    Aug 10, 2012
    Posts:
    71
    Hey guys. Anyone who's tried to make alpha blended hair has run into the issues with Zordering, so I'm trying to create a shader for the community that will ease some of the pain.

    I'm working on implementing ATI's Hair Sketch (http://www.shaderwrangler.com/publications/hairsketch/hairsketch.pdf) in Unity's ShaderLab. I managed to get the sorting correct using just vertex and fragment shaders,


    but when I tried to include lighting using Surface Shaders, that's when I started getting weird problems. I've figured out more or less what is happening and here are the observations I have found:
    1. Lighting is good from certain angles, but once lights are directly pointing at the alpha blended tips, they become completely transparent
    2. If I use only 1 directional light, this problem does not exist. It's only with multiple lights.
    And here's some pictures to show what I mean:
    Lights are pointed away from the hair, looks pretty good:

    Strong spot light pointed directly at alpha blended tips makes them disappear:



    Does anyone have any clue why this is happening? I don't want to just dump my whole shader code in the thread, beacause it seems like most people do that when they are trying to have someone write it for them. I just want insights, but if you're interested in seeing the code, I'd be happy to post it.
    The basic gist of it is this:
    4 pass shader,
    Pass 1 has these settings:
    Code (csharp):
    1.  
    2. Name "PrimeZBuffer"
    3.         Tags
    4.         {
    5.             "Queue" = "AlphaTest"
    6.             "IgnoreProjector" = "True"
    7.             "RenderType" = "TransparentCutout"
    8.         }
    9.         Cull Off                // 2 sided hair
    10.         AlphaTest GEqual 1.0    // Only render opaque pixels
    11.         ZWrite On
    12.         ZTest Less
    13.         ColorMask 0             // Disables color buffer writes
    14.        
    15.          CGPROGRAM
    16.             #include "CustomLighting.cginc"
    17.             #pragma surface surf KajiyaKayMarschner vertex:vert
    18.             #pragma target 3.0
    19.  
    Pass 2 has these settings:
    Code (csharp):
    1.  
    2. Name "RenderOpaqueRegions"
    3.         Tags
    4.         {
    5.             "Queue" = "AlphaTest"
    6.             "IgnoreProjector" = "True"
    7.             "RenderType" = "TransparentCutout"
    8.         }
    9.         Cull Off                // 2 sided hair
    10.         AlphaTest GEqual 1.0    // Only render opaque pixels
    11.         ZWrite Off
    12.         ZTest Equal
    13.        
    14.         CGPROGRAM
    15.             #include "CustomLighting.cginc"
    16.             #pragma surface surf KajiyaKayMarschner alpha vertex:vert
    17.             #pragma target 3.0
    18.  
    Pass 3 has these:
    Code (csharp):
    1.  
    2. Name "RenderTransparentBackfaces"
    3.         Tags
    4.         {
    5.             "Queue" = "Transparent"
    6.             "IgnoreProjector" = "True"
    7.             "RenderType" = "Transparent"
    8.         }
    9.         Cull Front
    10.         ZWrite Off
    11.         ZTest Less
    12.         Blend SrcAlpha OneMinusSrcAlpha
    13.        
    14.         CGPROGRAM
    15.             #include "CustomLighting.cginc"
    16.             #pragma surface surf KajiyaKayMarschner alpha vertex:vert
    17.             #pragma target 3.0
    18.  
    And finally Pass 4:
    Code (csharp):
    1.  
    2. Name "RenderTransparentFrontFaces"
    3.         Tags
    4.         {
    5.             "Queue" = "Transparent+1"
    6.             "IgnoreProjector" = "True"
    7.             "RenderType" = "Transparent"
    8.         }
    9.         Cull Back
    10.         ZWrite On
    11.         ZTest Less
    12.         Blend SrcAlpha OneMinusSrcAlpha
    13.        
    14.         CGPROGRAM
    15.             #include "CustomLighting.cginc"
    16.             #pragma surface surf KajiyaKayMarschner alpha vertex:vert
    17.             #pragma target 3.0
    18.  
    They all have CGPROGRAMs that run the same surface shader with the lighting model that I'm working on.
     

    Attached Files:

    Last edited: Jan 25, 2013
  2. panta

    panta

    Joined:
    Aug 10, 2012
    Posts:
    71
    Fixed it haha. It was the skin shader I was using from Advanced SS. Looks like I'll have to write my own! I'll keep you guys updated on how the hair shader progresses. I think it'll be pretty good by the end.
     
  3. lazygunn

    lazygunn

    Joined:
    Jul 24, 2011
    Posts:
    2,749
    your efforts are appreciated!
     
  4. panta

    panta

    Joined:
    Aug 10, 2012
    Posts:
    71
    Thanks man! I'm hoping to release a full pack of character-specific shaders by May or so. It'll include solutions for layered alpha blended hair, parallax offset mapped eyes, and translucent/SSS skin with tesselation.

    I dig your marble game by the way - it was pretty fun and the visual style of it was really cool!
     
  5. Reanimate_L

    Reanimate_L

    Joined:
    Oct 10, 2009
    Posts:
    2,788
    Wow cool, Do you mind to post the shader code i'm interested to check on it
     
  6. dogzerx2

    dogzerx2

    Joined:
    Dec 27, 2009
    Posts:
    3,967
    Man I'm doing some hair with alpha, and I'm kind of working it out by separating hair in front, top, sides, back, and some hair locks here and there. Also adding invisible triangles to offset the center to control the z ordering a little. I'm getting acceptable results but MAN it's such a pain in the arse to deal with the glitches and artifacts.
    Please keep working on this shader!

    I noticed the Unlit soft edge cutout transparency works beautifully if you play with the slider a bit, you can get very nice soft edges and correct z ordering. The sad part it's 100% unlit. Why stop there? D-: Why not give us a soft edge with normal maps?

    I tried getting into shader scripting but I feel there isn't enough help docs for that. All I've accomplished has been done with trial and error but I have no control or comprehension over what I'm doing so I rather stick with default shaders.


    The image below is has several meshes to compose the hair, and it uses normal mapped transparency.
    The hair is separated in top, front, and left side (it's wip of course) and beard is 7 meshes. Beard works 99.9% glitch free but the actual hair is more of a challenge.
    For the hair I've started over like 6 or 7 times trying to get a right workflow. I think I can get away with some minor glitches but tbh the defailt alpha transparency is very limiting.
     
    Last edited: Apr 24, 2013
  7. invadererik

    invadererik

    Joined:
    Oct 31, 2010
    Posts:
    148
    Last edited: Aug 28, 2013
  8. Kirienko

    Kirienko

    Joined:
    Apr 5, 2013
    Posts:
    37
    +1

    Thank you for yout efforts
     
  9. OfficialHermie

    OfficialHermie

    Joined:
    Oct 12, 2012
    Posts:
    585
    Can you add this double-sided vertex lit shader to your shader? It can be found on the internet.
    This is the one that actually works for me.

    Shader "Transparent/Double-Sided Vertex Lit" {
    Properties {
    _Color ("Main Color", Color) = (1,1,1,1)
    _MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
    }
    SubShader {
    Tags {"RenderType"="Transparent" "Queue"="Transparent"}
    // Render into depth buffer only
    Pass {
    ZWrite On
    Blend SrcAlpha OneMinusSrcAlpha
    ColorMask RGB
    Cull off
    Material {
    Diffuse [_Color]
    Ambient [_Color]
    }
    Lighting On
    SetTexture [_MainTex] {
    Combine texture * primary DOUBLE, texture * primary
    }
    }
    }
    }​
     
  10. invadererik

    invadererik

    Joined:
    Oct 31, 2010
    Posts:
    148