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 } 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; // TEXTURE2D(_WindNoiseTex); // SAMPLER(sampler_WindNoiseTex); struct Attributes_LT { float4 positionOS : POSITION; float2 uv : TEXCOORD0; UNITY_VERTEX_INPUT_INSTANCE_ID }; struct Varyings_LT { float4 positionCS : SV_POSITION; // UV float2 uv : TEXCOORD0; // world position float3 worldPos : TEXCOORD1; float windNoise : 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 Varyings_LT Vert(Attributes_LT input) { Varyings_LT output; UNITY_SETUP_INSTANCE_ID(input); output.worldPos = TransformObjectToWorld(input.positionOS).xyz; // 采样风噪声 float2 groundStartPos = -float2(_GroundSize.x, _GroundSize.y) * 0.5; float2 groundUV = (output.worldPos.xz - groundStartPos.xy) / _GroundSize.xy; float xUVMove = _Time.y * _WindParams.x; float yUVMove = _Time.y * _WindParams.y; float2 windUv = groundUV + float2(xUVMove, yUVMove); float2 windUvWrap = TRANSFORM_TEX(windUv, _WindNoiseTex); float windNoise = tex2Dlod(_WindNoiseTex, float4(windUvWrap, 0, 0)).r; float windMinY = _WindParams.z; float windMaxY = _WindParams.w; float lerpProgress = clamp((output.worldPos.y - windMinY) / (windMaxY - windMinY), 0, 10); // 根据风噪声做顶点偏移 float3 moveDt = lerp(0, _WindDirection.xyz, lerpProgress) * sin((windNoise * _WindDirection.w + _TimeScale * _Time.y) * 2 * 3.14); output.worldPos = output.worldPos + moveDt; output.positionCS = TransformWorldToHClip(output.worldPos); output.uv = TRANSFORM_TEX(input.uv, _BaseMap); output.windNoise = windNoise; 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 // 开启instance #pragma multi_compile_instancing // 开启接收阴影 #pragma multi_compile _ _MAIN_LIGHT_SHADOWS //主光源阴影 #pragma multi_compile _ _SHADOWS_SOFT //软阴影 float4 Frag(Varyings_LT input): SV_Target { // 基础色alpha clip float4 baseColor = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, input.uv); if (baseColor.a < _Cutoff) discard; // 根据worldPos计算地面颜色 float2 groundStartPos = -float2(_GroundSize.x, _GroundSize.y) * 0.5; float2 groundUV = (input.worldPos.xz - groundStartPos.xy) / _GroundSize.xy; float4 groundColor = SAMPLE_TEXTURE2D(_GroundColorTex, sampler_GroundColorTex, groundUV); // 基础色 float4 grassColor = _BaseColor; // 读取风噪声强度 if (input.windNoise > _WindColorParams.y && input.windNoise < _WindColorParams.z) { float scaleWindNoise = input.windNoise * _WindColorParams.x; grassColor = lerp(grassColor, _WindColor, input.windNoise * scaleWindNoise); } // 根据高度做颜色混合 float blendHeight = _GroundSize.z; float lerpProgress = clamp(input.worldPos.y / blendHeight, 0, 1); float4 lerpColor = lerp(groundColor, grassColor, lerpProgress); // 获取阴影 float4 shadowCoord = TransformWorldToShadowCoord(input.worldPos); Light mainLight = GetMainLight(shadowCoord); // 读取shadowStrength float shadowStrength = lerp(1, mainLight.shadowAttenuation, _ShadowIntensity); lerpColor *= shadowStrength; return lerpColor; } ENDHLSL } Pass { Cull Off Name "ShadowCaster" Tags { "LightMode" = "ShadowCaster" } HLSLPROGRAM #pragma target 3.0 #pragma vertex Vert #pragma fragment Frag // 开启instance #pragma multi_compile_instancing float4 Frag(Varyings_LT input): SV_Target { // 基础色alpha clip float4 baseColor = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, input.uv); if (baseColor.a < _Cutoff) discard; return float4(1, 1, 1, 1); } ENDHLSL } } }