97ac0f71f5
https://assetstore.unity.com/packages/tools/generative-ai/synaptic-ai-pro-natural-language-control-for-unity-336030
942 lines
32 KiB
Plaintext
942 lines
32 KiB
Plaintext
Shader "Synaptic/HairPro"
|
|
{
|
|
Properties
|
|
{
|
|
[Header(Base)]
|
|
_MainTex ("Albedo", 2D) = "white" {}
|
|
_Color ("Color", Color) = (0.3, 0.2, 0.15, 1)
|
|
_Cutoff ("Alpha Cutoff", Range(0, 1)) = 0.5
|
|
|
|
[Header(Kajiya Kay Specular)]
|
|
_SpecularShift ("Specular Shift", Range(-1, 1)) = 0.1
|
|
_ShiftTex ("Shift Texture", 2D) = "gray" {}
|
|
|
|
[Header(Primary Specular)]
|
|
_SpecularColor1 ("Primary Color", Color) = (1, 1, 1, 1)
|
|
_SpecularWidth1 ("Primary Width", Range(0, 1)) = 0.5
|
|
_SpecularStrength1 ("Primary Strength", Range(0, 2)) = 0.5
|
|
_SpecularShift1 ("Primary Shift", Range(-1, 1)) = 0.1
|
|
|
|
[Header(Secondary Specular)]
|
|
_SpecularColor2 ("Secondary Color", Color) = (0.8, 0.6, 0.4, 1)
|
|
_SpecularWidth2 ("Secondary Width", Range(0, 1)) = 0.3
|
|
_SpecularStrength2 ("Secondary Strength", Range(0, 2)) = 0.3
|
|
_SpecularShift2 ("Secondary Shift", Range(-1, 1)) = -0.1
|
|
|
|
[Header(Anisotropic)]
|
|
_Anisotropy ("Anisotropy", Range(0, 1)) = 0.8
|
|
_TangentMap ("Tangent Map", 2D) = "bump" {}
|
|
|
|
[Header(Rim Light)]
|
|
_RimColor ("Rim Color", Color) = (1, 0.9, 0.8, 1)
|
|
_RimPower ("Rim Power", Range(0.1, 10)) = 3
|
|
_RimStrength ("Rim Strength", Range(0, 2)) = 0.5
|
|
|
|
[Header(Shadow)]
|
|
_ShadowColor ("Shadow Color", Color) = (0.4, 0.3, 0.3, 1)
|
|
_ShadowThreshold ("Shadow Threshold", Range(0, 1)) = 0.5
|
|
_ShadowSoftness ("Shadow Softness", Range(0, 1)) = 0.1
|
|
|
|
[Header(Subsurface Scattering)]
|
|
_SSSColor ("SSS Color", Color) = (1, 0.5, 0.3, 1)
|
|
_SSSStrength ("SSS Strength", Range(0, 2)) = 0.3
|
|
_SSSDistortion ("SSS Distortion", Range(0, 1)) = 0.5
|
|
|
|
[Header(Outline)]
|
|
_OutlineColor ("Outline Color", Color) = (0.1, 0.05, 0.05, 1)
|
|
_OutlineWidth ("Outline Width", Range(0, 0.1)) = 0.002
|
|
|
|
[Header(Wind Animation)]
|
|
_WindStrength ("Wind Strength", Range(0, 1)) = 0.1
|
|
_WindSpeed ("Wind Speed", Range(0, 5)) = 1
|
|
_WindDirection ("Wind Direction", Vector) = (1, 0, 0.5, 0)
|
|
}
|
|
|
|
// ==================== URP SubShader ====================
|
|
SubShader
|
|
{
|
|
PackageRequirements { "com.unity.render-pipelines.universal" }
|
|
Tags
|
|
{
|
|
"RenderType" = "Opaque"
|
|
"RenderPipeline" = "UniversalPipeline"
|
|
"Queue" = "Geometry"
|
|
}
|
|
|
|
// Main Pass
|
|
Pass
|
|
{
|
|
Name "ForwardLit"
|
|
Tags { "LightMode" = "UniversalForward" }
|
|
|
|
Cull Off
|
|
|
|
HLSLPROGRAM
|
|
#pragma vertex vert
|
|
#pragma fragment frag
|
|
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE
|
|
#pragma multi_compile _ _ADDITIONAL_LIGHTS
|
|
#pragma multi_compile_fog
|
|
|
|
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
|
|
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
|
|
|
|
CBUFFER_START(UnityPerMaterial)
|
|
float4 _MainTex_ST;
|
|
float4 _Color;
|
|
float _Cutoff;
|
|
float _SpecularShift;
|
|
float4 _SpecularColor1;
|
|
float _SpecularWidth1;
|
|
float _SpecularStrength1;
|
|
float _SpecularShift1;
|
|
float4 _SpecularColor2;
|
|
float _SpecularWidth2;
|
|
float _SpecularStrength2;
|
|
float _SpecularShift2;
|
|
float _Anisotropy;
|
|
float4 _RimColor;
|
|
float _RimPower;
|
|
float _RimStrength;
|
|
float4 _ShadowColor;
|
|
float _ShadowThreshold;
|
|
float _ShadowSoftness;
|
|
float4 _SSSColor;
|
|
float _SSSStrength;
|
|
float _SSSDistortion;
|
|
float4 _OutlineColor;
|
|
float _OutlineWidth;
|
|
float _WindStrength;
|
|
float _WindSpeed;
|
|
float4 _WindDirection;
|
|
CBUFFER_END
|
|
|
|
TEXTURE2D(_MainTex);
|
|
SAMPLER(sampler_MainTex);
|
|
TEXTURE2D(_ShiftTex);
|
|
SAMPLER(sampler_ShiftTex);
|
|
TEXTURE2D(_TangentMap);
|
|
SAMPLER(sampler_TangentMap);
|
|
|
|
// Kajiya-Kay Specular Function
|
|
float KajiyaKaySpecular(float3 T, float3 H, float width)
|
|
{
|
|
float TdotH = dot(T, H);
|
|
float sinTH = sqrt(1.0 - TdotH * TdotH);
|
|
float dirAtten = smoothstep(-1.0, 0.0, TdotH);
|
|
return dirAtten * pow(sinTH, width * 100.0);
|
|
}
|
|
|
|
// Shift tangent by normal and shift amount
|
|
float3 SynapticShiftTangent(float3 T, float3 N, float shift)
|
|
{
|
|
return normalize(T + N * shift);
|
|
}
|
|
|
|
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;
|
|
float fogFactor : TEXCOORD5;
|
|
};
|
|
|
|
Varyings vert(Attributes input)
|
|
{
|
|
Varyings output;
|
|
|
|
// Wind animation
|
|
float3 posOS = input.positionOS.xyz;
|
|
float windPhase = _Time.y * _WindSpeed + posOS.x * 2.0 + posOS.z * 2.0;
|
|
float windOffset = sin(windPhase) * _WindStrength * input.uv.y;
|
|
posOS += _WindDirection.xyz * windOffset;
|
|
|
|
VertexPositionInputs posInputs = GetVertexPositionInputs(posOS);
|
|
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 = TRANSFORM_TEX(input.uv, _MainTex);
|
|
output.fogFactor = ComputeFogFactor(posInputs.positionCS.z);
|
|
|
|
return output;
|
|
}
|
|
|
|
half4 frag(Varyings input) : SV_Target
|
|
{
|
|
// Sample textures
|
|
half4 albedo = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, input.uv) * _Color;
|
|
clip(albedo.a - _Cutoff);
|
|
|
|
float shiftTex = SAMPLE_TEXTURE2D(_ShiftTex, sampler_ShiftTex, input.uv).r - 0.5;
|
|
|
|
// Normalize vectors
|
|
float3 N = normalize(input.normalWS);
|
|
float3 T = normalize(input.tangentWS);
|
|
float3 B = normalize(input.bitangentWS);
|
|
float3 V = normalize(GetWorldSpaceViewDir(input.positionWS));
|
|
|
|
// Get main light
|
|
Light mainLight = GetMainLight(TransformWorldToShadowCoord(input.positionWS));
|
|
float3 L = mainLight.direction;
|
|
float3 H = normalize(L + V);
|
|
|
|
// Shift tangent for hair strands
|
|
float shift1 = _SpecularShift + _SpecularShift1 + shiftTex;
|
|
float shift2 = _SpecularShift + _SpecularShift2 + shiftTex;
|
|
float3 T1 = SynapticShiftTangent(B, N, shift1);
|
|
float3 T2 = SynapticShiftTangent(B, N, shift2);
|
|
|
|
// Kajiya-Kay dual specular
|
|
float spec1 = KajiyaKaySpecular(T1, H, _SpecularWidth1) * _SpecularStrength1;
|
|
float spec2 = KajiyaKaySpecular(T2, H, _SpecularWidth2) * _SpecularStrength2;
|
|
|
|
float3 specular = _SpecularColor1.rgb * spec1 + _SpecularColor2.rgb * spec2;
|
|
specular *= mainLight.color * mainLight.shadowAttenuation;
|
|
|
|
// Diffuse with toon shading
|
|
float NdotL = dot(N, L);
|
|
float halfLambert = NdotL * 0.5 + 0.5;
|
|
float shadow = smoothstep(_ShadowThreshold - _ShadowSoftness, _ShadowThreshold + _ShadowSoftness, halfLambert);
|
|
shadow *= mainLight.shadowAttenuation;
|
|
|
|
float3 diffuse = lerp(_ShadowColor.rgb, float3(1,1,1), shadow) * albedo.rgb;
|
|
|
|
// Subsurface Scattering
|
|
float3 sssH = normalize(L + N * _SSSDistortion);
|
|
float VdotH = pow(saturate(dot(V, -sssH)), 3.0);
|
|
float3 sss = _SSSColor.rgb * VdotH * _SSSStrength * (1.0 - shadow);
|
|
|
|
// Rim light
|
|
float NdotV = saturate(dot(N, V));
|
|
float rim = pow(1.0 - NdotV, _RimPower) * _RimStrength;
|
|
float3 rimColor = _RimColor.rgb * rim * mainLight.color;
|
|
|
|
// Additional lights
|
|
float3 additionalLight = float3(0, 0, 0);
|
|
#ifdef _ADDITIONAL_LIGHTS
|
|
uint additionalLightsCount = GetAdditionalLightsCount();
|
|
for (uint i = 0; i < additionalLightsCount; ++i)
|
|
{
|
|
Light light = GetAdditionalLight(i, input.positionWS);
|
|
float addNdotL = saturate(dot(N, light.direction));
|
|
additionalLight += light.color * light.distanceAttenuation * addNdotL * 0.5;
|
|
}
|
|
#endif
|
|
|
|
// Combine
|
|
float3 finalColor = diffuse * mainLight.color + specular + sss + rimColor + additionalLight * albedo.rgb;
|
|
finalColor = MixFog(finalColor, input.fogFactor);
|
|
|
|
return half4(finalColor, albedo.a);
|
|
}
|
|
ENDHLSL
|
|
}
|
|
|
|
// Outline Pass
|
|
Pass
|
|
{
|
|
Name "Outline"
|
|
Tags { "LightMode" = "SRPDefaultUnlit" }
|
|
|
|
Cull Front
|
|
|
|
HLSLPROGRAM
|
|
#pragma vertex vertOutline
|
|
#pragma fragment fragOutline
|
|
|
|
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
|
|
|
|
CBUFFER_START(UnityPerMaterial)
|
|
float4 _MainTex_ST;
|
|
float4 _Color;
|
|
float _Cutoff;
|
|
float _SpecularShift;
|
|
float4 _SpecularColor1;
|
|
float _SpecularWidth1;
|
|
float _SpecularStrength1;
|
|
float _SpecularShift1;
|
|
float4 _SpecularColor2;
|
|
float _SpecularWidth2;
|
|
float _SpecularStrength2;
|
|
float _SpecularShift2;
|
|
float _Anisotropy;
|
|
float4 _RimColor;
|
|
float _RimPower;
|
|
float _RimStrength;
|
|
float4 _ShadowColor;
|
|
float _ShadowThreshold;
|
|
float _ShadowSoftness;
|
|
float4 _SSSColor;
|
|
float _SSSStrength;
|
|
float _SSSDistortion;
|
|
float4 _OutlineColor;
|
|
float _OutlineWidth;
|
|
float _WindStrength;
|
|
float _WindSpeed;
|
|
float4 _WindDirection;
|
|
CBUFFER_END
|
|
|
|
TEXTURE2D(_MainTex);
|
|
SAMPLER(sampler_MainTex);
|
|
|
|
struct Attributes
|
|
{
|
|
float4 positionOS : POSITION;
|
|
float3 normalOS : NORMAL;
|
|
float2 uv : TEXCOORD0;
|
|
};
|
|
|
|
struct Varyings
|
|
{
|
|
float4 positionCS : SV_POSITION;
|
|
float2 uv : TEXCOORD0;
|
|
};
|
|
|
|
Varyings vertOutline(Attributes input)
|
|
{
|
|
Varyings output;
|
|
|
|
float3 normalOS = normalize(input.normalOS);
|
|
float3 posOS = input.positionOS.xyz + normalOS * _OutlineWidth;
|
|
|
|
output.positionCS = TransformObjectToHClip(posOS);
|
|
output.uv = TRANSFORM_TEX(input.uv, _MainTex);
|
|
|
|
return output;
|
|
}
|
|
|
|
half4 fragOutline(Varyings input) : SV_Target
|
|
{
|
|
half4 albedo = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, input.uv);
|
|
clip(albedo.a - _Cutoff);
|
|
return _OutlineColor;
|
|
}
|
|
ENDHLSL
|
|
}
|
|
|
|
// Shadow Caster
|
|
Pass
|
|
{
|
|
Name "ShadowCaster"
|
|
Tags { "LightMode" = "ShadowCaster" }
|
|
|
|
ZWrite On
|
|
ZTest LEqual
|
|
ColorMask 0
|
|
Cull Off
|
|
|
|
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;
|
|
}
|
|
|
|
CBUFFER_START(UnityPerMaterial)
|
|
float4 _MainTex_ST;
|
|
float4 _Color;
|
|
float _Cutoff;
|
|
float _SpecularShift;
|
|
float4 _SpecularColor1;
|
|
float _SpecularWidth1;
|
|
float _SpecularStrength1;
|
|
float _SpecularShift1;
|
|
float4 _SpecularColor2;
|
|
float _SpecularWidth2;
|
|
float _SpecularStrength2;
|
|
float _SpecularShift2;
|
|
float _Anisotropy;
|
|
float4 _RimColor;
|
|
float _RimPower;
|
|
float _RimStrength;
|
|
float4 _ShadowColor;
|
|
float _ShadowThreshold;
|
|
float _ShadowSoftness;
|
|
float4 _SSSColor;
|
|
float _SSSStrength;
|
|
float _SSSDistortion;
|
|
float4 _OutlineColor;
|
|
float _OutlineWidth;
|
|
float _WindStrength;
|
|
float _WindSpeed;
|
|
float4 _WindDirection;
|
|
CBUFFER_END
|
|
|
|
TEXTURE2D(_MainTex);
|
|
SAMPLER(sampler_MainTex);
|
|
|
|
struct Attributes
|
|
{
|
|
float4 positionOS : POSITION;
|
|
float3 normalOS : NORMAL;
|
|
float2 uv : TEXCOORD0;
|
|
};
|
|
|
|
struct Varyings
|
|
{
|
|
float4 positionCS : SV_POSITION;
|
|
float2 uv : TEXCOORD0;
|
|
};
|
|
|
|
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
|
|
output.uv = TRANSFORM_TEX(input.uv, _MainTex);
|
|
|
|
return output;
|
|
}
|
|
|
|
half4 fragShadow(Varyings input) : SV_Target
|
|
{
|
|
half4 albedo = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, input.uv);
|
|
clip(albedo.a - _Cutoff);
|
|
return 0;
|
|
}
|
|
ENDHLSL
|
|
}
|
|
|
|
// Depth Only
|
|
Pass
|
|
{
|
|
Name "DepthOnly"
|
|
Tags { "LightMode" = "DepthOnly" }
|
|
|
|
ZWrite On
|
|
ColorMask 0
|
|
Cull Off
|
|
|
|
HLSLPROGRAM
|
|
#pragma vertex vertDepth
|
|
#pragma fragment fragDepth
|
|
|
|
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
|
|
|
|
CBUFFER_START(UnityPerMaterial)
|
|
float4 _MainTex_ST;
|
|
float4 _Color;
|
|
float _Cutoff;
|
|
float _SpecularShift;
|
|
float4 _SpecularColor1;
|
|
float _SpecularWidth1;
|
|
float _SpecularStrength1;
|
|
float _SpecularShift1;
|
|
float4 _SpecularColor2;
|
|
float _SpecularWidth2;
|
|
float _SpecularStrength2;
|
|
float _SpecularShift2;
|
|
float _Anisotropy;
|
|
float4 _RimColor;
|
|
float _RimPower;
|
|
float _RimStrength;
|
|
float4 _ShadowColor;
|
|
float _ShadowThreshold;
|
|
float _ShadowSoftness;
|
|
float4 _SSSColor;
|
|
float _SSSStrength;
|
|
float _SSSDistortion;
|
|
float4 _OutlineColor;
|
|
float _OutlineWidth;
|
|
float _WindStrength;
|
|
float _WindSpeed;
|
|
float4 _WindDirection;
|
|
CBUFFER_END
|
|
|
|
TEXTURE2D(_MainTex);
|
|
SAMPLER(sampler_MainTex);
|
|
|
|
struct Attributes
|
|
{
|
|
float4 positionOS : POSITION;
|
|
float2 uv : TEXCOORD0;
|
|
};
|
|
|
|
struct Varyings
|
|
{
|
|
float4 positionCS : SV_POSITION;
|
|
float2 uv : TEXCOORD0;
|
|
};
|
|
|
|
Varyings vertDepth(Attributes input)
|
|
{
|
|
Varyings output;
|
|
output.positionCS = TransformObjectToHClip(input.positionOS.xyz);
|
|
output.uv = TRANSFORM_TEX(input.uv, _MainTex);
|
|
return output;
|
|
}
|
|
|
|
half4 fragDepth(Varyings input) : SV_Target
|
|
{
|
|
half4 albedo = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, input.uv);
|
|
clip(albedo.a - _Cutoff);
|
|
return 0;
|
|
}
|
|
ENDHLSL
|
|
}
|
|
}
|
|
|
|
// ==================== Built-in SubShader ====================
|
|
SubShader
|
|
{
|
|
Tags
|
|
{
|
|
"RenderType" = "Opaque"
|
|
"Queue" = "Geometry"
|
|
}
|
|
|
|
// Main Pass
|
|
Pass
|
|
{
|
|
Name "ForwardBase"
|
|
Tags { "LightMode" = "ForwardBase" }
|
|
|
|
Cull Off
|
|
|
|
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 _MainTex;
|
|
float4 _MainTex_ST;
|
|
sampler2D _ShiftTex;
|
|
sampler2D _TangentMap;
|
|
|
|
fixed4 _Color;
|
|
float _Cutoff;
|
|
|
|
float _SpecularShift;
|
|
fixed4 _SpecularColor1;
|
|
float _SpecularWidth1;
|
|
float _SpecularStrength1;
|
|
float _SpecularShift1;
|
|
|
|
fixed4 _SpecularColor2;
|
|
float _SpecularWidth2;
|
|
float _SpecularStrength2;
|
|
float _SpecularShift2;
|
|
|
|
fixed4 _RimColor;
|
|
float _RimPower;
|
|
float _RimStrength;
|
|
|
|
fixed4 _ShadowColor;
|
|
float _ShadowThreshold;
|
|
float _ShadowSoftness;
|
|
|
|
fixed4 _SSSColor;
|
|
float _SSSStrength;
|
|
float _SSSDistortion;
|
|
|
|
float _WindStrength;
|
|
float _WindSpeed;
|
|
float4 _WindDirection;
|
|
|
|
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 worldTangent : TEXCOORD3;
|
|
float3 worldBitangent : TEXCOORD4;
|
|
UNITY_FOG_COORDS(5)
|
|
SHADOW_COORDS(6)
|
|
};
|
|
|
|
float KajiyaKaySpec(float3 T, float3 H, float width)
|
|
{
|
|
float TdotH = dot(T, H);
|
|
float sinTH = sqrt(1.0 - TdotH * TdotH);
|
|
float dirAtten = smoothstep(-1.0, 0.0, TdotH);
|
|
return dirAtten * pow(sinTH, width * 100.0);
|
|
}
|
|
|
|
float3 ShiftT(float3 T, float3 N, float shift)
|
|
{
|
|
return normalize(T + N * shift);
|
|
}
|
|
|
|
v2f vert(appdata v)
|
|
{
|
|
v2f o;
|
|
|
|
// Wind animation
|
|
float3 posOS = v.vertex.xyz;
|
|
float windPhase = _Time.y * _WindSpeed + posOS.x * 2.0 + posOS.z * 2.0;
|
|
float windOffset = sin(windPhase) * _WindStrength * v.uv.y;
|
|
posOS += _WindDirection.xyz * windOffset;
|
|
|
|
o.pos = UnityObjectToClipPos(float4(posOS, 1));
|
|
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
|
|
o.worldPos = mul(unity_ObjectToWorld, float4(posOS, 1)).xyz;
|
|
o.worldNormal = UnityObjectToWorldNormal(v.normal);
|
|
o.worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
|
|
o.worldBitangent = cross(o.worldNormal, o.worldTangent) * v.tangent.w;
|
|
|
|
UNITY_TRANSFER_FOG(o, o.pos);
|
|
TRANSFER_SHADOW(o);
|
|
|
|
return o;
|
|
}
|
|
|
|
fixed4 frag(v2f i) : SV_Target
|
|
{
|
|
fixed4 albedo = tex2D(_MainTex, i.uv) * _Color;
|
|
clip(albedo.a - _Cutoff);
|
|
|
|
float shiftTex = tex2D(_ShiftTex, i.uv).r - 0.5;
|
|
|
|
float3 N = normalize(i.worldNormal);
|
|
float3 T = normalize(i.worldTangent);
|
|
float3 B = normalize(i.worldBitangent);
|
|
float3 V = normalize(_WorldSpaceCameraPos - i.worldPos);
|
|
float3 L = normalize(_WorldSpaceLightPos0.xyz);
|
|
float3 H = normalize(L + V);
|
|
|
|
// Kajiya-Kay
|
|
float shift1 = _SpecularShift + _SpecularShift1 + shiftTex;
|
|
float shift2 = _SpecularShift + _SpecularShift2 + shiftTex;
|
|
float3 T1 = ShiftT(B, N, shift1);
|
|
float3 T2 = ShiftT(B, N, shift2);
|
|
|
|
float spec1 = KajiyaKaySpec(T1, H, _SpecularWidth1) * _SpecularStrength1;
|
|
float spec2 = KajiyaKaySpec(T2, H, _SpecularWidth2) * _SpecularStrength2;
|
|
float3 specular = _SpecularColor1.rgb * spec1 + _SpecularColor2.rgb * spec2;
|
|
|
|
// Shadow
|
|
float atten = SHADOW_ATTENUATION(i);
|
|
float NdotL = dot(N, L);
|
|
float halfLambert = NdotL * 0.5 + 0.5;
|
|
float shadow = smoothstep(_ShadowThreshold - _ShadowSoftness, _ShadowThreshold + _ShadowSoftness, halfLambert);
|
|
shadow *= atten;
|
|
|
|
float3 diffuse = lerp(_ShadowColor.rgb, float3(1,1,1), shadow) * albedo.rgb;
|
|
|
|
// SSS
|
|
float3 sssH = normalize(L + N * _SSSDistortion);
|
|
float VdotH = pow(saturate(dot(V, -sssH)), 3.0);
|
|
float3 sss = _SSSColor.rgb * VdotH * _SSSStrength * (1.0 - shadow);
|
|
|
|
// Rim
|
|
float NdotV = saturate(dot(N, V));
|
|
float rim = pow(1.0 - NdotV, _RimPower) * _RimStrength;
|
|
float3 rimColor = _RimColor.rgb * rim;
|
|
|
|
float3 finalColor = diffuse * _LightColor0.rgb + specular * _LightColor0.rgb * atten + sss + rimColor;
|
|
|
|
UNITY_APPLY_FOG(i.fogCoord, finalColor);
|
|
return fixed4(finalColor, albedo.a);
|
|
}
|
|
ENDCG
|
|
}
|
|
|
|
// Outline Pass
|
|
Pass
|
|
{
|
|
Name "Outline"
|
|
Tags { "LightMode" = "Always" }
|
|
|
|
Cull Front
|
|
|
|
CGPROGRAM
|
|
#pragma vertex vert
|
|
#pragma fragment frag
|
|
|
|
#include "UnityCG.cginc"
|
|
|
|
sampler2D _MainTex;
|
|
float4 _MainTex_ST;
|
|
float _Cutoff;
|
|
fixed4 _OutlineColor;
|
|
float _OutlineWidth;
|
|
|
|
struct appdata
|
|
{
|
|
float4 vertex : POSITION;
|
|
float3 normal : NORMAL;
|
|
float2 uv : TEXCOORD0;
|
|
};
|
|
|
|
struct v2f
|
|
{
|
|
float4 pos : SV_POSITION;
|
|
float2 uv : TEXCOORD0;
|
|
};
|
|
|
|
v2f vert(appdata v)
|
|
{
|
|
v2f o;
|
|
float3 normalOS = normalize(v.normal);
|
|
float3 posOS = v.vertex.xyz + normalOS * _OutlineWidth;
|
|
o.pos = UnityObjectToClipPos(float4(posOS, 1));
|
|
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
|
|
return o;
|
|
}
|
|
|
|
fixed4 frag(v2f i) : SV_Target
|
|
{
|
|
fixed4 albedo = tex2D(_MainTex, i.uv);
|
|
clip(albedo.a - _Cutoff);
|
|
return _OutlineColor;
|
|
}
|
|
ENDCG
|
|
}
|
|
|
|
// Shadow Caster
|
|
Pass
|
|
{
|
|
Name "ShadowCaster"
|
|
Tags { "LightMode" = "ShadowCaster" }
|
|
|
|
ZWrite On
|
|
ZTest LEqual
|
|
Cull Off
|
|
|
|
CGPROGRAM
|
|
#pragma vertex vert
|
|
#pragma fragment frag
|
|
#pragma multi_compile_shadowcaster
|
|
|
|
#include "UnityCG.cginc"
|
|
|
|
sampler2D _MainTex;
|
|
float4 _MainTex_ST;
|
|
float _Cutoff;
|
|
|
|
struct appdata
|
|
{
|
|
float4 vertex : POSITION;
|
|
float3 normal : NORMAL;
|
|
float2 uv : TEXCOORD0;
|
|
};
|
|
|
|
struct v2f
|
|
{
|
|
V2F_SHADOW_CASTER;
|
|
float2 uv : TEXCOORD1;
|
|
};
|
|
|
|
v2f vert(appdata v)
|
|
{
|
|
v2f o;
|
|
TRANSFER_SHADOW_CASTER_NORMALOFFSET(o);
|
|
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
|
|
return o;
|
|
}
|
|
|
|
fixed4 frag(v2f i) : SV_Target
|
|
{
|
|
fixed4 albedo = tex2D(_MainTex, i.uv);
|
|
clip(albedo.a - _Cutoff);
|
|
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" }
|
|
|
|
Cull Off
|
|
|
|
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 _MainTex_ST;
|
|
float4 _Color;
|
|
float _Cutoff;
|
|
float _SpecularShift;
|
|
float4 _SpecularColor1;
|
|
float _SpecularWidth1;
|
|
float _SpecularStrength1;
|
|
float _SpecularShift1;
|
|
float4 _SpecularColor2;
|
|
float _SpecularWidth2;
|
|
float _SpecularStrength2;
|
|
float _SpecularShift2;
|
|
float4 _RimColor;
|
|
float _RimPower;
|
|
float _RimStrength;
|
|
float4 _ShadowColor;
|
|
float _ShadowThreshold;
|
|
float _ShadowSoftness;
|
|
float4 _SSSColor;
|
|
float _SSSStrength;
|
|
float _SSSDistortion;
|
|
float _WindStrength;
|
|
float _WindSpeed;
|
|
float4 _WindDirection;
|
|
CBUFFER_END
|
|
|
|
TEXTURE2D(_MainTex);
|
|
SAMPLER(sampler_MainTex);
|
|
TEXTURE2D(_ShiftTex);
|
|
SAMPLER(sampler_ShiftTex);
|
|
|
|
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;
|
|
};
|
|
|
|
float KKSpec(float3 T, float3 H, float width)
|
|
{
|
|
float TdotH = dot(T, H);
|
|
float sinTH = sqrt(1.0 - TdotH * TdotH);
|
|
float dirAtten = smoothstep(-1.0, 0.0, TdotH);
|
|
return dirAtten * pow(sinTH, width * 100.0);
|
|
}
|
|
|
|
float3 ShiftTan(float3 T, float3 N, float shift)
|
|
{
|
|
return normalize(T + N * shift);
|
|
}
|
|
|
|
Varyings vert(Attributes input)
|
|
{
|
|
Varyings output;
|
|
|
|
float3 posOS = input.positionOS.xyz;
|
|
float windPhase = _Time.y * _WindSpeed + posOS.x * 2.0 + posOS.z * 2.0;
|
|
float windOffset = sin(windPhase) * _WindStrength * input.uv.y;
|
|
posOS += _WindDirection.xyz * windOffset;
|
|
|
|
output.positionWS = TransformObjectToWorld(posOS);
|
|
output.positionCS = TransformWorldToHClip(output.positionWS);
|
|
output.normalWS = TransformObjectToWorldNormal(input.normalOS);
|
|
output.tangentWS = TransformObjectToWorldDir(input.tangentOS.xyz);
|
|
output.bitangentWS = cross(output.normalWS, output.tangentWS) * input.tangentOS.w;
|
|
output.uv = input.uv * _MainTex_ST.xy + _MainTex_ST.zw;
|
|
|
|
return output;
|
|
}
|
|
|
|
float4 frag(Varyings input) : SV_Target
|
|
{
|
|
float4 albedo = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, input.uv) * _Color;
|
|
clip(albedo.a - _Cutoff);
|
|
|
|
float shiftTex = SAMPLE_TEXTURE2D(_ShiftTex, sampler_ShiftTex, input.uv).r - 0.5;
|
|
|
|
float3 N = normalize(input.normalWS);
|
|
float3 T = normalize(input.tangentWS);
|
|
float3 B = normalize(input.bitangentWS);
|
|
float3 V = normalize(GetWorldSpaceViewDir(input.positionWS));
|
|
float3 L = normalize(float3(0.5, 1, 0.3));
|
|
float3 H = normalize(L + V);
|
|
|
|
float shift1 = _SpecularShift + _SpecularShift1 + shiftTex;
|
|
float shift2 = _SpecularShift + _SpecularShift2 + shiftTex;
|
|
float3 T1 = ShiftTan(B, N, shift1);
|
|
float3 T2 = ShiftTan(B, N, shift2);
|
|
|
|
float spec1 = KKSpec(T1, H, _SpecularWidth1) * _SpecularStrength1;
|
|
float spec2 = KKSpec(T2, H, _SpecularWidth2) * _SpecularStrength2;
|
|
float3 specular = _SpecularColor1.rgb * spec1 + _SpecularColor2.rgb * spec2;
|
|
|
|
float NdotL = dot(N, L);
|
|
float halfLambert = NdotL * 0.5 + 0.5;
|
|
float shadow = smoothstep(_ShadowThreshold - _ShadowSoftness, _ShadowThreshold + _ShadowSoftness, halfLambert);
|
|
|
|
float3 diffuse = lerp(_ShadowColor.rgb, float3(1,1,1), shadow) * albedo.rgb;
|
|
|
|
float3 sssH = normalize(L + N * _SSSDistortion);
|
|
float VdotH = pow(saturate(dot(V, -sssH)), 3.0);
|
|
float3 sss = _SSSColor.rgb * VdotH * _SSSStrength * (1.0 - shadow);
|
|
|
|
float NdotV = saturate(dot(N, V));
|
|
float rim = pow(1.0 - NdotV, _RimPower) * _RimStrength;
|
|
float3 rimColor = _RimColor.rgb * rim;
|
|
|
|
float3 finalColor = diffuse + specular + sss + rimColor;
|
|
|
|
return float4(finalColor, albedo.a);
|
|
}
|
|
ENDHLSL
|
|
}
|
|
}
|
|
|
|
FallBack "Diffuse"
|
|
CustomEditor "SynapticHairProEditor"
|
|
}
|