我们美术有个需求是只需要修改阴影的颜色,于是我第一想法和网上很多人的想法一样,去修改unity设置的光照颜色。
于是就修改了Lightting中的Setting的
网上也很多人说这样修改。但是我修改后发现其实这个修改的是环境光,是全局的一个光照,并不是只对阴影生效。所以这个修改时不能做到“只需要”修改阴影颜色的需求的。
我们知道阴影一般有两部分组成,第一是该物体是否能投射阴影,第二是该物体是否能接受阴影。
然后我就参考shader中实现阴影的部分。
在shader中,一般我们要真能投射阴影的话需要FallBack "Diffuse"来实现。因为在unity的shader中Diffuse做了投射阴影的行为。我们可以看到unity自身的shader写法
可以观察到其实这里没其他区别,区别主要是有个Fallback "Mobile/VertexLit"。那么我们尝试只Fallback这个vertexlit是否能投射阴影。
结论是可以的。
然后我们看看Mobile/VertexLit做了什么
主要在这个pass里,他的光照类型也是ShadowCaster然后顶点及片元都是shadow相关的计算。可得知这块就是核心的shaow投影算法。(具体他里面在做什么,大家可以自己查阅unity的shader)
如果我们想修改投影的颜色,这个投射投影的地方我们需不需要改变?
是不需要的,他只是关于阴影投射的方式,并不是真正显示投影的shader。
那么真正投射阴影的shader在哪呢?
其实就是在接受投影的shader中。
比如在地板上我们就由接受投影的shader来负责显示投影对象的
VtoS vertex_shader(Input v)
{
VtoS data;
data.pos = UnityObjectToClipPos(v.vertex);
data.uv_main_fog.xy = v.texcoord0.xy * _MainTex_ST.xy + _MainTex_ST.zw;
data.uv_main_fog.z = EBGFogVertex(v.vertex);
data.uv_lm = v.texcoord1.xy * unity_LightmapST.xy + unity_LightmapST.zw;
float3 worldN = normalize(mul((float3x3)unity_ObjectToWorld, v.normal));
data.worldN = worldN;
data._ShadowCoord = float4(0,0,0,0);
TRANSFER_VERTEX_TO_FRAGMENT(data);
return data;
}
float4 fragment_shader(VtoS IN) : COLOR0
{
fixed4 mainTex = tex2D(_MainTex, IN.uv_main_fog.xy);
fixed3 col = mainTex.rgb;
col *= _EBGEnvLightColorScale;
col *= _EBGEnvScale;
half3 light = 1;
half3 bakedColor = DecodeLightmap(UNITY_SAMPLE_TEX2D(unity_Lightmap, IN.uv_lm.xy));
light = bakedColor;
col *= light;
fixed alpha = 1.0;
col = EBGFogFragment(col, IN.uv_main_fog.z);
col = col * _EBGEnvAdjustScale + _EBGEnvAdjustOffset;
float atten = SHADOW_ATTENUATION(IN);
col = col * atten;
return fixed4(col, alpha);
}
在上面这个shader中,atten就是具体显示哪个像素需要显示阴影的地方。(具体的实现方式其实跟shadowmaptexture相关,大家可以自行看unity的shader)
那么我们分析如果不显示阴影的话,那么atten必须为1.
所以如果我们要让显示的阴影改变颜色的话就是改变col了,可以在atten不为1的时候给col乘上一个颜色。(如果你需要增加对比度或明暗度则可以转为hsv来运算)
col = fixed3(col.r * (atten < 1 ? _ShadowColor.r : 1) * atten, col.g * (atten < 1 ? _ShadowColor.g : 1) * atten, col.b * (atten < 1 ? _ShadowColor.b : 1) * atten);
具体shader为
Tags
{
"Queue"="Geometry"
"RenderType"="Environment"
"LightMode"="ForwardBase"
}
Lighting Off
Fog { Mode Off }
Cull Back
ZWrite On
ZTest LEqual
Blend Off
Subshader
{
LOD 400
Pass
{
CGPROGRAM
#include "UnityCG.cginc"
#include "Lighting.cginc"
#include "AutoLight.cginc"
#include "Assets/Scripts/Rendering/Shaders/Lib/EBG_Globals.cginc"
#pragma target 3.0
#pragma vertex vertex_shader
#pragma fragment fragment_shader
#pragma multi_compile_fwdbase
//EBG_FOG_ON EBG_DYNAMIC_SHADOWS_ON EBG_LIGHTMAP_ON EBG_VERTEX_LIGHTING_OFF EBG_ALPHA_CUTOFF_OFF EBG_HIGHLIGHTS_IGNORE_ALPHA_OFF EBG_REFLECTIONS_OFF EBG_PLANAR_REFLECTIONS_OFF EBG_FRESNEL_OFF EBG_DISABLE_LIGHTMAP_OFF
sampler2D _MainTex;
struct Input
{
float4 vertex : POSITION;
float2 texcoord0 : TEXCOORD0;
float3 normal : NORMAL;
float2 texcoord1 : TEXCOORD1;
};
struct VtoS
{
float4 pos : SV_POSITION;
float3 uv_main_fog : TEXCOORD0;
float2 uv_lm : TEXCOORD1;
float4 _ShadowCoord : TEXCOORD8;
float3 worldN : TEXCOORD9;
};
float4 _MainTex_ST;
float4 _ShadowColor;
VtoS vertex_shader(Input v)
{
VtoS data;
data.pos = UnityObjectToClipPos(v.vertex);
data.uv_main_fog.xy = v.texcoord0.xy * _MainTex_ST.xy + _MainTex_ST.zw;
data.uv_main_fog.z = EBGFogVertex(v.vertex);
data.uv_lm = v.texcoord1.xy * unity_LightmapST.xy + unity_LightmapST.zw;
float3 worldN = normalize(mul((float3x3)unity_ObjectToWorld, v.normal));
data.worldN = worldN;
data._ShadowCoord = float4(0,0,0,0);
TRANSFER_VERTEX_TO_FRAGMENT(data);
return data;
}
float4 fragment_shader(VtoS IN) : COLOR0
{
fixed4 mainTex = tex2D(_MainTex, IN.uv_main_fog.xy);
fixed3 col = mainTex.rgb;
col *= _EBGEnvLightColorScale;
col *= _EBGEnvScale;
half3 light = 1;
half3 bakedColor = DecodeLightmap(UNITY_SAMPLE_TEX2D(unity_Lightmap, IN.uv_lm.xy));
light = bakedColor;
col *= light;
fixed alpha = 1.0;
col = EBGFogFragment(col, IN.uv_main_fog.z);
col = col * _EBGEnvAdjustScale + _EBGEnvAdjustOffset;
float atten = SHADOW_ATTENUATION(IN);
//col = col * atten;
col = fixed3(col.r * (atten < 1 ? _ShadowColor.r : 1) * atten, col.g * (atten < 1 ? _ShadowColor.g : 1) * atten, col.b * (atten < 1 ? _ShadowColor.b : 1) * atten);
return fixed4(col, alpha);
}
ENDCG
}
}
当然_ShadowColor是一个颜色值,初始时4个1。
_ShadowColor("Shadow Color", Color) = (1, 1, 1, 1)
然后我们再看阴影,他会根据你的shaowcolor变色了。