104 lines
4.0 KiB
Plaintext
104 lines
4.0 KiB
Plaintext
Shader "Custom/ImprovedPseudoShadow" {
|
||
Properties {
|
||
[Header(Base)]
|
||
_MainTex ("Texture", 2D) = "white" {}
|
||
_Color ("Main Color", Color) = (1,1,1,1)
|
||
|
||
[Header(Shadow)]
|
||
_ShadowColor ("Shadow Color", Color) = (0.2, 0.2, 0.3, 1) // 默认偏蓝的阴影
|
||
_ShadowThreshold ("Shadow Threshold", Range(-1,1)) = 0.0
|
||
_ShadowSmoothness ("Shadow Smoothness", Range(0,1)) = 0.1
|
||
|
||
[Header(Lighting Mode)]
|
||
_UseWorldLight ("Use Fixed World Light?", Range(0,1)) = 0
|
||
_FakeLightDir ("Fake Light Dir (XYZ)", Vector) = (0.5, 1, 0.5, 0) // 模拟从右上方来的光
|
||
}
|
||
|
||
SubShader {
|
||
Tags { "RenderType"="Transparent" }
|
||
LOD 100
|
||
|
||
Pass {
|
||
CGPROGRAM
|
||
#pragma vertex vert
|
||
#pragma fragment frag
|
||
// 开启 GPU Instancing 支持
|
||
#pragma multi_compile_instancing
|
||
#include "UnityCG.cginc"
|
||
|
||
struct appdata {
|
||
float4 vertex : POSITION;
|
||
float3 normal : NORMAL;
|
||
float2 uv : TEXCOORD0;
|
||
UNITY_VERTEX_INPUT_INSTANCE_ID // Instancing ID
|
||
};
|
||
|
||
struct v2f {
|
||
float2 uv : TEXCOORD0;
|
||
float4 vertex : SV_POSITION;
|
||
float lightFactor : TEXCOORD1; // 传递光照因子
|
||
UNITY_VERTEX_INPUT_INSTANCE_ID // Instancing ID
|
||
};
|
||
|
||
sampler2D _MainTex;
|
||
float4 _MainTex_ST;
|
||
|
||
// 声明 Instancing 属性变量
|
||
UNITY_INSTANCING_BUFFER_START(Props)
|
||
UNITY_DEFINE_INSTANCED_PROP(fixed4, _Color)
|
||
UNITY_DEFINE_INSTANCED_PROP(fixed4, _ShadowColor)
|
||
UNITY_DEFINE_INSTANCED_PROP(float4, _FakeLightDir)
|
||
UNITY_DEFINE_INSTANCED_PROP(float, _ShadowThreshold)
|
||
UNITY_DEFINE_INSTANCED_PROP(float, _ShadowSmoothness)
|
||
UNITY_DEFINE_INSTANCED_PROP(float, _UseWorldLight)
|
||
UNITY_INSTANCING_BUFFER_END(Props)
|
||
|
||
v2f vert (appdata v) {
|
||
v2f o;
|
||
UNITY_SETUP_INSTANCE_ID(v);
|
||
UNITY_TRANSFER_INSTANCE_ID(o, v);
|
||
|
||
o.vertex = UnityObjectToClipPos(v.vertex);
|
||
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
|
||
|
||
float3 normalWorld = UnityObjectToWorldNormal(v.normal);
|
||
float3 lightDir;
|
||
|
||
float useWorldLight = UNITY_ACCESS_INSTANCED_PROP(Props, _UseWorldLight);
|
||
float3 fakeDir = normalize(UNITY_ACCESS_INSTANCED_PROP(Props, _FakeLightDir).xyz);
|
||
float3 viewDir = normalize(WorldSpaceViewDir(v.vertex));
|
||
// 用lerp实现分支
|
||
lightDir = normalize(lerp(viewDir, fakeDir, useWorldLight));
|
||
|
||
float dotProduct = dot(normalWorld, lightDir);
|
||
o.lightFactor = dotProduct;
|
||
return o;
|
||
}
|
||
|
||
fixed4 frag (v2f i) : SV_Target {
|
||
UNITY_SETUP_INSTANCE_ID(i);
|
||
|
||
// 获取属性
|
||
fixed4 mainColor = UNITY_ACCESS_INSTANCED_PROP(Props, _Color);
|
||
fixed4 shadowColor = UNITY_ACCESS_INSTANCED_PROP(Props, _ShadowColor);
|
||
float threshold = UNITY_ACCESS_INSTANCED_PROP(Props, _ShadowThreshold);
|
||
float smoothness = UNITY_ACCESS_INSTANCED_PROP(Props, _ShadowSmoothness);
|
||
|
||
fixed4 texCol = tex2D(_MainTex, i.uv) * mainColor;
|
||
|
||
// 改进2:更平滑且可控的阈值计算 (Smoothstep)
|
||
// lightFactor 越大说明越直接面对光源
|
||
float lightIntensity = smoothstep(threshold, threshold + smoothness, i.lightFactor);
|
||
|
||
// 改进3:基于光照强度的颜色插值 (Lerp)
|
||
// 0 (背光) -> ShadowColor
|
||
// 1 (受光) -> Texture Color
|
||
fixed3 finalRGB = lerp(shadowColor.rgb * texCol.rgb, texCol.rgb, lightIntensity);
|
||
|
||
return fixed4(finalRGB, texCol.a);
|
||
}
|
||
ENDCG
|
||
}
|
||
}
|
||
FallBack "VertexLit"
|
||
} |