Hair shader with Kajiya-Kay specularity and proper sorting

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:

  • Lighting is good from certain angles, but once lights are directly pointing at the alpha blended tips, they become completely transparent
  • 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:

Name "PrimeZBuffer"
		Tags
		{
			"Queue" = "AlphaTest"
			"IgnoreProjector" = "True"
			"RenderType" = "TransparentCutout"
		}
		Cull Off				// 2 sided hair
		AlphaTest GEqual 1.0	// Only render opaque pixels
		ZWrite On
		ZTest Less
		ColorMask 0				// Disables color buffer writes 
		
		 CGPROGRAM
			#include "CustomLighting.cginc"
			#pragma surface surf KajiyaKayMarschner vertex:vert
			#pragma target 3.0

Pass 2 has these settings:

Name "RenderOpaqueRegions"
        Tags
		{
			"Queue" = "AlphaTest"
			"IgnoreProjector" = "True"
			"RenderType" = "TransparentCutout"
		}
		Cull Off				// 2 sided hair
		AlphaTest GEqual 1.0	// Only render opaque pixels
		ZWrite Off
		ZTest Equal
		
		CGPROGRAM
			#include "CustomLighting.cginc"
			#pragma surface surf KajiyaKayMarschner alpha vertex:vert
			#pragma target 3.0

Pass 3 has these:

Name "RenderTransparentBackfaces"
        Tags
		{
			"Queue" = "Transparent"
			"IgnoreProjector" = "True"
			"RenderType" = "Transparent"
		}
		Cull Front
		ZWrite Off
		ZTest Less
		Blend SrcAlpha OneMinusSrcAlpha
		
		CGPROGRAM
			#include "CustomLighting.cginc"
			#pragma surface surf KajiyaKayMarschner alpha vertex:vert
			#pragma target 3.0

And finally Pass 4:

Name "RenderTransparentFrontFaces"
        Tags
		{
			"Queue" = "Transparent+1"
			"IgnoreProjector" = "True"
			"RenderType" = "Transparent"
		}
		Cull Back
		ZWrite On
		ZTest Less
		Blend SrcAlpha OneMinusSrcAlpha
		
		CGPROGRAM
			#include "CustomLighting.cginc"
			#pragma surface surf KajiyaKayMarschner alpha vertex:vert
			#pragma target 3.0

They all have CGPROGRAMs that run the same surface shader with the lighting model that I’m working on.



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.

your efforts are appreciated!

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!

Wow cool, Do you mind to post the shader code i’m interested to check on it

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.

hey dogzerx2 I’ll trade you a kajiya-kay hair shader similar to panta’s for a nice female model with good hair to test it on = ]

see: http://forum.unity3d.com/threads/168322-Unity-Character-Surface-Shader-pack-(trailer)/page2?p=1337215&viewfull=1#post1337215

+1

Thank you for yout efforts

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
}
}
}
}

is the above directed towards me ? Just wondering if you’ve tried: Unity Asset Store - The Best Assets for Game Making
if so, what is not working ?

Thanks for any clarification.