Files

106 lines
3.9 KiB
GLSL

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