2026-06-06 20:12:40 +07:00
parent de84b2bf48
commit 97ac0f71f5
13682 changed files with 1125938 additions and 0 deletions
@@ -0,0 +1,874 @@
Shader "Synaptic/GrassPro"
{
Properties
{
[Header(Base)]
_MainTex ("Albedo", 2D) = "white" {}
_BaseColor ("Base Color", Color) = (0.2, 0.6, 0.2, 1)
_TipColor ("Tip Color", Color) = (0.5, 0.9, 0.3, 1)
_GradientPower ("Gradient Power", Range(0.1, 3)) = 1
[Header(Wind Animation)]
[Toggle(_WIND_ON)] _WindEnabled ("Enable Wind", Float) = 1
_WindStrength ("Wind Strength", Range(0, 2)) = 0.5
_WindSpeed ("Wind Speed", Float) = 1
_WindFrequency ("Wind Frequency", Float) = 1
_WindDirection ("Wind Direction", Vector) = (1, 0, 0.5, 0)
_WindNoiseTex ("Wind Noise", 2D) = "grey" {}
_WindNoiseScale ("Wind Noise Scale", Float) = 0.1
_WindGustStrength ("Gust Strength", Range(0, 2)) = 0.3
_WindGustFrequency ("Gust Frequency", Float) = 0.5
[Header(Player Interaction)]
[Toggle(_INTERACTION_ON)] _InteractionEnabled ("Enable Interaction", Float) = 1
_InteractionRadius ("Interaction Radius", Float) = 2
_InteractionStrength ("Interaction Strength", Range(0, 2)) = 1
_InteractionFalloff ("Interaction Falloff", Range(0.1, 5)) = 2
[Header(Subsurface Scattering)]
[Toggle(_SSS_ON)] _SSSEnabled ("Enable SSS", Float) = 1
_SSSColor ("SSS Color", Color) = (0.8, 1.0, 0.5, 1)
_SSSStrength ("SSS Strength", Range(0, 2)) = 1
_SSSDistortion ("SSS Distortion", Range(0, 1)) = 0.5
_SSSPower ("SSS Power", Range(1, 16)) = 4
[Header(Detail)]
_AO ("Ambient Occlusion", Range(0, 1)) = 0.5
_AOPower ("AO Power", Range(0.1, 3)) = 1
_Roughness ("Roughness", Range(0, 1)) = 0.8
[Header(Specular)]
[Toggle(_SPECULAR_ON)] _SpecularEnabled ("Enable Specular", Float) = 1
_SpecularColor ("Specular Color", Color) = (1, 1, 0.8, 1)
_SpecularIntensity ("Specular Intensity", Range(0, 3)) = 0.5
_SpecularPower ("Specular Power", Range(1, 128)) = 32
[Header(Distance Fade)]
[Toggle(_DISTANCE_FADE_ON)] _DistanceFadeEnabled ("Enable Distance Fade", Float) = 1
_FadeStart ("Fade Start", Float) = 30
_FadeEnd ("Fade End", Float) = 50
_FadeMinScale ("Fade Min Scale", Range(0, 1)) = 0.3
[Header(Cutout)]
_Cutoff ("Alpha Cutoff", Range(0, 1)) = 0.5
[Header(Rendering)]
[Enum(UnityEngine.Rendering.CullMode)] _Cull ("Cull Mode", Float) = 0
}
SubShader
{
PackageRequirements { "com.unity.render-pipelines.universal" }
Tags
{
"RenderType" = "TransparentCutout"
"Queue" = "AlphaTest"
"RenderPipeline" = "UniversalPipeline"
}
Pass
{
Name "GrassForward"
Tags { "LightMode" = "UniversalForward" }
Cull [_Cull]
AlphaToMask On
HLSLPROGRAM
#pragma target 4.5
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE
#pragma multi_compile_fragment _ _SHADOWS_SOFT
#pragma multi_compile _ _ADDITIONAL_LIGHTS
#pragma multi_compile_fog
#pragma multi_compile_instancing
#pragma shader_feature_local _WIND_ON
#pragma shader_feature_local _INTERACTION_ON
#pragma shader_feature_local _SSS_ON
#pragma shader_feature_local _SPECULAR_ON
#pragma shader_feature_local _DISTANCE_FADE_ON
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
TEXTURE2D(_MainTex);
TEXTURE2D(_WindNoiseTex);
SAMPLER(sampler_MainTex);
SAMPLER(sampler_WindNoiseTex);
// Interaction positions (set from script)
float4 _InteractionPositions[16];
int _InteractionCount;
CBUFFER_START(UnityPerMaterial)
float4 _MainTex_ST;
float4 _BaseColor;
float4 _TipColor;
float _GradientPower;
float _WindStrength;
float _WindSpeed;
float _WindFrequency;
float4 _WindDirection;
float4 _WindNoiseTex_ST;
float _WindNoiseScale;
float _WindGustStrength;
float _WindGustFrequency;
float _InteractionRadius;
float _InteractionStrength;
float _InteractionFalloff;
float4 _SSSColor;
float _SSSStrength;
float _SSSDistortion;
float _SSSPower;
float _AO;
float _AOPower;
float _Roughness;
float4 _SpecularColor;
float _SpecularIntensity;
float _SpecularPower;
float _FadeStart;
float _FadeEnd;
float _FadeMinScale;
float _Cutoff;
CBUFFER_END
struct Attributes
{
float4 positionOS : POSITION;
float3 normalOS : NORMAL;
float2 uv : TEXCOORD0;
float4 color : COLOR; // R = height, G = AO, B = unused, A = stiffness
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct Varyings
{
float4 positionCS : SV_POSITION;
float2 uv : TEXCOORD0;
float3 worldPos : TEXCOORD1;
float3 worldNormal : TEXCOORD2;
float4 vertexColor : TEXCOORD3;
float4 shadowCoord : TEXCOORD4;
float fogFactor : TEXCOORD5;
float heightGradient : TEXCOORD6;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
// Wind functions
float3 WindAnimation(float3 worldPos, float height, float stiffness, float time)
{
#if defined(_WIND_ON)
float3 windDir = normalize(_WindDirection.xyz);
// Sample wind noise
float2 noiseUV = worldPos.xz * _WindNoiseScale + time * _WindSpeed * 0.1;
float noise = SAMPLE_TEXTURE2D_LOD(_WindNoiseTex, sampler_WindNoiseTex, noiseUV, 0).r;
// Main wind wave
float windPhase = dot(worldPos.xz, windDir.xz) * _WindFrequency + time * _WindSpeed;
float wave = sin(windPhase) * 0.5 + 0.5;
// Gust
float gustPhase = time * _WindGustFrequency;
float gust = sin(gustPhase) * sin(gustPhase * 2.3) * _WindGustStrength;
// Combined wind
float windFactor = (wave + gust + noise - 0.5) * _WindStrength;
windFactor *= height * height; // Quadratic falloff from root
windFactor *= (1 - stiffness); // Stiffness reduces wind effect
return windDir * windFactor;
#else
return float3(0, 0, 0);
#endif
}
// Player interaction
float3 InteractionDisplacement(float3 worldPos, float height)
{
#if defined(_INTERACTION_ON)
float3 totalDisplacement = float3(0, 0, 0);
for (int i = 0; i < _InteractionCount && i < 16; i++)
{
float3 interactorPos = _InteractionPositions[i].xyz;
float3 toGrass = worldPos - interactorPos;
toGrass.y = 0;
float dist = length(toGrass);
float influence = 1 - saturate(pow(dist / _InteractionRadius, _InteractionFalloff));
if (influence > 0.001)
{
float3 pushDir = normalize(toGrass + float3(0.001, 0, 0.001));
totalDisplacement += pushDir * influence * _InteractionStrength * height;
}
}
return totalDisplacement;
#else
return float3(0, 0, 0);
#endif
}
Varyings vert(Attributes IN)
{
Varyings OUT;
UNITY_SETUP_INSTANCE_ID(IN);
UNITY_TRANSFER_INSTANCE_ID(IN, OUT);
float height = IN.color.r; // Height along blade (0 = root, 1 = tip)
float stiffness = IN.color.a;
float time = _Time.y;
float3 posOS = IN.positionOS.xyz;
float3 worldPosBase = TransformObjectToWorld(float3(0, 0, 0));
// Distance fade
#if defined(_DISTANCE_FADE_ON)
float distToCam = distance(worldPosBase, _WorldSpaceCameraPos);
float fadeFactor = saturate((distToCam - _FadeStart) / (_FadeEnd - _FadeStart));
float scale = lerp(1, _FadeMinScale, fadeFactor);
posOS *= scale;
#endif
float3 worldPos = TransformObjectToWorld(posOS);
// Apply wind
float3 windOffset = WindAnimation(worldPos, height, stiffness, time);
worldPos += windOffset;
// Apply interaction
float3 interactOffset = InteractionDisplacement(worldPos, height);
worldPos += interactOffset;
OUT.worldPos = worldPos;
OUT.positionCS = TransformWorldToHClip(worldPos);
OUT.uv = TRANSFORM_TEX(IN.uv, _MainTex);
OUT.worldNormal = TransformObjectToWorldNormal(IN.normalOS);
OUT.vertexColor = IN.color;
OUT.shadowCoord = TransformWorldToShadowCoord(worldPos);
OUT.fogFactor = ComputeFogFactor(OUT.positionCS.z);
OUT.heightGradient = height;
return OUT;
}
// SSS function
float3 SubsurfaceScattering(float3 viewDir, float3 lightDir, float3 normal, float3 lightColor)
{
#if defined(_SSS_ON)
float3 H = normalize(lightDir + normal * _SSSDistortion);
float VdotH = pow(saturate(dot(viewDir, -H)), _SSSPower);
return _SSSColor.rgb * VdotH * _SSSStrength * lightColor;
#else
return float3(0, 0, 0);
#endif
}
float4 frag(Varyings IN) : SV_Target
{
UNITY_SETUP_INSTANCE_ID(IN);
// Sample texture
float4 texColor = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, IN.uv);
clip(texColor.a - _Cutoff);
float3 viewDir = normalize(_WorldSpaceCameraPos - IN.worldPos);
float3 normal = normalize(IN.worldNormal);
// Height-based color gradient
float gradientFactor = pow(IN.heightGradient, _GradientPower);
float3 albedo = lerp(_BaseColor.rgb, _TipColor.rgb, gradientFactor) * texColor.rgb;
// Ambient occlusion from vertex color
float ao = lerp(1, IN.vertexColor.g, _AO);
ao = pow(ao, _AOPower);
// Lighting
Light mainLight = GetMainLight(IN.shadowCoord);
float3 lightDir = mainLight.direction;
float3 lightColor = mainLight.color;
float shadow = mainLight.shadowAttenuation;
// Wrapped diffuse for softer look
float NdotL = dot(normal, lightDir);
float wrappedNdotL = NdotL * 0.5 + 0.5;
float3 diffuse = albedo * lightColor * wrappedNdotL * shadow;
// SSS
float3 sss = SubsurfaceScattering(viewDir, lightDir, normal, lightColor);
sss *= (1 - IN.heightGradient) * shadow; // More SSS at base
// Specular
float3 specular = float3(0, 0, 0);
#if defined(_SPECULAR_ON)
float3 halfDir = normalize(lightDir + viewDir);
float NdotH = saturate(dot(normal, halfDir));
float spec = pow(NdotH, _SpecularPower) * _SpecularIntensity;
specular = _SpecularColor.rgb * spec * shadow * IN.heightGradient; // More specular at tip
#endif
// Additional lights
float3 additionalLights = float3(0, 0, 0);
#if defined(_ADDITIONAL_LIGHTS)
uint pixelLightCount = GetAdditionalLightsCount();
for (uint i = 0; i < pixelLightCount; i++)
{
Light light = GetAdditionalLight(i, IN.worldPos);
float addNdotL = saturate(dot(normal, light.direction));
additionalLights += albedo * light.color * light.distanceAttenuation * addNdotL * 0.5;
}
#endif
// Ambient
float3 ambient = albedo * 0.1;
// Combine
float3 finalColor = (diffuse + sss + specular + additionalLights + ambient) * ao;
// Fog
finalColor = MixFog(finalColor, IN.fogFactor);
return float4(finalColor, texColor.a);
}
ENDHLSL
}
// Shadow caster pass
Pass
{
Name "ShadowCaster"
Tags { "LightMode" = "ShadowCaster" }
ZWrite On
ZTest LEqual
ColorMask 0
Cull Off
HLSLPROGRAM
#pragma target 4.5
#pragma vertex ShadowVert
#pragma fragment ShadowFrag
#pragma multi_compile_instancing
#pragma shader_feature_local _WIND_ON
#pragma shader_feature_local _DISTANCE_FADE_ON
#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;
}
TEXTURE2D(_MainTex);
TEXTURE2D(_WindNoiseTex);
SAMPLER(sampler_MainTex);
SAMPLER(sampler_WindNoiseTex);
CBUFFER_START(UnityPerMaterial)
float4 _MainTex_ST;
float _WindStrength;
float _WindSpeed;
float _WindFrequency;
float4 _WindDirection;
float _WindNoiseScale;
float _WindGustStrength;
float _WindGustFrequency;
float _FadeStart;
float _FadeEnd;
float _FadeMinScale;
float _Cutoff;
CBUFFER_END
struct Attributes
{
float4 positionOS : POSITION;
float3 normalOS : NORMAL;
float2 uv : TEXCOORD0;
float4 color : COLOR;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct Varyings
{
float4 positionCS : SV_POSITION;
float2 uv : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
float3 WindAnimation(float3 worldPos, float height, float stiffness, float time)
{
#if defined(_WIND_ON)
float3 windDir = normalize(_WindDirection.xyz);
float windPhase = dot(worldPos.xz, windDir.xz) * _WindFrequency + time * _WindSpeed;
float wave = sin(windPhase) * 0.5 + 0.5;
float gustPhase = time * _WindGustFrequency;
float gust = sin(gustPhase) * sin(gustPhase * 2.3) * _WindGustStrength;
float windFactor = (wave + gust - 0.25) * _WindStrength;
windFactor *= height * height;
windFactor *= (1 - stiffness);
return windDir * windFactor;
#else
return float3(0, 0, 0);
#endif
}
Varyings ShadowVert(Attributes IN)
{
Varyings OUT;
UNITY_SETUP_INSTANCE_ID(IN);
UNITY_TRANSFER_INSTANCE_ID(IN, OUT);
float height = IN.color.r;
float stiffness = IN.color.a;
float3 posOS = IN.positionOS.xyz;
#if defined(_DISTANCE_FADE_ON)
float3 worldPosBase = TransformObjectToWorld(float3(0, 0, 0));
float distToCam = distance(worldPosBase, _WorldSpaceCameraPos);
float fadeFactor = saturate((distToCam - _FadeStart) / (_FadeEnd - _FadeStart));
float scale = lerp(1, _FadeMinScale, fadeFactor);
posOS *= scale;
#endif
float3 worldPos = TransformObjectToWorld(posOS);
worldPos += WindAnimation(worldPos, height, stiffness, _Time.y);
float3 worldNormal = TransformObjectToWorldNormal(IN.normalOS);
worldPos = ApplyShadowBiasCustom(worldPos, worldNormal, _LightDirection);
float4 posCS = TransformWorldToHClip(worldPos);
#if UNITY_REVERSED_Z
posCS.z = min(posCS.z, UNITY_NEAR_CLIP_VALUE);
#else
posCS.z = max(posCS.z, UNITY_NEAR_CLIP_VALUE);
#endif
OUT.positionCS = posCS;
OUT.uv = TRANSFORM_TEX(IN.uv, _MainTex);
return OUT;
}
float4 ShadowFrag(Varyings IN) : SV_Target
{
float alpha = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, IN.uv).a;
clip(alpha - _Cutoff);
return 0;
}
ENDHLSL
}
// Depth pass
Pass
{
Name "DepthOnly"
Tags { "LightMode" = "DepthOnly" }
ZWrite On
ColorMask 0
Cull Off
HLSLPROGRAM
#pragma target 4.5
#pragma vertex DepthVert
#pragma fragment DepthFrag
#pragma multi_compile_instancing
#pragma shader_feature_local _WIND_ON
#pragma shader_feature_local _DISTANCE_FADE_ON
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
TEXTURE2D(_MainTex);
SAMPLER(sampler_MainTex);
CBUFFER_START(UnityPerMaterial)
float4 _MainTex_ST;
float _WindStrength;
float _WindSpeed;
float _WindFrequency;
float4 _WindDirection;
float _WindGustStrength;
float _WindGustFrequency;
float _FadeStart;
float _FadeEnd;
float _FadeMinScale;
float _Cutoff;
CBUFFER_END
struct Attributes
{
float4 positionOS : POSITION;
float2 uv : TEXCOORD0;
float4 color : COLOR;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct Varyings
{
float4 positionCS : SV_POSITION;
float2 uv : TEXCOORD0;
};
float3 WindAnimation(float3 worldPos, float height, float stiffness, float time)
{
#if defined(_WIND_ON)
float3 windDir = normalize(_WindDirection.xyz);
float windPhase = dot(worldPos.xz, windDir.xz) * _WindFrequency + time * _WindSpeed;
float wave = sin(windPhase) * 0.5 + 0.5;
float gustPhase = time * _WindGustFrequency;
float gust = sin(gustPhase) * sin(gustPhase * 2.3) * _WindGustStrength;
float windFactor = (wave + gust - 0.25) * _WindStrength;
windFactor *= height * height;
windFactor *= (1 - stiffness);
return windDir * windFactor;
#else
return float3(0, 0, 0);
#endif
}
Varyings DepthVert(Attributes IN)
{
Varyings OUT;
UNITY_SETUP_INSTANCE_ID(IN);
float height = IN.color.r;
float stiffness = IN.color.a;
float3 posOS = IN.positionOS.xyz;
#if defined(_DISTANCE_FADE_ON)
float3 worldPosBase = TransformObjectToWorld(float3(0, 0, 0));
float distToCam = distance(worldPosBase, _WorldSpaceCameraPos);
float fadeFactor = saturate((distToCam - _FadeStart) / (_FadeEnd - _FadeStart));
posOS *= lerp(1, _FadeMinScale, fadeFactor);
#endif
float3 worldPos = TransformObjectToWorld(posOS);
worldPos += WindAnimation(worldPos, height, stiffness, _Time.y);
OUT.positionCS = TransformWorldToHClip(worldPos);
OUT.uv = TRANSFORM_TEX(IN.uv, _MainTex);
return OUT;
}
float4 DepthFrag(Varyings IN) : SV_Target
{
float alpha = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, IN.uv).a;
clip(alpha - _Cutoff);
return 0;
}
ENDHLSL
}
}
// ==================== Built-in Pipeline SubShader ====================
SubShader
{
Tags { "RenderType" = "TransparentCutout" "Queue" = "AlphaTest" }
Pass
{
Name "GrassBuiltIn"
Tags { "LightMode" = "ForwardBase" }
Cull Off
CGPROGRAM
#pragma target 3.0
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fwdbase
#pragma multi_compile_fog
#pragma multi_compile_instancing
#pragma shader_feature_local _WIND_ON
#pragma shader_feature_local _SSS_ON
#pragma shader_feature_local _SPECULAR_ON
#include "UnityCG.cginc"
#include "Lighting.cginc"
#include "AutoLight.cginc"
sampler2D _MainTex;
float4 _MainTex_ST;
float4 _BaseColor;
float4 _TipColor;
float _GradientPower;
float _WindStrength;
float _WindSpeed;
float _WindFrequency;
float4 _WindDirection;
float _WindGustStrength;
float _WindGustFrequency;
float4 _SSSColor;
float _SSSStrength;
float _SSSDistortion;
float _SSSPower;
float4 _SpecularColor;
float _SpecularIntensity;
float _SpecularPower;
float _AO;
float _AOPower;
float _Cutoff;
struct appdata
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float2 uv : TEXCOORD0;
float4 color : COLOR;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct v2f
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float3 worldPos : TEXCOORD1;
float3 worldNormal : TEXCOORD2;
float4 vertexColor : TEXCOORD3;
float heightGradient : TEXCOORD4;
SHADOW_COORDS(5)
UNITY_FOG_COORDS(6)
UNITY_VERTEX_INPUT_INSTANCE_ID
};
float3 WindAnimation(float3 worldPos, float height, float stiffness, float time)
{
#if defined(_WIND_ON)
float3 windDir = normalize(_WindDirection.xyz);
float windPhase = dot(worldPos.xz, windDir.xz) * _WindFrequency + time * _WindSpeed;
float wave = sin(windPhase) * 0.5 + 0.5;
float gustPhase = time * _WindGustFrequency;
float gust = sin(gustPhase) * sin(gustPhase * 2.3) * _WindGustStrength;
float windFactor = (wave + gust - 0.25) * _WindStrength;
windFactor *= height * height * (1 - stiffness);
return windDir * windFactor;
#else
return float3(0, 0, 0);
#endif
}
v2f vert(appdata v)
{
v2f o;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_TRANSFER_INSTANCE_ID(v, o);
float height = v.color.r;
float stiffness = v.color.a;
float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
worldPos += WindAnimation(worldPos, height, stiffness, _Time.y);
o.pos = mul(UNITY_MATRIX_VP, float4(worldPos, 1));
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.worldPos = worldPos;
o.worldNormal = UnityObjectToWorldNormal(v.normal);
o.vertexColor = v.color;
o.heightGradient = height;
TRANSFER_SHADOW(o)
UNITY_TRANSFER_FOG(o, o.pos);
return o;
}
float4 frag(v2f i) : SV_Target
{
UNITY_SETUP_INSTANCE_ID(i);
float4 texColor = tex2D(_MainTex, i.uv);
clip(texColor.a - _Cutoff);
float3 viewDir = normalize(_WorldSpaceCameraPos - i.worldPos);
float3 normal = normalize(i.worldNormal);
float gradientFactor = pow(i.heightGradient, _GradientPower);
float3 albedo = lerp(_BaseColor.rgb, _TipColor.rgb, gradientFactor) * texColor.rgb;
float ao = pow(lerp(1, i.vertexColor.g, _AO), _AOPower);
float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
float3 lightColor = _LightColor0.rgb;
float shadow = SHADOW_ATTENUATION(i);
float NdotL = saturate(dot(normal, lightDir));
float3 diffuse = albedo * lightColor * NdotL * shadow;
float3 sss = float3(0, 0, 0);
#if defined(_SSS_ON)
float3 H = normalize(lightDir + normal * _SSSDistortion);
float VdotH = pow(saturate(dot(viewDir, -H)), _SSSPower);
sss = _SSSColor.rgb * VdotH * _SSSStrength * lightColor * shadow;
#endif
float3 specular = float3(0, 0, 0);
#if defined(_SPECULAR_ON)
float3 halfDir = normalize(lightDir + viewDir);
float NdotH = saturate(dot(normal, halfDir));
float spec = pow(NdotH, _SpecularPower);
specular = _SpecularColor.rgb * spec * _SpecularIntensity * lightColor * shadow;
#endif
float3 ambient = albedo * 0.1;
float3 finalColor = (diffuse + sss + specular + ambient) * ao;
UNITY_APPLY_FOG(i.fogCoord, finalColor);
return float4(finalColor, texColor.a);
}
ENDCG
}
}
// ==================== HDRP SubShader ====================
SubShader
{
PackageRequirements { "com.unity.render-pipelines.high-definition" }
Tags { "RenderType" = "TransparentCutout" "Queue" = "AlphaTest" "RenderPipeline" = "HDRenderPipeline" }
Pass
{
Name "GrassHDRP"
Tags { "LightMode" = "Forward" }
Cull Off
HLSLPROGRAM
#pragma target 4.5
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_instancing
#pragma shader_feature_local _WIND_ON
#pragma shader_feature_local _SSS_ON
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl"
TEXTURE2D(_MainTex);
SAMPLER(sampler_MainTex);
CBUFFER_START(UnityPerMaterial)
float4 _MainTex_ST;
float4 _BaseColor;
float4 _TipColor;
float _GradientPower;
float _WindStrength;
float _WindSpeed;
float _WindFrequency;
float4 _WindDirection;
float _WindGustStrength;
float _WindGustFrequency;
float4 _SSSColor;
float _SSSStrength;
float _SSSDistortion;
float _SSSPower;
float _AO;
float _AOPower;
float _Cutoff;
CBUFFER_END
struct Attributes
{
float4 positionOS : POSITION;
float3 normalOS : NORMAL;
float2 uv : TEXCOORD0;
float4 color : COLOR;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct Varyings
{
float4 positionCS : SV_POSITION;
float2 uv : TEXCOORD0;
float3 worldPos : TEXCOORD1;
float3 worldNormal : TEXCOORD2;
float4 vertexColor : TEXCOORD3;
float heightGradient : TEXCOORD4;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
float3 WindAnimation(float3 worldPos, float height, float stiffness, float time)
{
#if defined(_WIND_ON)
float3 windDir = normalize(_WindDirection.xyz);
float windPhase = dot(worldPos.xz, windDir.xz) * _WindFrequency + time * _WindSpeed;
float wave = sin(windPhase) * 0.5 + 0.5;
float gust = sin(time * _WindGustFrequency) * sin(time * _WindGustFrequency * 2.3) * _WindGustStrength;
float windFactor = (wave + gust - 0.25) * _WindStrength * height * height * (1 - stiffness);
return windDir * windFactor;
#else
return float3(0, 0, 0);
#endif
}
Varyings vert(Attributes IN)
{
Varyings OUT;
UNITY_SETUP_INSTANCE_ID(IN);
UNITY_TRANSFER_INSTANCE_ID(IN, OUT);
float height = IN.color.r;
float stiffness = IN.color.a;
float3 worldPos = TransformObjectToWorld(IN.positionOS.xyz);
worldPos += WindAnimation(worldPos, height, stiffness, _Time.y);
OUT.positionCS = TransformWorldToHClip(worldPos);
OUT.uv = IN.uv * _MainTex_ST.xy + _MainTex_ST.zw;
OUT.worldPos = worldPos;
OUT.worldNormal = TransformObjectToWorldNormal(IN.normalOS);
OUT.vertexColor = IN.color;
OUT.heightGradient = height;
return OUT;
}
float4 frag(Varyings IN) : SV_Target
{
UNITY_SETUP_INSTANCE_ID(IN);
float4 texColor = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, IN.uv);
clip(texColor.a - _Cutoff);
float3 viewDir = GetWorldSpaceNormalizeViewDir(IN.worldPos);
float3 normal = normalize(IN.worldNormal);
float gradientFactor = pow(IN.heightGradient, _GradientPower);
float3 albedo = lerp(_BaseColor.rgb, _TipColor.rgb, gradientFactor) * texColor.rgb;
float ao = pow(lerp(1, IN.vertexColor.g, _AO), _AOPower);
float3 lightDir = float3(0.5, 0.8, 0.2);
float NdotL = saturate(dot(normal, lightDir));
float3 diffuse = albedo * NdotL;
float3 sss = float3(0, 0, 0);
#if defined(_SSS_ON)
float3 H = normalize(lightDir + normal * _SSSDistortion);
float VdotH = pow(saturate(dot(viewDir, -H)), _SSSPower);
sss = _SSSColor.rgb * VdotH * _SSSStrength;
#endif
float3 finalColor = (diffuse + sss + albedo * 0.1) * ao;
return float4(finalColor, texColor.a);
}
ENDHLSL
}
}
FallBack "Universal Render Pipeline/Unlit"
}