Shader "Custom/SphereGradientShader" { Properties { [HDR] _BaseColor("Base Color", Color) = (1,1,1,1) [HDR] _HeadColor("Head Color (Facing End)", Color) = (1,1,1,1) [HDR] _TailColor("Tail Color (Facing Start)", Color) = (1,1,1,1) [Toggle(_EMISSION_ON)] _UseEmission("Enable Emission", Float) = 0 [HDR] _EmissionColor("Emission Color", Color) = (0,0,0,0) _EmissionIntensity("Emission Intensity", Range(0, 10)) = 1.0 _MoveDir("Movement Direction", Vector) = (0,0,1,0) _GradientScale("Gradient Scale", Range(0, 2)) = 1.0 _GradientPower("Gradient Power", Range(0.5, 5)) = 2.0 [Enum(UnityEngine.Rendering.BlendMode)] _SrcBlend("Src Blend", Float) = 1 [Enum(UnityEngine.Rendering.BlendMode)] _DstBlend("Dst Blend", Float) = 0 [Enum(Off, 0, On, 1)] _ZWrite("ZWrite", Float) = 1 } SubShader { Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" "Queue" = "Geometry" } LOD 100 Pass { Blend [_SrcBlend] [_DstBlend] ZWrite [_ZWrite] HLSLPROGRAM #pragma shader_feature _EMISSION_ON #pragma vertex vert #pragma fragment frag #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" struct Attributes { float4 positionOS : POSITION; float2 uv : TEXCOORD0; float3 normalOS : NORMAL; }; struct Varyings { float4 positionCS : SV_POSITION; float2 uv : TEXCOORD0; float3 normalWS : TEXCOORD1; float3 positionWS : TEXCOORD2; }; CBUFFER_START(UnityPerMaterial) float4 _BaseColor; float4 _HeadColor; float4 _TailColor; float4 _EmissionColor; float _EmissionIntensity; float4 _MoveDir; float _GradientScale; float _GradientPower; CBUFFER_END Varyings vert(Attributes input) { Varyings output; output.positionWS = TransformObjectToWorld(input.positionOS.xyz); output.positionCS = TransformWorldToHClip(output.positionWS); output.uv = input.uv; output.normalWS = TransformObjectToWorldNormal(input.normalOS); return output; } half4 frag(Varyings input) : SV_Target { float3 normal = normalize(input.normalWS); float3 moveDir = normalize(_MoveDir.xyz); // 计算空间渐变:-1 到 1 映射到 0 到 1 // 面向 endPoint (moveDir) 时 dot 接近 1,使用 HeadColor // 面向 startPoint (-moveDir) 时 dot 接近 -1,使用 TailColor // 反转:使用 -dot 或者 1.0 - spatialLerp float spatialLerp = dot(normal, -moveDir) * 0.5 + 0.5; // 应用幂函数调整渐变分布 spatialLerp = clamp(spatialLerp, 0.0, 1.0); half4 color = lerp(_TailColor, _HeadColor, spatialLerp); // 叠加一个基础的菲涅尔效果增加立体感 float3 viewDir = normalize(GetWorldSpaceViewDir(input.positionWS)); float fresnel = 1.0 - saturate(dot(normal, viewDir)); fresnel = pow(fresnel, _GradientPower) * _GradientScale; color.rgb += fresnel * color.rgb * 0.5; // 边缘轻微提亮 // 自发光叠加 #if defined(_EMISSION_ON) color.rgb += _EmissionColor.rgb * _EmissionIntensity; #endif return color; } ENDHLSL } } }