Shader "NLD_URP/NLD_Scene_Grass" { Properties { [MainTexture]_BaseMap ("主贴图", 2D) = "white" {} [MainColor] _BaseColor("基础颜色", Color) = (1, 1, 1, 1) _Cutoff("Alpha裁剪", Range(0.0, 1.0)) = 0.5 _GroundColorTex ("地面颜色贴图", 2D) = "white" {} _GroundSize("地面大小(宽,高,融合高度)", Vector) = (50, 50, 0, 0) _WindNoiseTex ("风噪声贴图", 2D) = "white" {} _WindParams("风参数(XUV,YUV,摆动min,摆动max)", Vector) = (0.1, 0.1, 0, 0) _WindDirection("风向(风向xyz,风贴图强度缩放)", Vector) = (1, 0, 0, 0) _TimeScale("自然摆动时间缩放", Range(0, 1)) = 1 _WindColor("风颜色", Color) = (1, 1, 1, 1) _WindColorParams("风颜色参数(压亮,截取min,截取max)", Vector) = (0.8, 0.2, 1, 0) _ShadowIntensity("阴影强度", Range(0, 1)) = 1 [Toggle(USE_HALF_PRECISION)] _UseHalfPrecision("使用half", Float) = 0 } SubShader { Tags { "RenderType"="Transparent" "RenderPipeline" = "UniversalPipeline" } LOD 100 HLSLINCLUDE #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl" TEXTURE2D(_BaseMap); SAMPLER(sampler_BaseMap); TEXTURE2D(_GroundColorTex); SAMPLER(sampler_GroundColorTex); sampler2D _WindNoiseTex; struct Attributes_LT { float4 positionOS : POSITION; float2 uv : TEXCOORD0; UNITY_VERTEX_INPUT_INSTANCE_ID }; struct Varyings_LT { float4 positionCS : SV_POSITION; float2 uv : TEXCOORD0; float4 worldPosAndGroundU : TEXCOORD1; float2 windNoiseAndGroundV : TEXCOORD2; UNITY_VERTEX_INPUT_INSTANCE_ID UNITY_VERTEX_OUTPUT_STEREO }; #if !defined(UNITY_INSTANCING_ENABLED) CBUFFER_START(UnityPerMaterial) #endif float _Cutoff; float4 _BaseColor; float4 _GroundSize; float4 _WindParams; float4 _WindDirection; float _TimeScale; float4 _BaseMap_ST; float4 _GroundColorTex_ST; float4 _WindNoiseTex_ST; float4 _WindColor; float4 _WindColorParams; float _ShadowIntensity; #if !defined(UNITY_INSTANCING_ENABLED) CBUFFER_END #endif #ifdef USE_HALF_PRECISION #define GRASS_FLOAT half #define GRASS_FLOAT2 half2 #define GRASS_FLOAT3 half3 #define GRASS_FLOAT4 half4 #else #define GRASS_FLOAT float #define GRASS_FLOAT2 float2 #define GRASS_FLOAT3 float3 #define GRASS_FLOAT4 float4 #endif Varyings_LT Vert(Attributes_LT input) { Varyings_LT output = (Varyings_LT)0; UNITY_SETUP_INSTANCE_ID(input); UNITY_TRANSFER_INSTANCE_ID(input, output); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); float3 worldPos = TransformObjectToWorld(input.positionOS.xyz); float2 groundStartPos = _GroundSize.xy * -0.5; float2 groundUV = (worldPos.xz - groundStartPos) * rcp(_GroundSize.xy); float2 windUv = groundUV + _Time.y * _WindParams.xy; float2 windUvWrap = windUv * _WindNoiseTex_ST.xy + _WindNoiseTex_ST.zw; float windNoise = tex2Dlod(_WindNoiseTex, float4(windUvWrap, 0, 0)).r; float lerpProgress = saturate((worldPos.y - _WindParams.z) * rcp(_WindParams.w - _WindParams.z)); float windPhase = (windNoise * _WindDirection.w + _TimeScale * _Time.y) * 6.28318530718; float3 moveDt = _WindDirection.xyz * (lerpProgress * sin(windPhase)); worldPos += moveDt; output.positionCS = TransformWorldToHClip(worldPos); output.uv = input.uv * _BaseMap_ST.xy + _BaseMap_ST.zw; output.worldPosAndGroundU = float4(worldPos, groundUV.x); output.windNoiseAndGroundV = float2(windNoise, groundUV.y); return output; } ENDHLSL Pass { Cull Off Name "ForwardLit" Tags { "LightMode" = "UniversalForward" } ZWrite On ZTest LEqual HLSLPROGRAM #pragma target 3.0 #pragma vertex Vert #pragma fragment Frag #pragma multi_compile_instancing #pragma multi_compile _ _MAIN_LIGHT_SHADOWS #pragma multi_compile _ _SHADOWS_SOFT #pragma shader_feature_local USE_HALF_PRECISION float4 Frag(Varyings_LT input): SV_Target { GRASS_FLOAT4 baseColor = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, input.uv); clip(baseColor.a - _Cutoff); GRASS_FLOAT2 groundUV = GRASS_FLOAT2(input.worldPosAndGroundU.w, input.windNoiseAndGroundV.y); GRASS_FLOAT4 groundColor = SAMPLE_TEXTURE2D(_GroundColorTex, sampler_GroundColorTex, groundUV); GRASS_FLOAT4 grassColor = _BaseColor; GRASS_FLOAT windNoise = input.windNoiseAndGroundV.x; GRASS_FLOAT windMask = saturate((windNoise - _WindColorParams.y) * rcp(_WindColorParams.z - _WindColorParams.y)); GRASS_FLOAT windColorStrength = windNoise * windNoise * _WindColorParams.x; grassColor = lerp(grassColor, _WindColor, windMask * windColorStrength); GRASS_FLOAT3 worldPos = input.worldPosAndGroundU.xyz; GRASS_FLOAT lerpProgress = saturate(worldPos.y * rcp(_GroundSize.z)); GRASS_FLOAT4 lerpColor = lerp(groundColor, grassColor, lerpProgress); float4 shadowCoord = TransformWorldToShadowCoord(worldPos); Light mainLight = GetMainLight(shadowCoord); GRASS_FLOAT shadowStrength = lerp(1, mainLight.shadowAttenuation, _ShadowIntensity); lerpColor.rgb *= shadowStrength; return lerpColor; } ENDHLSL } Pass { Cull Off Name "ShadowCaster" Tags { "LightMode" = "ShadowCaster" } HLSLPROGRAM #pragma target 3.0 #pragma vertex Vert #pragma fragment Frag #pragma multi_compile_instancing float4 Frag(Varyings_LT input): SV_Target { float4 baseColor = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, input.uv); clip(baseColor.a - _Cutoff); return float4(1, 1, 1, 1); } ENDHLSL } } }