Files
FreewayGamesTest/Assets/Synaptic AI Pro/Shaders/Character/SynapticEyePro.shader
T

849 lines
30 KiB
Plaintext

Shader "Synaptic/EyePro"
{
Properties
{
[Header(Iris)]
_IrisColor ("Iris Color", Color) = (0.3, 0.5, 0.8, 1)
_IrisTex ("Iris Texture", 2D) = "white" {}
_IrisSize ("Iris Size", Range(0.1, 1)) = 0.5
_IrisDepth ("Iris Depth (Parallax)", Range(0, 0.5)) = 0.15
[Header(Pupil)]
_PupilColor ("Pupil Color", Color) = (0.05, 0.05, 0.1, 1)
_PupilSize ("Pupil Size", Range(0.05, 0.5)) = 0.2
_PupilDilation ("Pupil Dilation", Range(0.5, 2)) = 1.0
_PupilSharpness ("Pupil Sharpness", Range(1, 20)) = 10
[Header(Sclera)]
_ScleraColor ("Sclera Color", Color) = (1, 0.98, 0.95, 1)
_ScleraTex ("Sclera Texture", 2D) = "white" {}
[Header(Cornea Reflection)]
_ReflectionStrength ("Reflection Strength", Range(0, 2)) = 1.0
_ReflectionSmoothness ("Reflection Smoothness", Range(0, 1)) = 0.95
_Cubemap ("Environment Map", CUBE) = "" {}
[Header(Highlight)]
_Highlight1Pos ("Highlight 1 Position", Vector) = (0.2, 0.3, 0, 0)
_Highlight1Size ("Highlight 1 Size", Range(0, 0.3)) = 0.08
_Highlight1Strength ("Highlight 1 Strength", Range(0, 2)) = 1.5
_Highlight2Pos ("Highlight 2 Position", Vector) = (-0.15, -0.2, 0, 0)
_Highlight2Size ("Highlight 2 Size", Range(0, 0.2)) = 0.04
_Highlight2Strength ("Highlight 2 Strength", Range(0, 2)) = 0.8
[Header(Limbal Ring)]
_LimbalColor ("Limbal Ring Color", Color) = (0.1, 0.15, 0.2, 1)
_LimbalWidth ("Limbal Ring Width", Range(0, 0.3)) = 0.1
_LimbalStrength ("Limbal Ring Strength", Range(0, 2)) = 1.0
[Header(Caustics)]
_CausticsStrength ("Caustics Strength", Range(0, 1)) = 0.3
_CausticsScale ("Caustics Scale", Range(1, 20)) = 8
_CausticsSpeed ("Caustics Speed", Range(0, 2)) = 0.5
[Header(Subsurface)]
_SSSColor ("SSS Color", Color) = (1, 0.3, 0.2, 1)
_SSSStrength ("SSS Strength", Range(0, 1)) = 0.2
[Header(Rim Light)]
_RimColor ("Rim Color", Color) = (0.8, 0.9, 1, 1)
_RimPower ("Rim Power", Range(0.5, 10)) = 4
_RimStrength ("Rim Strength", Range(0, 2)) = 0.5
[Header(Shadow)]
_ShadowColor ("Shadow Color", Color) = (0.3, 0.3, 0.4, 1)
_ShadowThreshold ("Shadow Threshold", Range(0, 1)) = 0.5
}
HLSLINCLUDE
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
CBUFFER_START(UnityPerMaterial)
float4 _IrisColor;
float4 _IrisTex_ST;
float _IrisSize;
float _IrisDepth;
float4 _PupilColor;
float _PupilSize;
float _PupilDilation;
float _PupilSharpness;
float4 _ScleraColor;
float _ReflectionStrength;
float _ReflectionSmoothness;
float4 _Highlight1Pos;
float _Highlight1Size;
float _Highlight1Strength;
float4 _Highlight2Pos;
float _Highlight2Size;
float _Highlight2Strength;
float4 _LimbalColor;
float _LimbalWidth;
float _LimbalStrength;
float _CausticsStrength;
float _CausticsScale;
float _CausticsSpeed;
float4 _SSSColor;
float _SSSStrength;
float4 _RimColor;
float _RimPower;
float _RimStrength;
float4 _ShadowColor;
float _ShadowThreshold;
CBUFFER_END
TEXTURE2D(_IrisTex);
SAMPLER(sampler_IrisTex);
TEXTURE2D(_ScleraTex);
SAMPLER(sampler_ScleraTex);
TEXTURECUBE(_Cubemap);
SAMPLER(sampler_Cubemap);
// Simple noise for caustics
float noise2D(float2 p)
{
return frac(sin(dot(p, float2(127.1, 311.7))) * 43758.5453);
}
float smoothNoise(float2 p)
{
float2 i = floor(p);
float2 f = frac(p);
f = f * f * (3.0 - 2.0 * f);
float a = noise2D(i);
float b = noise2D(i + float2(1, 0));
float c = noise2D(i + float2(0, 1));
float d = noise2D(i + float2(1, 1));
return lerp(lerp(a, b, f.x), lerp(c, d, f.x), f.y);
}
float caustics(float2 uv, float time)
{
float c1 = smoothNoise(uv * _CausticsScale + time * 0.5);
float c2 = smoothNoise(uv * _CausticsScale * 1.3 - time * 0.3);
return pow(c1 * c2, 2) * 4.0;
}
ENDHLSL
// ==================== URP SubShader ====================
SubShader
{
PackageRequirements { "com.unity.render-pipelines.universal" }
Tags
{
"RenderType" = "Opaque"
"RenderPipeline" = "UniversalPipeline"
"Queue" = "Geometry"
}
Pass
{
Name "ForwardLit"
Tags { "LightMode" = "UniversalForward" }
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE
#pragma multi_compile_fog
struct Attributes
{
float4 positionOS : POSITION;
float3 normalOS : NORMAL;
float4 tangentOS : TANGENT;
float2 uv : TEXCOORD0;
};
struct Varyings
{
float4 positionCS : SV_POSITION;
float2 uv : TEXCOORD0;
float3 positionWS : TEXCOORD1;
float3 normalWS : TEXCOORD2;
float3 tangentWS : TEXCOORD3;
float3 bitangentWS : TEXCOORD4;
float3 viewDirTS : TEXCOORD5;
float fogFactor : TEXCOORD6;
};
Varyings vert(Attributes input)
{
Varyings output;
VertexPositionInputs posInputs = GetVertexPositionInputs(input.positionOS.xyz);
VertexNormalInputs normalInputs = GetVertexNormalInputs(input.normalOS, input.tangentOS);
output.positionCS = posInputs.positionCS;
output.positionWS = posInputs.positionWS;
output.normalWS = normalInputs.normalWS;
output.tangentWS = normalInputs.tangentWS;
output.bitangentWS = normalInputs.bitangentWS;
output.uv = input.uv;
// Tangent space view direction for parallax
float3 viewDirWS = GetWorldSpaceViewDir(posInputs.positionWS);
float3x3 TBN = float3x3(normalInputs.tangentWS, normalInputs.bitangentWS, normalInputs.normalWS);
output.viewDirTS = mul(TBN, viewDirWS);
output.fogFactor = ComputeFogFactor(posInputs.positionCS.z);
return output;
}
half4 frag(Varyings input) : SV_Target
{
// Centered UV
float2 centeredUV = input.uv - 0.5;
float dist = length(centeredUV);
// Parallax offset for iris depth
float3 viewDirTS = normalize(input.viewDirTS);
float2 parallaxOffset = viewDirTS.xy / viewDirTS.z * _IrisDepth;
float2 irisUV = centeredUV + parallaxOffset;
float irisDist = length(irisUV);
// Pupil (with dilation)
float pupilRadius = _PupilSize * _PupilDilation;
float pupilMask = 1.0 - saturate(pow(irisDist / pupilRadius, _PupilSharpness));
// Iris mask
float irisMask = saturate(1.0 - smoothstep(_IrisSize - 0.05, _IrisSize + 0.05, irisDist));
irisMask *= (1.0 - pupilMask);
// Limbal ring
float limbalDist = abs(irisDist - _IrisSize);
float limbalMask = (1.0 - smoothstep(0, _LimbalWidth, limbalDist)) * irisMask;
// Sample iris texture
float2 irisTexUV = (irisUV / _IrisSize) * 0.5 + 0.5;
half4 irisTex = SAMPLE_TEXTURE2D(_IrisTex, sampler_IrisTex, irisTexUV);
// Sample sclera
half4 scleraTex = SAMPLE_TEXTURE2D(_ScleraTex, sampler_ScleraTex, input.uv);
// Build eye color
float3 eyeColor = _ScleraColor.rgb * scleraTex.rgb;
eyeColor = lerp(eyeColor, _IrisColor.rgb * irisTex.rgb, irisMask);
eyeColor = lerp(eyeColor, _LimbalColor.rgb, limbalMask * _LimbalStrength);
eyeColor = lerp(eyeColor, _PupilColor.rgb, pupilMask);
// Caustics inside iris
float time = _Time.y * _CausticsSpeed;
float causticsValue = caustics(irisUV * 2.0, time);
eyeColor += causticsValue * _CausticsStrength * irisMask * (1.0 - pupilMask);
// Normalize vectors
float3 N = normalize(input.normalWS);
float3 V = normalize(GetWorldSpaceViewDir(input.positionWS));
// Get main light
Light mainLight = GetMainLight(TransformWorldToShadowCoord(input.positionWS));
float3 L = mainLight.direction;
// Toon shading
float NdotL = dot(N, L);
float halfLambert = NdotL * 0.5 + 0.5;
float shadow = step(_ShadowThreshold, halfLambert) * mainLight.shadowAttenuation;
float3 diffuse = lerp(_ShadowColor.rgb, float3(1,1,1), shadow);
// Environment reflection (cornea)
float3 reflectDir = reflect(-V, N);
float3 envReflection = SAMPLE_TEXTURECUBE_LOD(_Cubemap, sampler_Cubemap, reflectDir, (1.0 - _ReflectionSmoothness) * 6.0).rgb;
float fresnel = pow(1.0 - saturate(dot(N, V)), 3.0);
float3 reflection = envReflection * _ReflectionStrength * fresnel;
// Highlights (anime style)
float2 hl1UV = centeredUV - _Highlight1Pos.xy;
float hl1 = 1.0 - saturate(length(hl1UV) / _Highlight1Size);
hl1 = pow(hl1, 2.0) * _Highlight1Strength;
float2 hl2UV = centeredUV - _Highlight2Pos.xy;
float hl2 = 1.0 - saturate(length(hl2UV) / _Highlight2Size);
hl2 = pow(hl2, 2.0) * _Highlight2Strength;
float3 highlights = float3(1,1,1) * (hl1 + hl2);
// Subsurface scattering
float sss = pow(saturate(dot(-V, L)), 3.0) * _SSSStrength;
float3 sssColor = _SSSColor.rgb * sss;
// Rim light
float NdotV = saturate(dot(N, V));
float rim = pow(1.0 - NdotV, _RimPower) * _RimStrength;
float3 rimColor = _RimColor.rgb * rim;
// Combine
float3 finalColor = eyeColor * diffuse * mainLight.color;
finalColor += reflection;
finalColor += highlights;
finalColor += sssColor;
finalColor += rimColor;
finalColor = MixFog(finalColor, input.fogFactor);
return half4(finalColor, 1);
}
ENDHLSL
}
// Shadow Caster
Pass
{
Name "ShadowCaster"
Tags { "LightMode" = "ShadowCaster" }
ZWrite On
ZTest LEqual
ColorMask 0
HLSLPROGRAM
#pragma vertex vertShadow
#pragma fragment fragShadow
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
float3 _LightDirection;
float3 ApplyShadowBiasCustom(float3 positionWS, float3 normalWS, float3 lightDirection)
{
float invNdotL = 1.0 - saturate(dot(lightDirection, normalWS));
float scale = invNdotL * 0.001;
positionWS = lightDirection * 0.001 + positionWS;
positionWS = normalWS * scale.xxx + positionWS;
return positionWS;
}
struct Attributes
{
float4 positionOS : POSITION;
float3 normalOS : NORMAL;
};
struct Varyings
{
float4 positionCS : SV_POSITION;
};
Varyings vertShadow(Attributes input)
{
Varyings output;
float3 posWS = TransformObjectToWorld(input.positionOS.xyz);
float3 normalWS = TransformObjectToWorldNormal(input.normalOS);
posWS = ApplyShadowBiasCustom(posWS, normalWS, _LightDirection);
output.positionCS = TransformWorldToHClip(posWS);
#if UNITY_REVERSED_Z
output.positionCS.z = min(output.positionCS.z, UNITY_NEAR_CLIP_VALUE);
#else
output.positionCS.z = max(output.positionCS.z, UNITY_NEAR_CLIP_VALUE);
#endif
return output;
}
half4 fragShadow(Varyings input) : SV_Target
{
return 0;
}
ENDHLSL
}
// Depth Only
Pass
{
Name "DepthOnly"
Tags { "LightMode" = "DepthOnly" }
ZWrite On
ColorMask 0
HLSLPROGRAM
#pragma vertex vertDepth
#pragma fragment fragDepth
struct Attributes
{
float4 positionOS : POSITION;
};
struct Varyings
{
float4 positionCS : SV_POSITION;
};
Varyings vertDepth(Attributes input)
{
Varyings output;
output.positionCS = TransformObjectToHClip(input.positionOS.xyz);
return output;
}
half4 fragDepth(Varyings input) : SV_Target
{
return 0;
}
ENDHLSL
}
}
// ==================== Built-in SubShader ====================
SubShader
{
Tags
{
"RenderType" = "Opaque"
"Queue" = "Geometry"
}
Pass
{
Name "ForwardBase"
Tags { "LightMode" = "ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fwdbase
#pragma multi_compile_fog
#include "UnityCG.cginc"
#include "Lighting.cginc"
#include "AutoLight.cginc"
sampler2D _IrisTex;
float4 _IrisTex_ST;
sampler2D _ScleraTex;
samplerCUBE _Cubemap;
fixed4 _IrisColor;
float _IrisSize;
float _IrisDepth;
fixed4 _PupilColor;
float _PupilSize;
float _PupilDilation;
float _PupilSharpness;
fixed4 _ScleraColor;
float _ReflectionStrength;
float _ReflectionSmoothness;
float4 _Highlight1Pos;
float _Highlight1Size;
float _Highlight1Strength;
float4 _Highlight2Pos;
float _Highlight2Size;
float _Highlight2Strength;
fixed4 _LimbalColor;
float _LimbalWidth;
float _LimbalStrength;
float _CausticsStrength;
float _CausticsScale;
float _CausticsSpeed;
fixed4 _SSSColor;
float _SSSStrength;
fixed4 _RimColor;
float _RimPower;
float _RimStrength;
fixed4 _ShadowColor;
float _ShadowThreshold;
struct appdata
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 tangent : TANGENT;
float2 uv : TEXCOORD0;
};
struct v2f
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float3 worldPos : TEXCOORD1;
float3 worldNormal : TEXCOORD2;
float3 viewDirTS : TEXCOORD3;
UNITY_FOG_COORDS(4)
SHADOW_COORDS(5)
};
float noise2D(float2 p)
{
return frac(sin(dot(p, float2(127.1, 311.7))) * 43758.5453);
}
float smoothNoise(float2 p)
{
float2 i = floor(p);
float2 f = frac(p);
f = f * f * (3.0 - 2.0 * f);
float a = noise2D(i);
float b = noise2D(i + float2(1, 0));
float c = noise2D(i + float2(0, 1));
float d = noise2D(i + float2(1, 1));
return lerp(lerp(a, b, f.x), lerp(c, d, f.x), f.y);
}
float caustics(float2 uv, float time)
{
float c1 = smoothNoise(uv * _CausticsScale + time * 0.5);
float c2 = smoothNoise(uv * _CausticsScale * 1.3 - time * 0.3);
return pow(c1 * c2, 2) * 4.0;
}
v2f vert(appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
o.worldNormal = UnityObjectToWorldNormal(v.normal);
float3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
float3 worldBitangent = cross(o.worldNormal, worldTangent) * v.tangent.w;
float3 viewDirWS = normalize(_WorldSpaceCameraPos - o.worldPos);
float3x3 TBN = float3x3(worldTangent, worldBitangent, o.worldNormal);
o.viewDirTS = mul(TBN, viewDirWS);
UNITY_TRANSFER_FOG(o, o.pos);
TRANSFER_SHADOW(o);
return o;
}
fixed4 frag(v2f i) : SV_Target
{
float2 centeredUV = i.uv - 0.5;
float dist = length(centeredUV);
float3 viewDirTS = normalize(i.viewDirTS);
float2 parallaxOffset = viewDirTS.xy / viewDirTS.z * _IrisDepth;
float2 irisUV = centeredUV + parallaxOffset;
float irisDist = length(irisUV);
float pupilRadius = _PupilSize * _PupilDilation;
float pupilMask = 1.0 - saturate(pow(irisDist / pupilRadius, _PupilSharpness));
float irisMask = saturate(1.0 - smoothstep(_IrisSize - 0.05, _IrisSize + 0.05, irisDist));
irisMask *= (1.0 - pupilMask);
float limbalDist = abs(irisDist - _IrisSize);
float limbalMask = (1.0 - smoothstep(0, _LimbalWidth, limbalDist)) * irisMask;
float2 irisTexUV = (irisUV / _IrisSize) * 0.5 + 0.5;
fixed4 irisTex = tex2D(_IrisTex, irisTexUV);
fixed4 scleraTex = tex2D(_ScleraTex, i.uv);
float3 eyeColor = _ScleraColor.rgb * scleraTex.rgb;
eyeColor = lerp(eyeColor, _IrisColor.rgb * irisTex.rgb, irisMask);
eyeColor = lerp(eyeColor, _LimbalColor.rgb, limbalMask * _LimbalStrength);
eyeColor = lerp(eyeColor, _PupilColor.rgb, pupilMask);
float time = _Time.y * _CausticsSpeed;
float causticsValue = caustics(irisUV * 2.0, time);
eyeColor += causticsValue * _CausticsStrength * irisMask * (1.0 - pupilMask);
float3 N = normalize(i.worldNormal);
float3 V = normalize(_WorldSpaceCameraPos - i.worldPos);
float3 L = normalize(_WorldSpaceLightPos0.xyz);
float atten = SHADOW_ATTENUATION(i);
float NdotL = dot(N, L);
float halfLambert = NdotL * 0.5 + 0.5;
float shadow = step(_ShadowThreshold, halfLambert) * atten;
float3 diffuse = lerp(_ShadowColor.rgb, float3(1,1,1), shadow);
float3 reflectDir = reflect(-V, N);
float3 envReflection = texCUBElod(_Cubemap, float4(reflectDir, (1.0 - _ReflectionSmoothness) * 6.0)).rgb;
float fresnel = pow(1.0 - saturate(dot(N, V)), 3.0);
float3 reflection = envReflection * _ReflectionStrength * fresnel;
float2 hl1UV = centeredUV - _Highlight1Pos.xy;
float hl1 = 1.0 - saturate(length(hl1UV) / _Highlight1Size);
hl1 = pow(hl1, 2.0) * _Highlight1Strength;
float2 hl2UV = centeredUV - _Highlight2Pos.xy;
float hl2 = 1.0 - saturate(length(hl2UV) / _Highlight2Size);
hl2 = pow(hl2, 2.0) * _Highlight2Strength;
float3 highlights = float3(1,1,1) * (hl1 + hl2);
float sss = pow(saturate(dot(-V, L)), 3.0) * _SSSStrength;
float3 sssColor = _SSSColor.rgb * sss;
float NdotV = saturate(dot(N, V));
float rim = pow(1.0 - NdotV, _RimPower) * _RimStrength;
float3 rimColor = _RimColor.rgb * rim;
float3 finalColor = eyeColor * diffuse * _LightColor0.rgb;
finalColor += reflection;
finalColor += highlights;
finalColor += sssColor;
finalColor += rimColor;
UNITY_APPLY_FOG(i.fogCoord, finalColor);
return fixed4(finalColor, 1);
}
ENDCG
}
// Shadow Caster
Pass
{
Name "ShadowCaster"
Tags { "LightMode" = "ShadowCaster" }
ZWrite On
ZTest LEqual
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_shadowcaster
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f
{
V2F_SHADOW_CASTER;
};
v2f vert(appdata v)
{
v2f o;
TRANSFER_SHADOW_CASTER_NORMALOFFSET(o);
return o;
}
fixed4 frag(v2f i) : SV_Target
{
SHADOW_CASTER_FRAGMENT(i);
}
ENDCG
}
}
// ==================== HDRP SubShader ====================
SubShader
{
PackageRequirements { "com.unity.render-pipelines.high-definition" }
Tags
{
"RenderType" = "Opaque"
"RenderPipeline" = "HDRenderPipeline"
"Queue" = "Geometry"
}
Pass
{
Name "ForwardOnly"
Tags { "LightMode" = "ForwardOnly" }
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 4.5
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl"
CBUFFER_START(UnityPerMaterial)
float4 _IrisColor;
float4 _IrisTex_ST;
float _IrisSize;
float _IrisDepth;
float4 _PupilColor;
float _PupilSize;
float _PupilDilation;
float _PupilSharpness;
float4 _ScleraColor;
float _ReflectionStrength;
float _ReflectionSmoothness;
float4 _Highlight1Pos;
float _Highlight1Size;
float _Highlight1Strength;
float4 _Highlight2Pos;
float _Highlight2Size;
float _Highlight2Strength;
float4 _LimbalColor;
float _LimbalWidth;
float _LimbalStrength;
float _CausticsStrength;
float _CausticsScale;
float _CausticsSpeed;
float4 _SSSColor;
float _SSSStrength;
float4 _RimColor;
float _RimPower;
float _RimStrength;
float4 _ShadowColor;
float _ShadowThreshold;
CBUFFER_END
TEXTURE2D(_IrisTex);
SAMPLER(sampler_IrisTex);
TEXTURE2D(_ScleraTex);
SAMPLER(sampler_ScleraTex);
TEXTURECUBE(_Cubemap);
SAMPLER(sampler_Cubemap);
struct Attributes
{
float4 positionOS : POSITION;
float3 normalOS : NORMAL;
float4 tangentOS : TANGENT;
float2 uv : TEXCOORD0;
};
struct Varyings
{
float4 positionCS : SV_POSITION;
float2 uv : TEXCOORD0;
float3 positionWS : TEXCOORD1;
float3 normalWS : TEXCOORD2;
float3 viewDirTS : TEXCOORD3;
};
float noise2D(float2 p)
{
return frac(sin(dot(p, float2(127.1, 311.7))) * 43758.5453);
}
float smoothNoise(float2 p)
{
float2 i = floor(p);
float2 f = frac(p);
f = f * f * (3.0 - 2.0 * f);
float a = noise2D(i);
float b = noise2D(i + float2(1, 0));
float c = noise2D(i + float2(0, 1));
float d = noise2D(i + float2(1, 1));
return lerp(lerp(a, b, f.x), lerp(c, d, f.x), f.y);
}
float causticsFunc(float2 uv, float time)
{
float c1 = smoothNoise(uv * _CausticsScale + time * 0.5);
float c2 = smoothNoise(uv * _CausticsScale * 1.3 - time * 0.3);
return pow(c1 * c2, 2) * 4.0;
}
Varyings vert(Attributes input)
{
Varyings output;
output.positionWS = TransformObjectToWorld(input.positionOS.xyz);
output.positionCS = TransformWorldToHClip(output.positionWS);
output.normalWS = TransformObjectToWorldNormal(input.normalOS);
output.uv = input.uv;
float3 tangentWS = TransformObjectToWorldDir(input.tangentOS.xyz);
float3 bitangentWS = cross(output.normalWS, tangentWS) * input.tangentOS.w;
float3 viewDirWS = GetWorldSpaceViewDir(output.positionWS);
float3x3 TBN = float3x3(tangentWS, bitangentWS, output.normalWS);
output.viewDirTS = mul(TBN, viewDirWS);
return output;
}
float4 frag(Varyings input) : SV_Target
{
float2 centeredUV = input.uv - 0.5;
float dist = length(centeredUV);
float3 viewDirTS = normalize(input.viewDirTS);
float2 parallaxOffset = viewDirTS.xy / viewDirTS.z * _IrisDepth;
float2 irisUV = centeredUV + parallaxOffset;
float irisDist = length(irisUV);
float pupilRadius = _PupilSize * _PupilDilation;
float pupilMask = 1.0 - saturate(pow(irisDist / pupilRadius, _PupilSharpness));
float irisMask = saturate(1.0 - smoothstep(_IrisSize - 0.05, _IrisSize + 0.05, irisDist));
irisMask *= (1.0 - pupilMask);
float limbalDist = abs(irisDist - _IrisSize);
float limbalMask = (1.0 - smoothstep(0, _LimbalWidth, limbalDist)) * irisMask;
float2 irisTexUV = (irisUV / _IrisSize) * 0.5 + 0.5;
float4 irisTex = SAMPLE_TEXTURE2D(_IrisTex, sampler_IrisTex, irisTexUV);
float4 scleraTex = SAMPLE_TEXTURE2D(_ScleraTex, sampler_ScleraTex, input.uv);
float3 eyeColor = _ScleraColor.rgb * scleraTex.rgb;
eyeColor = lerp(eyeColor, _IrisColor.rgb * irisTex.rgb, irisMask);
eyeColor = lerp(eyeColor, _LimbalColor.rgb, limbalMask * _LimbalStrength);
eyeColor = lerp(eyeColor, _PupilColor.rgb, pupilMask);
float time = _Time.y * _CausticsSpeed;
float causticsValue = causticsFunc(irisUV * 2.0, time);
eyeColor += causticsValue * _CausticsStrength * irisMask * (1.0 - pupilMask);
float3 N = normalize(input.normalWS);
float3 V = normalize(GetWorldSpaceViewDir(input.positionWS));
float3 L = normalize(float3(0.5, 1, 0.3));
float NdotL = dot(N, L);
float halfLambert = NdotL * 0.5 + 0.5;
float shadow = step(_ShadowThreshold, halfLambert);
float3 diffuse = lerp(_ShadowColor.rgb, float3(1,1,1), shadow);
float3 reflectDir = reflect(-V, N);
float3 envReflection = SAMPLE_TEXTURECUBE_LOD(_Cubemap, sampler_Cubemap, reflectDir, (1.0 - _ReflectionSmoothness) * 6.0).rgb;
float fresnel = pow(1.0 - saturate(dot(N, V)), 3.0);
float3 reflection = envReflection * _ReflectionStrength * fresnel;
float2 hl1UV = centeredUV - _Highlight1Pos.xy;
float hl1 = 1.0 - saturate(length(hl1UV) / _Highlight1Size);
hl1 = pow(hl1, 2.0) * _Highlight1Strength;
float2 hl2UV = centeredUV - _Highlight2Pos.xy;
float hl2 = 1.0 - saturate(length(hl2UV) / _Highlight2Size);
hl2 = pow(hl2, 2.0) * _Highlight2Strength;
float3 highlights = float3(1,1,1) * (hl1 + hl2);
float sss = pow(saturate(dot(-V, L)), 3.0) * _SSSStrength;
float3 sssColor = _SSSColor.rgb * sss;
float NdotV = saturate(dot(N, V));
float rim = pow(1.0 - NdotV, _RimPower) * _RimStrength;
float3 rimColor = _RimColor.rgb * rim;
float3 finalColor = eyeColor * diffuse + reflection + highlights + sssColor + rimColor;
return float4(finalColor, 1);
}
ENDHLSL
}
}
FallBack "Diffuse"
CustomEditor "SynapticEyeProEditor"
}