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 } } }