97ac0f71f5
https://assetstore.unity.com/packages/tools/generative-ai/synaptic-ai-pro-natural-language-control-for-unity-336030
849 lines
30 KiB
Plaintext
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"
|
|
}
|