//////////////////////////////
// Organic Skin Shader
// Converted John C Leutz II
//////////////////////////////
//////////////////////////////
// Matrix
//////////////////////////////;
float4x4 matWorldViewProj;
float4x4 matWorld;
float4x4 matView;
float4x4 matWorldInv;
float4x4 matViewInv;
//////////////////////////////
// Lighting
//////////////////////////////
float4 vecLightPos[8];
float4 vecLightColor[8];
float4 vecAmbient;
//////////////////////////////
// Coloring
//////////////////////////////
float4 DiffColor = {0.9f, 1.0f, 0.9f, 1.0f};
float4 AmbiColor = {0.1f, 0.1f, 0.1f, 1.0f};
float4 SubColor = {1.0f, 0.2f, 0.2f, 1.0f};
float3 SpecColor = {0.7f, 0.7f, 1.0f};
float GlossTopUI = 0.46;
float GlossBotUI = 0.41;
float GlossDrop = 0.25;
float RollOff = 0.2;
float Ks = 0.5;
float SpecExpon = 6.0;
float PhongExp = 128.0;
//////////////////////////////
// Texture Reference
//////////////////////////////
texture entSkin1;
texture entSkin2;
texture entSkin3;
sampler2D ColorSampler = sampler_state
{
Texture = entSkin1;
MinFilter = Linear;
MagFilter = Linear;
MipFilter = Linear;
AddressU = WRAP;
AddressV = WRAP;
};
sampler NormalSampler = sampler_state
{
Texture = entSkin2;
MinFilter = Linear;
MagFilter = Linear;
MipFilter = Linear;
AddressU = WRAP;
AddressV = WRAP;
};
sampler GlossSampler = sampler_state
{
Texture = entSkin3;
MinFilter = Linear;
MagFilter = Linear;
MipFilter = Linear;
AddressU = WRAP;
AddressV = WRAP;
};
//////////////////////////////
// Data Structs
//////////////////////////////
struct appdata
{
float3 Pos : POSITION;
float4 UV : TEXCOORD0;
float4 Norm : NORMAL;
float4 Tangent : TANGENT0;
float4 Binormal : BINORMAL0;
float4 Color : COLOR0;
};
/* data passed from vertex shader to pixel shader */
struct vertexOutput
{
half4 Pos : POSITION;
half4 Tex : TEXCOORD0;
half3 Light : TEXCOORD1;
half3 WorldNorm : TEXCOORD2;
float3 WorldTangent : TEXCOORD3;
float3 WorldBinormal: TEXCOORD4;
float3 WorldView : TEXCOORD5;
float4 Color : COLOR0;
};
//////////////////////////////
// Vertex Shader
//////////////////////////////
void lambskin(float3 N,float3 L,out float4 Diffuse,out float4 Subsurface)
{
float ldn = dot(L,N);
float diffComp = max(0,ldn);
Diffuse = float4((diffComp * DiffColor).xyz,1);
float subLamb = smoothstep(-RollOff,1.0,ldn) - smoothstep(0.0,1.0,ldn);
subLamb = max(0.0,subLamb);
Subsurface = subLamb * SubColor;
}
float glossy_drop(float v,
uniform float top,
uniform float bot,
uniform float drop)
{
return (drop+smoothstep(bot,top,v)*(1.0-drop));
}
vertexOutput simpleVS(appdata IN)
{
vertexOutput OUT;
half4 Po = half4(IN.Pos.xyz,1);
OUT.Pos = mul(Po, matWorldViewProj);
OUT.Tex = IN.UV;
float4 vN = normalize(IN.Norm);
OUT.Light = float4(0.f,0.f,0.f,0.f);
OUT.WorldNorm = mul(vN, matWorldInv).xyz;
OUT.WorldTangent = mul(IN.Tangent,matWorldInv).xyz;
OUT.WorldBinormal = mul(IN.Binormal,matWorldInv).xyz;
half3 Pw = mul(Po, matWorld).xyz;
for (int i=0; i<8; i++)
{
OUT.Light+= normalize(vecLightPos[i] - Pw);
}
OUT.WorldView = normalize(matViewInv[3].xyz - Pw.xyz);
OUT.Color = IN.Color;
return OUT;
}
//////////////////////////////
// Pixle Shader
//////////////////////////////
void lamb_ps_shared(vertexOutput IN,out float4 DiffuseContrib,out float4 SubContrib)
{
half3 Ln = normalize(IN.Light);
half3 Nn = normalize(IN.WorldNorm);
lambskin(Nn,Ln,DiffuseContrib,SubContrib);
}
void gloss_shared(vertexOutput IN,
uniform float3 SurfaceColor,
uniform float Ks,
uniform float SpecExpon,
uniform float3 SpecColor,
uniform float GlossTopUI,
uniform float GlossBotUI,
uniform float GlossDrop,
uniform float3 AmbiColor,
out float3 DiffuseContrib,
out float3 SpecularContrib)
{
float3 Ln = normalize(IN.Light.xyz);
float3 Nn = normalize(IN.WorldNorm);
float3 Vn = normalize(IN.WorldView);
float3 Hn = normalize(Vn + Ln);
float4 litV = lit(dot(Ln,Nn),dot(Hn,Nn),SpecExpon);
float spec = litV.y * litV.z;
float GlossTop = max(GlossTopUI,GlossBotUI);
float GlossBot = min(GlossTopUI,GlossBotUI);
spec *= (Ks * glossy_drop(spec,GlossTop,GlossBot,GlossDrop));
SpecularContrib = spec * SpecColor;
DiffuseContrib = litV.y * SurfaceColor + AmbiColor;
}
float4 lambPS_t(vertexOutput IN) : COLOR
{
float4 diffContrib;
float4 subContrib;
float3 specContrib;
float4 Color = tex2D(ColorSampler, IN.Tex);
float4 Gloss = tex2D(GlossSampler,IN.Tex);
float3 Bump = tex2D(NormalSampler,IN.Tex).xyz - float3(0.5,0.5,0.5);
//LambSkin
lamb_ps_shared(IN,diffContrib,subContrib);
float4 litC = diffContrib + AmbiColor + subContrib;
//Gloss
gloss_shared(IN,Color.rgb,Ks,SpecExpon,Gloss.rgb,GlossTopUI,GlossBotUI,GlossDrop,AmbiColor,diffContrib.rgb,specContrib);
float3 FinalSpec = diffContrib + specContrib;
//NormalMap
// transform tNorm to world space
Bump = normalize(Bump.x*IN.WorldTangent - Bump.y*IN.WorldBinormal + Bump.z*IN.WorldNorm);
// view and light directions
float3 Vn = normalize(IN.WorldView);
float3 Ln = normalize(IN.Light.xyz-IN.WorldView);
// compute diffuse and specular terms
FinalSpec = saturate(dot(normalize(Ln-Vn),Bump));
FinalSpec = pow(FinalSpec,PhongExp);
float4 FinalColor = (litC*Color)*(FinalSpec,1);
FinalColor.a=1;
return FinalColor;
}
technique HumanSkin
{
pass p0
{
ZEnable = true;
ZWriteEnable = true;
CullMode = None;
ZFunc = LessEqual;
AlphaBlendEnable = false;
VertexShader = compile vs_2_0 simpleVS();
PixelShader = compile ps_2_0 lambPS_t();
}
}