如果场景不接受shadowmap,只有角色接收shadowmap的话会显示不正确
用shadowmap的方式显示阴影的时候,会产生一个效果,就是阴影不应该存在的地方也显示了阴影。
这部分是不应该存在的,因为光照是从人脸方向照过来的,所以这块应该是完全被遮挡的。
如果场景本身也接收投射阴影是看不到这阴影的,因为这块区域全部被自身的阴影遮挡了。
但我们在开发过程中,如果所有场景都投放阴影因为会出现双倍的dc,整体性能没那么好,而且显得场景黑,并且不是美术想要的,所以就不需要投射阴影了。
那么这块角色投射出来的阴影就成了问题点,理论上他不应该投射阴影。
分析问题:
这个问题出现的原因是因为:
1.我们会在每个接收阴影的shader中计算shadowmap的颜色和偏移,所以在下方会有偏移的阴影存在。
2.光照和角色阴影达到一个很大的夹角但还是产生了阴影
3.并且因为存在阴影偏移,假如有多层场景,会在很远的地方也出现阴影显示。跟前面说是一个道理,因为下个地板存在shadow bias
解决办法:
1.我们可以在渲染阴影的代码中加一个光照和场景的点乘来获取夹角,如果小于一定角度(比如0)则不显示阴影。
half shadowAttenuation = ddotn > 0.0 ? MainLightRealtimeShadow(i.shadowCoord) : 1.0;
2.如果不想太远距离还能显示阴影,则需要判断距离
private void OnControllerColliderHit(ControllerColliderHit hit)
{
var currentHit = hit.gameObject;
if (currentHit != null && mCurrentHit != currentHit)
{
mCurrentHit = currentHit;
if (!mPrevHits.Contains(currentHit))
{
mPrevHits.Add(currentHit);
}
if (mPrevHits.Count != 0)
{
for (int i = mPrevHits.Count - 1; i >= 0; i--)
{
var prevHit = mPrevHits[i];
if (prevHit != null && prevHit != currentHit)
{
if (Vector3.Distance(prevHit.transform.position, gameObject.transform.position) >= 11)
{
SetShadowReceive(prevHit, false);
mPrevHits.Remove(prevHit);
}
}
}
}
SetShadowReceive(currentHit, true);
}
}