Files
Ipseity-Demo/Assets/_Content/Shaders/PortalMeadow.shader
T
2026-09-28 14:58:25 +02:00

146 lines
6.9 KiB
Plaintext

Shader "Unheimlich/Portal Meadow"
{
Properties
{
_RootColor("Grass roots", Color) = (0.055, 0.12, 0.025, 1)
_TipColor("Grass tips", Color) = (0.35, 0.48, 0.12, 1)
_GroundColor("Ground", Color) = (0.08, 0.12, 0.035, 1)
_Curvature("Curvature", Float) = 0.006
_BendAngle("Bend angle (0 down, 180 up)", Range(0,360)) = 0
_StartDistance("Bend start distance", Float) = 6
_HorizontalInfluence("Horizontal influence", Range(0,1)) = 0.12
_WindStrength("Wind strength", Range(0,1)) = 0.22
_WindSpeed("Wind speed", Float) = 1.8
_WindDirection("Wind direction XZ", Vector) = (1,0.4,0,0)
[Enum(Default,0,Outside,1,Inside,2)] _MaskID("Portal mask", Float) = 0
[HideInInspector] _MeadowRegion("Circular region", Vector) = (0,0,0,0)
[HideInInspector] _MeadowEdgeFade("Edge fade", Float) = 4
[HideInInspector] _MeadowEdgeColor("Edge haze", Color) = (0.36,0.43,0.46,1)
}
SubShader
{
Tags { "RenderPipeline"="UniversalPipeline" "RenderType"="Opaque" "Queue"="Geometry" }
Cull Off
HLSLINCLUDE
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
#include "Include/CurvedWorld.hlsl"
#include "EnkiBilal/Include/Mask.hlsl"
CBUFFER_START(UnityPerMaterial)
float4 _RootColor, _TipColor, _GroundColor, _WindDirection;
float _Curvature, _StartDistance, _HorizontalInfluence, _BendAngle;
float _WindStrength, _WindSpeed, _MaskID;
float4 _MeadowRegion, _MeadowEdgeColor;
float _MeadowEdgeFade;
float4x4 _MeadowWorldToLocal;
CBUFFER_END
#include "Include/PortalMeadowRegion.hlsl"
float4x4 _Mask0, _Mask1, _Mask2;
struct Attributes { float4 positionOS : POSITION; float3 normalOS : NORMAL; float2 uv : TEXCOORD0; float4 color : COLOR; };
struct Varyings { float4 positionCS : SV_POSITION; float3 positionWS : TEXCOORD0; float3 normalWS : TEXCOORD1; float2 uv : TEXCOORD2; float4 color : COLOR; float fog : TEXCOORD3; float3 originalWS : TEXCOORD4; };
Varyings Vert(Attributes input)
{
Varyings output;
float3 p = input.positionOS.xyz;
float3 ws = TransformObjectToWorld(p);
float2 wind = _WindDirection.xy / max(length(_WindDirection.xy), 0.001);
// UV.y is zero at the roots. Color.a is zero for ground vertices.
float wave = sin(dot(ws.xz, float2(0.43,0.31)) - _Time.y * _WindSpeed);
wave += 0.35 * sin(dot(ws.xz, float2(1.7,-0.9)) - _Time.y * _WindSpeed * 2.1 + input.color.g * 6.28);
ws.xz += wind * (0.45 + wave * 0.55) * _WindStrength * input.uv.y * input.uv.y * input.color.a;
p = TransformWorldToObject(ws);
output.originalWS = ws;
float3 positionVS = CurvedWorldToFrame(ws);
float3 normalVS = CurvedWorldDirToFrame(TransformObjectToWorldNormal(input.normalOS));
normalVS = CurvedWorldNormalVS(positionVS, normalVS, _Curvature, _StartDistance, _HorizontalInfluence, _BendAngle);
CurvedWorld_float(p, _Curvature, _StartDistance, _HorizontalInfluence, _BendAngle, p);
output.positionWS = TransformObjectToWorld(p);
output.positionCS = TransformWorldToHClip(output.positionWS);
output.normalWS = normalize(CurvedFrameDirToWorld(normalVS));
output.uv = input.uv;
output.color = input.color;
output.fog = ComputeFogFactor(output.positionCS.z);
return output;
}
void ApplyMask(float3 positionWS)
{
float alpha;
Mask_float(positionWS, _MaskID, _Mask0, _Mask1, _Mask2, alpha);
clip(alpha - 0.5);
}
half4 Frag(Varyings input) : SV_Target
{
float edgeFade = ClipMeadowRegion(input.originalWS, input.positionCS.xy);
ApplyMask(input.positionWS);
half3 grass = lerp(_RootColor.rgb, _TipColor.rgb, saturate(input.uv.y));
half3 albedo = lerp(_GroundColor.rgb, grass, input.color.a) * lerp(0.75, 1.25, input.color.r);
half3 n = normalize(input.normalWS);
// Light layers keep the lights of the other world (e.g. the cave spot) out of PortalB.
uint meshRenderingLayers = GetMeshRenderingLayer();
Light sun = GetMainLight();
half3 illumination = max(SampleSH(half3(0,1,0)), half3(0.32,0.32,0.32));
if (IsMatchingLightLayer(sun.layerMask, meshRenderingLayers))
illumination += sun.color * (0.3 + 0.7 * abs(dot(n, sun.direction))) * sun.distanceAttenuation;
#if defined(_ADDITIONAL_LIGHTS)
uint count = GetAdditionalLightsCount();
for (uint i = 0u; i < count; ++i)
{
Light light = GetAdditionalLight(i, input.positionWS);
if (IsMatchingLightLayer(light.layerMask, meshRenderingLayers))
illumination += light.color * saturate(abs(dot(n, light.direction))) * light.distanceAttenuation;
}
#endif
return half4(lerp(_MeadowEdgeColor.rgb, MixFog(albedo * illumination, input.fog), edgeFade), 1);
}
half4 DepthFrag(Varyings input) : SV_Target { ClipMeadowRegion(input.originalWS, input.positionCS.xy); ApplyMask(input.positionWS); return 0; }
half4 NormalsFrag(Varyings input) : SV_Target
{
ClipMeadowRegion(input.originalWS, input.positionCS.xy);
ApplyMask(input.positionWS);
float3 normalWS = normalize(input.normalWS);
#if defined(_GBUFFER_NORMALS_OCT)
float2 oct = PackNormalOctQuadEncode(normalWS);
return half4(PackFloat2To888(saturate(oct * 0.5 + 0.5)), 0);
#else
return half4(normalWS, 0);
#endif
}
ENDHLSL
Pass
{
Name "Forward"
Tags { "LightMode"="UniversalForwardOnly" }
HLSLPROGRAM
#pragma vertex Vert
#pragma fragment Frag
#pragma target 3.5
#pragma multi_compile_fog
#pragma multi_compile _ _ADDITIONAL_LIGHTS
#pragma multi_compile _ _LIGHT_LAYERS
ENDHLSL
}
Pass
{
Name "DepthOnly"
Tags { "LightMode"="DepthOnly" }
ColorMask 0
HLSLPROGRAM
#pragma vertex Vert
#pragma fragment DepthFrag
#pragma target 3.5
ENDHLSL
}
Pass
{
Name "DepthNormals"
Tags { "LightMode"="DepthNormalsOnly" }
HLSLPROGRAM
#pragma vertex Vert
#pragma fragment NormalsFrag
#pragma target 3.5
#pragma multi_compile_fragment _ _GBUFFER_NORMALS_OCT
ENDHLSL
}
}
}