//////////////////////////////
// Hair Fx
//////////////////////////////
//////////////////////////////
// Matrix
//////////////////////////////
float4x4 matWorldViewProj;
float4x4 matWorld;
float4x4 matView;
float4x4 matWorldInv;
float4x4 matViewInv;
//////////////////////////////
// Lighting
//////////////////////////////
float4 vecLightPos[8];
float4 vecLightColor[8];
float4 vecAmbient;
float4 vecDiffuse;
float4 vecSpecular;
//////////////////////////////
// Coloring
//////////////////////////////
float specExp1 = 10;
float specExp2 = 0;
//////////////////////////////
// Tweakables
//////////////////////////////
float primeShift = 10;
float secondShift = 15;
//////////////////////////////
// Texture Reference
//////////////////////////////
texture entSkin1;
texture entSkin2;
texture entSkin3;
texture entSkin4;
sampler2D ColorSampler = sampler_state
{
Texture = entSkin1;
MinFilter = Linear;
MagFilter = Linear;
MipFilter = Linear;
AddressU = WRAP;
AddressV = WRAP;
};
sampler ShiftSampler = sampler_state
{
Texture = entSkin2;
MinFilter = Linear;
MagFilter = Linear;
MipFilter = Linear;
AddressU = WRAP;
AddressV = WRAP;
};
sampler SpecSampler = sampler_state
{
Texture = entSkin3;
MinFilter = Linear;
MagFilter = Linear;
MipFilter = Linear;
AddressU = WRAP;
AddressV = WRAP;
};
sampler AmbOccSampler = sampler_state
{
Texture = entSkin3;
MinFilter = Linear;
MagFilter = Linear;
MipFilter = Linear;
AddressU = WRAP;
AddressV = WRAP;
};
//////////////////////////////
// Data Structs
//////////////////////////////
struct appdata
{
float3 Position : POSITION;
float4 UV : TEXCOORD0;
float4 Normal : NORMAL;
float4 Tangent : TANGENT0;
float4 Binormal : BINORMAL0;
};
struct vertexOutput
{
float4 HPosition : POSITION;
float2 UV : TEXCOORD0;
float3 LightVec : TEXCOORD1;
float3 WorldNormal : TEXCOORD2;
float3 WorldTangent : TEXCOORD3;
float3 WorldBinormal : TEXCOORD4;
float3 WorldView : TEXCOORD5;
float4 LightColor : COLOR0;
};
//////////////////////////////
// Additonal Functions
//////////////////////////////
float3 ShiftTangent(float3 T, float3 N, float shift)
{
float3 shifttedT = T + shift * N;
return normalize(shifttedT);
}
float StrandSpecular(float3 T, float3 V, float3 L, float exponet)
{
float3 H = normalize(L+V);
float dotTh = dot(T,H);
float sinTh = sqrt(1.0 - dotTh * dotTh);
float dirAtten = smoothstep(-1.0,0.0, dot(T,H));
return dirAtten * pow(sinTh,exponet);
}
float4 DoPointLight(float3 P, float3 N, int i)
{
// calculate the light ray pointing from the light to the surface
float3 D = (float3)vecLightPos[i]-P;
// calculate the angle between surface and light ray
float NdotL = dot(N,normalize(D));
// modulate the light by the surface angle
float4 Color = vecLightColor[i] * NdotL;
// calculate the light attenuation factor
float fac = 0.f;
if (NdotL >= 0.f && vecLightPos[i].w > 0.f)
{
// get the distance factor
float LD = length(D)/vecLightPos[i].w;
if (LD < 1.f)
fac = 1.f - LD;
}
return Color * fac;
}
//////////////////////////////
// Vertex Shader
//////////////////////////////
vertexOutput simpleVS(appdata IN)
{
vertexOutput OUT = (vertexOutput)0;
OUT.WorldNormal = mul(IN.Normal,matWorldInv).xyz;
OUT.WorldTangent = mul(IN.Tangent,matWorldInv).xyz;
OUT.WorldBinormal = mul(IN.Binormal,matWorldInv).xyz;
float4 Po = float4(IN.Position.xyz,1); // homogeneous location
float4 Pw = mul(Po,matWorld); // convert to "world" space
float3 N = normalize(IN.Normal);
float3 P = mul(IN.Position,matWorld);
for (int i=0; i<8; i++)
{
OUT.LightVec = vecLightPos[i] - Pw.xyz;
OUT.LightColor += DoPointLight(P,N,i);
}
OUT.UV = IN.UV.xy;
OUT.WorldView = normalize(matViewInv[3].xyz - Pw.xyz);
OUT.HPosition = mul(Po,matWorldViewProj);
return OUT;
}
//////////////////////////////
// Pixle Shader
//////////////////////////////
float4 hairPS_t(vertexOutput IN) : COLOR
{
float shiftTex = tex2D(ShiftSampler, IN.UV) - 0.5;
float t1 = ShiftTangent(IN.WorldTangent,IN.WorldNormal,primeShift+shiftTex);
float t2 = ShiftTangent(IN.WorldTangent,IN.WorldNormal,secondShift+shiftTex);
float3 diffuse = saturate(lerp(0.25,1.0,dot(IN.WorldNormal,IN.LightVec)));
diffuse*=vecDiffuse.rgb;
float3 specular = vecSpecular * StrandSpecular(t1,IN.WorldView,IN.LightVec,specExp1);
float specMask = tex2D(SpecSampler,IN.UV);
specular+= vecSpecular * specMask * StrandSpecular(t2,IN.WorldView,IN.LightVec,specExp2);
float4 FinalColor = (0.0,0.0,0.0,1.0);
float4 Color = tex2D(ColorSampler,IN.UV);
FinalColor.rgb = (diffuse+specular) * Color.rgb * IN.LightColor;
FinalColor.rgb*= tex2D(AmbOccSampler,IN.UV).rgb;
FinalColor.a = Color.a;
return Color;
}
///////////////////////////////////////
/// TECHNIQUES
////////////////////////
technique Hair
{
pass p0
{
ZEnable = true;
ZWriteEnable = true;
CullMode = ccw;
ZFunc = Less;
AlphaBlendEnable=true;
//SrcBlend=srcalpha;
//DestBlend=invsrcColor;
AlphaTestEnable = True;
BlendOpAlpha = ADD;
VertexShader = compile vs_2_0 simpleVS();
PixelShader = compile ps_2_0 hairPS_t();
}
}