124 lines
3.9 KiB
Plaintext
124 lines
3.9 KiB
Plaintext
Shader "Custom/Outline"
|
|
{
|
|
Properties
|
|
{
|
|
_MainTex ("Main Texture", 2D) = "white" {}
|
|
_OutlineColor ("Outline Color", Color) = (1,0.5,0,1)
|
|
_OutlineWidth ("Outline Width", Range(0, 0.5)) = 0.1
|
|
_GlowIntensity ("Glow Intensity", Range(0, 10)) = 3
|
|
_Falloff ("Falloff", Range(0.1, 5)) = 2
|
|
}
|
|
|
|
SubShader
|
|
{
|
|
Tags { "RenderType"="Transparent" "Queue"="Transparent" }
|
|
LOD 100
|
|
|
|
Pass
|
|
{
|
|
Cull Off
|
|
Blend SrcAlpha OneMinusSrcAlpha
|
|
ZWrite Off
|
|
|
|
CGPROGRAM
|
|
#pragma vertex vert
|
|
#pragma fragment frag
|
|
#include "UnityCG.cginc"
|
|
|
|
struct appdata
|
|
{
|
|
float4 vertex : POSITION;
|
|
float2 uv : TEXCOORD0;
|
|
};
|
|
|
|
struct v2f
|
|
{
|
|
float2 uv : TEXCOORD0;
|
|
float4 vertex : SV_POSITION;
|
|
float2 scaledWidth : TEXCOORD1;
|
|
float2 uvSign : TEXCOORD2;
|
|
};
|
|
|
|
sampler2D _MainTex;
|
|
float4 _MainTex_ST;
|
|
float4 _OutlineColor;
|
|
float _OutlineWidth;
|
|
float _GlowIntensity;
|
|
float _Falloff;
|
|
|
|
v2f vert (appdata v)
|
|
{
|
|
v2f o;
|
|
o.vertex = UnityObjectToClipPos(v.vertex);
|
|
|
|
// 计算缩放符号
|
|
float2 scaleSign = float2(
|
|
sign(unity_ObjectToWorld._m00),
|
|
sign(unity_ObjectToWorld._m11)
|
|
);
|
|
|
|
// 修正UV方向
|
|
o.uv = v.uv * scaleSign + (1 - scaleSign)/2;
|
|
o.uv = TRANSFORM_TEX(o.uv, _MainTex);
|
|
|
|
// 计算有效描边宽度(基于世界空间缩放)
|
|
float2 worldScale = float2(
|
|
length(unity_ObjectToWorld._m00_m10_m20),
|
|
length(unity_ObjectToWorld._m01_m11_m21)
|
|
);
|
|
o.scaledWidth = _OutlineWidth / abs(worldScale) * 0.5;
|
|
|
|
o.uvSign = scaleSign;
|
|
return o;
|
|
}
|
|
|
|
fixed4 frag (v2f i) : SV_Target
|
|
{
|
|
// 基础颜色采样(处理镜像)
|
|
float2 baseUV = i.uv;
|
|
if(i.uvSign.x < 0) baseUV.x = 1 - baseUV.x;
|
|
if(i.uvSign.y < 0) baseUV.y = 1 - baseUV.y;
|
|
|
|
fixed4 col = tex2D(_MainTex, baseUV);
|
|
if(col.a > 0.99) return col;
|
|
|
|
// 渐变参数初始化
|
|
float maxDistance = length(i.scaledWidth);
|
|
float glow = 0;
|
|
|
|
// 多级采样实现渐变
|
|
const int steps = 8;
|
|
for(int s=1; s<=steps; s++)
|
|
{
|
|
float progress = s/(float)steps;
|
|
float currentWidth = progress * maxDistance;
|
|
|
|
// 环形采样
|
|
for(float angle=0; angle<6.283; angle+=1.047) // 60度步进
|
|
{
|
|
float2 dir = float2(cos(angle), sin(angle));
|
|
float2 sampleUV = baseUV + dir * currentWidth;
|
|
fixed4 sampleCol = tex2D(_MainTex, sampleUV);
|
|
|
|
if(sampleCol.a > 0.95)
|
|
{
|
|
// 距离衰减计算
|
|
float attenuation = 1 - pow(progress, _Falloff);
|
|
glow += attenuation * _GlowIntensity / steps;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 颜色混合(非线性插值)
|
|
float glowFactor = saturate(glow);
|
|
fixed4 final = col;
|
|
final.rgb = lerp(col.rgb, _OutlineColor.rgb, glowFactor);
|
|
final.a = max(col.a, glowFactor * _OutlineColor.a);
|
|
|
|
return final;
|
|
}
|
|
ENDCG
|
|
}
|
|
}
|
|
} |