115 lines
4.6 KiB
Plaintext
115 lines
4.6 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)]
|
||
[Toggle(USE_WORLD_LIGHT)] _UseWorldLight ("Use Fixed World Light?", Float) = 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
|
||
// 开启着色器变体以支持两种光照模式
|
||
#pragma shader_feature USE_WORLD_LIGHT
|
||
|
||
#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_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;
|
||
|
||
#ifdef USE_WORLD_LIGHT
|
||
// 改进1:使用固定的世界空间伪光照方向
|
||
lightDir = normalize(UNITY_ACCESS_INSTANCED_PROP(Props, _FakeLightDir).xyz);
|
||
#else
|
||
// 原版逻辑:使用视线方向 (Headlamp)
|
||
// 注意:为了获得类似漫反射的效果,这里通常不需要取反,
|
||
// 但如果要模拟“边缘光”则算法不同。这里沿用原文档的思路:面朝相机越亮。
|
||
lightDir = normalize(WorldSpaceViewDir(v.vertex));
|
||
#endif
|
||
|
||
// 点积计算 (-1 到 1)
|
||
float dotProduct = dot(normalWorld, lightDir);
|
||
|
||
// 将点积结果保存,在片元阶段处理颜色,或者直接在这里计算
|
||
// 保持 Vertex Lighting 的高性能
|
||
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"
|
||
} |