假阴影
用一个偏移的椭圆形来模拟球体投射的阴影,不需要任何光线追踪,关键代码是:
下面拆解这个技巧的原理。
什么是假阴影
真实的阴影需要追踪光线、计算遮挡,在片元着色器里代价很高。假阴影(fake shadow)的思路是:阴影在现实中大致是球体在地面的投影,形状近似椭圆。直接在球体下方画一个模糊的深色椭圆,视觉上就能以假乱真。
用 SDF 画椭圆
length(vec2(p.x, p.y+0.28)) - 0.28 是一个圆形的有符号距离场(SDF):
p.y + 0.28把圆心向下移了 0.28 单位(从球心移到球的下方)- 0.28是圆的半径,让距离场的 0 值落在圆边缘上
把这个距离扔进 smoothstep(0.0, 0.08, d),就得到从圆内部(值 0)到圆外部(值 1)的柔和遮罩。用 1.0 - ... 翻转后,圆内是 1(有阴影),圆外是 0(无阴影)。
控制阴影浓度
原始遮罩最大是 1.0(100% 黑色)。乘以 0.35 把最深阴影压到 35%,让阴影半透明、更自然。
然后用 mix(bg, vec3(0.0), shadow) 把背景色和黑色按阴影强度混合:shadow=0 时显示背景,shadow=0.35 时背景稍微变暗。
试着改一改
| 改动 | 效果 |
|---|---|
把 0.28(偏移量)改为 0.35 | 阴影位置下移,球体感觉悬浮更高 |
把 0.08(柔化范围)改为 0.02 | 阴影边缘更锐利 |
把 0.35(浓度)改为 0.7 | 阴影更深更明显 |
把半径 0.28 改为 0.15 | 阴影变小 |
练习
练习代码中球体已经绘制完成,但 shadow 变量还未计算。补全阴影的 SDF 计算,并将其混合到背景颜色里,让球体下方出现模糊的椭圆阴影。
答案解析
起始代码中背景直接用 bg,没有任何阴影。
length(vec2(p.x, p.y+0.28)) - 0.28 在球心正下方 0.28 处画了一个半径 0.28 的圆形 SDF。smoothstep(0.0, 0.08, d) 将 0 到 0.08 的距离范围平滑映射到 0→1,1.0 - ... 翻转为圆内是 1。乘以 0.35 控制透明度,最后 mix(bg, vec3(0.0), shadow) 把深色叠到背景上。
试着把偏移量 0.28 改成 p.x * 0.2 + 0.28,让阴影随 x 坐标偏移,模拟光从斜上方照射的效果。