diff options
Diffstat (limited to 'Assets/Art/Shaders/UnityChan/CharaMain.cginc')
-rw-r--r-- | Assets/Art/Shaders/UnityChan/CharaMain.cginc | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/Assets/Art/Shaders/UnityChan/CharaMain.cginc b/Assets/Art/Shaders/UnityChan/CharaMain.cginc new file mode 100644 index 00000000..f7b5fba1 --- /dev/null +++ b/Assets/Art/Shaders/UnityChan/CharaMain.cginc @@ -0,0 +1,187 @@ +// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' + +// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld' + +// Character shader +// Includes falloff shadow and highlight, specular, reflection, and normal mapping + +#define ENABLE_CAST_SHADOWS + +// Material parameters +float4 _Color; +float4 _ShadowColor; +float4 _LightColor0; +float _SpecularPower; + +float4 _MainTex_ST; + +// Textures +sampler2D _MainTex; +sampler2D _FalloffSampler; +sampler2D _RimLightSampler; +sampler2D _SpecularReflectionSampler; +sampler2D _EnvMapSampler; +sampler2D _NormalMapSampler; + +// Constants +#define FALLOFF_POWER 0.3 + +// Float types +#define float_t half +#define float2_t half2 +#define float3_t half3 +#define float4_t half4 +#define float3x3_t half3x3 + +#ifdef ENABLE_CAST_SHADOWS + +// Structure from vertex shader to fragment shader +struct v2f +{ + float4 pos : SV_POSITION; + LIGHTING_COORDS( 0, 1 ) + float2 uv : TEXCOORD2; + float3 eyeDir : TEXCOORD3; + float3 lightDir : TEXCOORD4; + float3 normal : TEXCOORD5; + #ifdef ENABLE_NORMAL_MAP + float3 tangent : TEXCOORD6; + float3 binormal : TEXCOORD7; + #endif +}; + +#else + +// Structure from vertex shader to fragment shader +struct v2f +{ + float4 pos : SV_POSITION; + float2 uv : TEXCOORD0; + float3 eyeDir : TEXCOORD1; + float3 lightDir : TEXCOORD2; + float3 normal : TEXCOORD3; + #ifdef ENABLE_NORMAL_MAP + float3 tangent : TEXCOORD4; + float3 binormal : TEXCOORD5; + #endif +}; + +#endif + +// Vertex shader +v2f vert( appdata_tan v ) +{ + v2f o; + o.pos = UnityObjectToClipPos( v.vertex ); + o.uv.xy = TRANSFORM_TEX( v.texcoord.xy, _MainTex ); + o.normal = normalize( mul( unity_ObjectToWorld, float4_t( v.normal, 0 ) ).xyz ); + + // Eye direction vector + float4 worldPos = mul( unity_ObjectToWorld, v.vertex ); + o.eyeDir.xyz = normalize( _WorldSpaceCameraPos.xyz - worldPos.xyz ).xyz; + o.lightDir = WorldSpaceLightDir( v.vertex ); + + #ifdef ENABLE_NORMAL_MAP + // Binormal and tangent (for normal map) + o.tangent = normalize( mul( unity_ObjectToWorld, float4_t( v.tangent.xyz, 0 ) ).xyz ); + o.binormal = normalize( cross( o.normal, o.tangent ) * v.tangent.w ); + #endif + + #ifdef ENABLE_CAST_SHADOWS + TRANSFER_VERTEX_TO_FRAGMENT( o ); + #endif + + return o; +} + +// Overlay blend +inline float3_t GetOverlayColor( float3_t inUpper, float3_t inLower ) +{ + float3_t oneMinusLower = float3_t( 1.0, 1.0, 1.0 ) - inLower; + float3_t valUnit = 2.0 * oneMinusLower; + float3_t minValue = 2.0 * inLower - float3_t( 1.0, 1.0, 1.0 ); + float3_t greaterResult = inUpper * valUnit + minValue; + + float3_t lowerResult = 2.0 * inLower * inUpper; + + half3 lerpVals = round(inLower); + return lerp(lowerResult, greaterResult, lerpVals); +} + +#ifdef ENABLE_NORMAL_MAP + + // Compute normal from normal map + inline float3_t GetNormalFromMap( v2f input ) + { + float3_t normalVec = tex2D( _NormalMapSampler, input.uv ).xyz * 2 - 1; + + // Fix for Metal graphics API + float3_t xBasis = float3_t( input.tangent.x, input.binormal.x, input.normal.x ); + float3_t yBasis = float3_t( input.tangent.y, input.binormal.y, input.normal.y ); + float3_t zBasis = float3_t( input.tangent.z, input.binormal.z, input.normal.z ); + + normalVec = float3_t( + dot( normalVec, xBasis ), + dot( normalVec, yBasis ), + dot( normalVec, zBasis ) + ); + normalVec = normalize( normalVec ); + + return normalVec; + } + +#endif + +// Fragment shader +float4 frag( v2f i ) : COLOR +{ + float4_t diffSamplerColor = tex2D( _MainTex, i.uv.xy ); + + #ifdef ENABLE_NORMAL_MAP + float3_t normalVec = GetNormalFromMap( i ); + #else + float3_t normalVec = i.normal; + #endif + + // Falloff. Convert the angle between the normal and the camera direction into a lookup for the gradient + float_t normalDotEye = dot( normalVec, i.eyeDir.xyz ); + float_t falloffU = clamp( 1.0 - abs( normalDotEye ), 0.02, 0.98 ); + float4_t falloffSamplerColor = FALLOFF_POWER * tex2D( _FalloffSampler, float2( falloffU, 0.25f ) ); + float3_t shadowColor = diffSamplerColor.rgb * diffSamplerColor.rgb; + float3_t combinedColor = lerp( diffSamplerColor.rgb, shadowColor, falloffSamplerColor.r ); + combinedColor *= ( 1.0 + falloffSamplerColor.rgb * falloffSamplerColor.a ); + + // Specular + // Use the eye vector as the light vector + float4_t reflectionMaskColor = tex2D( _SpecularReflectionSampler, i.uv.xy ); + float_t specularDot = dot( normalVec, i.eyeDir.xyz ); + float4_t lighting = lit( normalDotEye, specularDot, _SpecularPower ); + float3_t specularColor = saturate( lighting.z ) * reflectionMaskColor.rgb * diffSamplerColor.rgb; + combinedColor += specularColor; + + // Reflection + float3_t reflectVector = reflect( -i.eyeDir.xyz, normalVec ).xzy; + float2_t sphereMapCoords = 0.5 * ( float2_t( 1.0, 1.0 ) + reflectVector.xy ); + float3_t reflectColor = tex2D( _EnvMapSampler, sphereMapCoords ).rgb; + reflectColor = GetOverlayColor( reflectColor, combinedColor ); + + combinedColor = lerp( combinedColor, reflectColor, reflectionMaskColor.a ); + combinedColor *= _Color.rgb * _LightColor0.rgb; + float opacity = diffSamplerColor.a * _Color.a * _LightColor0.a; + + #ifdef ENABLE_CAST_SHADOWS + // Cast shadows + shadowColor = _ShadowColor.rgb * combinedColor; + float_t attenuation = saturate( 2.0 * LIGHT_ATTENUATION( i ) - 1.0 ); + combinedColor = lerp( shadowColor, combinedColor, attenuation ); + #endif + + // Rimlight + float_t rimlightDot = saturate( 0.5 * ( dot( normalVec, i.lightDir ) + 1.0 ) ); + falloffU = saturate( rimlightDot * falloffU ); + falloffU = tex2D( _RimLightSampler, float2( falloffU, 0.25f ) ).r; + float3_t lightColor = diffSamplerColor.rgb; // * 2.0; + combinedColor += falloffU * lightColor; + + return float4( combinedColor, opacity ); +} |