datax 面试题_【UPS引用IT面试题】面试问题:UnitySh… - 看准网

最近想着自己拿SRP写个能用的管线试试的,写到阴影的时候发现自己对Unity的阴影绘制流程并没有一个毕竟全面的了解,正好借此机会把Unity默认管线的阴影绘制过一遍

一、非屏幕空间阴影

我们从最简单的入手,目标PC DX11平台,不要Cascade,不要 screen space shadowmap。在 Graphics setting 里关掉 Cascaded Shadow,场景只打一个 hard shadow 的平行光,此时场景和 framedebugger 如下:

f7199***683700656895cddd8f2ff7831.jpg

3f8869bcf0609cd3dbaa1704786de1ce.png

可以看到没有 screen space shadow 的 collect 阶段了,阴影渲染阶段直接调用了 std 的 shadowcaster pass,涉及代码如下:

#define TRANSFER_SHADOW_CASTER_NOPOS(o,opos) \

opos = UnityClipSpaceShadowCasterPos(v.vertex, v.normal); \

opos = UnityApplyLinearShadowBias(opos);

float4 UnityClipSpaceShadowCasterPos(float4 vertex, float3 normal)

{

float4 wPos = mul(unity_ObjectToWorld, vertex);

if (unity_LightShadowBias.z != 0.0)

{

float3 wNormal = UnityObjectToWorldNormal(normal);

float3 wLight = normalize(UnityWorldSpaceLightDir(wPos.xyz));

// apply normal offset bias (inset position along the normal)

// bias needs to be scaled by sine between normal and light direction

// (http://the-witness.net/news/2013/09/shadow-mapping-summary-part-1/)

//

// unity_LightShadowBias.z contains user-specified normal offset amount

// scaled by world space texel size.

float shadowCos = dot(wNormal, wLight);

float shadowSine = sqrt(1-shadowCos*shadowCos);

float normalBias = unity_LightShadowBias.z * shadowSine;

wPos.xyz -= wNormal * normalBias;

}

return mul(UNITY_MATRIX_VP, wPos);

}

float4 UnityApplyLinearShadowBias(float4 clipPos)

{

#if defined(UNITY_REVERSED_Z)

// We use max/min instead of clamp to ensure proper handling of the rare case

// where both numerator and denominator are zero and the fraction becomes NaN.

clipPos.z += max(-1, min(unity_LightShadowBias.x / clipPos.w, 0));

float clamped = min(clipPos.z, clipPos.w*UNITY_NEAR_CLIP_VALUE);

#else

clipPos.z += saturate(unity_LightShadowBias.x/clipPos.w);

float clamped = max(clipPos.z, clipPos.w*UNITY_NEAR_CLIP_VALUE);

#endif

clipPos.z = lerp(clipPos.z, clamped, unity_LightShadowBias.y);

return clipPos;

}

其解释我直接引用 topameng 的:

如果z值没有偏移,很容易 Shadow Acne 现象。类似的比如z-fighting, 而如果z偏移值过大,又容易出现Peter Panning 现象,影子和物体出现分离现在常用的shadow bias的计算方法,是基于物体斜度的称为slope scale based depth bias 就是UnityClipSpaceShadowCasterPos中的内容。UnityApplyLinearShadowBias函数是在裁剪空间中的线性增加Z坐标的值unity_LightShadowBiasx表示阴影裁切空间中的线性偏移bias一般是个比较小的负数比如-0.0005,透视相机unity是按照摄像机参数计算的这个值, y 表示插值,一般为1. z 代表阴影slope depth bias scale对于直射光你可以认为ShadowMap就是一张深度图, 你改变颜色信息并不能影响深度。上面提到过是返回SV_Target 和SV_Depth的区别。shadowMap = new RenderTexture(width, height, 16, RenderTextureFormat.Depth);这样给一样能很好的工作不过Unity有新的RenderTextureFormat.Shadowmap格式,在Depth上加了一些保护之类。UnityApplyLinearShadowBias 给的偏移是往离摄像机近的方向挪一点。两个偏移都是往摄像机近一点调节,并不是相互抵消的,如果出现Peter Panning影子和模型分离,可以去光源面板调整阴影的bias项

继续往后看,此时framedebugger 给出的 keywords 是 :

DIRECTIONAL SHADOWS_SCREEN LIGHTPROBE_SH

我们可以在 AutoLight.cginc 中看到对应的阴影代码:

// ---- Screen space direction light shadows helpers (any version)

#if defined (SHADOWS_SCREEN)

#if defined(UNITY_NO_SCREENSPACE_SHADOWS)

UNITY_DECLARE_SHADOWMAP(_ShadowMapTexture);

#define TRANSFER_SHADOW(a) a._ShadowCoord = mul( unity_WorldToShadow[0], mul( unity_ObjectToWorld, v.vertex ) );

inline fixed unitySampleShadow (unityShadowCoord4 shadowCoord)

{

#if defined(SHADOWS_

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值