文章摘要
这篇文章介绍了作者使用距离场技术实现2D软阴影效果的图形项目。核心是通过计算每个像素到形状的距离生成距离场,然后沿着像素到光源的射线进行步进检测,判断像素是否处于阴影中。作者使用自己开发的库快速生成距离场,并分享了实现原理。
文章总结
二维光线步进软阴影技术解析
免责声明:本文演示使用了部分移动设备可能不支持的WebGL功能。
核心原理:距离场
这项技术基于距离场实现——一种记录每个像素与图形边缘距离的特殊图像。浅灰色表示靠近图形,深灰色表示远离图形。项目启动时,系统会在2D画布上绘制文字并生成对应的距离场,这里使用了作者开发的高效距离场生成库。
光线步进算法
光照计算的核心思路是:对每个待着色像素,发射一条指向光源的射线: 1. 若射线与文字相交,则该像素处于阴影中 2. 传统逐像素检测效率低下 3. 光线步进的核心优势:利用距离场数据,每次安全推进当前点到最近图形的距离,避免漏检

软阴影实现三原则
- 近似相交原则:射线越接近图形,阴影越深(通过
sceneDist值判断) - 距离衰减原则:像素离近似相交点越远,阴影扩散越明显(通过
sceneDist/rayProgress比值控制) - 光源衰减原则:光照强度随距离平方衰减
glsl
// 核心算法代码示例
vec2 rayOrigin = ...;
float rayProgress = 0.;
float lightContribution = 1.;
for (int i = 0; i < 64; i++) {
float sceneDist = getDistance(rayOrigin + rayProgress * rayDirection);
lightContribution = min(lightContribution, sceneDist / rayProgress);
rayProgress += sceneDist;
}
技术优化与挑战
- 带状伪影问题:因步进采样不足导致,采用Inigo Quilez提出的改进方案
- 随机扰动技术:通过
sceneDist * randomJitter增加采样随机性,缓解带状伪影(但会产生噪点) - 性能平衡:使用固定步数循环替代while循环,避免极端情况下的性能问题
效果展示
最终实现的软阴影具有渐变效果,虽然不符合物理真实,但视觉效果更柔和美观。作者表示该技术仍在优化中,欢迎通过Twitter提供建议。
致谢:感谢Jessica Liu等同事对本文的审阅,同时欢迎加入Figma团队共事。
评论总结
这篇评论主要围绕一个技术博客中的实时演示效果展开讨论,主要观点如下:
- 对技术演示效果的赞赏
- "It's always impressive to see a live demo...especially one that runs so fast and slick on mobile"(评论1)
- "this looks great"(评论7)
- 相关技术联想与比较
- 提到类似技术"radiance cascades"(评论2)
- 联想到PICO-8上的阴影投射实现(评论3)
- 技术实现细节讨论
- 认为计算方法很聪明:"a very clever series of calculations"(评论5)
- 建议考虑SDF梯度:"I wonder if it would help if you looked at gradient of the SDF"(评论6)
- 交互提示与功能建议
- 指出首图是交互式演示:"Note that the first image is an interactive demo"(评论4)
- 建议增加动态光源:"make the light source a bouncing ball"(评论9)
- 性能对比反思
- 对比企业仪表盘性能:"my company's 'enterprise dashboard' struggles to render 50 divs"(评论8)
- 演示链接询问
- 询问演示链接:"is there no demo link?"(评论7)