创建时间: 2025-12-05最后更新: 2025-12-22作者: yangbo(96862973d)

1概述

feDiffuseLighting 用于模拟漫反射光照.

它利用输入图像的 Alpha 通道(透明度)来模拟光照效果, 其中

  • Alpha = 1: 表示高处, 光照强度最大
  • Alpha = 0: 表示低处, 光照强度最小
  • Alpha = 0.5(中间值): 表示中间位置, 处于斜坡, 光照强度为中间值

滤镜会根据这些高低起伏以及你设置的光源位置来计算哪里亮、哪里暗, 从而模拟出立体感. 或者 3D 的浮雕质感.

他的参数如下:

  • in:输入图像, 通常是 SourceGraphic 或者 BackgroundImage
  • surfaceScale:峰值高度, 默认值为 1, 取值范围为 0 到 100. 值越大, 阴影和高光越强烈, 起伏感越强
  • diffuseConstant:漫反射系数, 默认值为 1, 取值范围为 0 到 1, 这决定了光照的整体强度和亮度
  • lighting-color:光源颜色, 默认值为 white

feDiffuseLighting 本身只是一个计算材质的表面, 它必须包含以下三种光源之一才能生效:

  • feDistantLight:平行光, 模拟太阳或灯泡等远距离光源, 由 azimuth(方位角) 和 elevation (仰角)两个角度确定方向
  • fePointLight:点光源, 模拟灯泡等近距离光, 由 xyz 三个坐标确定位置
  • feSpotLight:聚光灯, 模拟手电筒或激光等定向光源, 由 xyz 三个坐标确定位置, 以及 pointsAtXpointsAtYpointsAtZ 三个坐标确定目标位置

2案例:粗糙纹理生成

下面这个案例中, 我们先使用 feTurbulence 生成一个噪点纹理, 然后使用 feDiffuseLighting 来模拟一个光照. 这样, 我们就能够得到一个粗糙纸张的纹理.

预览
index.tsx
01
export default function App() {
02
return (
03
<div className="w-full h-full flex flex-col items-center justify-center bg-gray-200 rounded-xl p-8 relative overflow-hidden">
04
<svg width="300" height="200" viewBox="0 0 300 200" xmlns="http://www.w3.org/2000/svg">
05
<defs>
06
<filter id="demo1-diffuse-lighting">
07
{/* 1. 生成基底噪音 (Turbulence) */}
08
<feTurbulence type="fractalNoise" baseFrequency="0.04" numOctaves="5" result="noise" />
09
{/* 2. 应用漫反射光照 */}
10
{/* lighting-color: 设置暖黄色光, 营造旧纸张感 */}
11
{/* surfaceScale: 设置为 2, 让纹理适度突起 */}
12
<feDiffuseLighting
13
in="noise"
14
surfaceScale={2}
15
lightingColor="#fdf5e6"
16
result="lightOutput"
17
>
18
{/* 使用平行光, 从左上角照射 */}
19
<feDistantLight azimuth={45} elevation={60} />
20
</feDiffuseLighting>
21
</filter>
22
</defs>
23
24
{/* 显示结果 */}
25
<rect x="0" y="0" width="100%" height="100%" filter="url(#demo1-diffuse-lighting)" />
26
</svg>
27
</div>
28
);
29
}
30

3案例:3D 文字效果

这个案例, 我们首先利用 feGaussianBlur 对原始图像进行高斯模糊, 它把文字的 Alpha 通道边缘变“糊”了, 然后使用 feDiffuseLighting 来模拟一个光照. 这样, 我们就能够得到一个 3D 文字效果.

预览
index.tsx
01
export default function App() {
02
return (
03
<div className="w-full h-full flex flex-col items-center justify-center bg-gray-900 rounded-xl p-8 relative overflow-hidden">
04
<svg width="400" height="150" viewBox="0 0 400 150" xmlns="http://www.w3.org/2000/svg">
05
<defs>
06
<filter id="demo2-diffuse-lighting">
07
{/* 1. 获取源图像的 Alpha 通道 */}
08
{/* 2. 使用高斯模糊平滑 Alpha 边缘 */}
09
{/* 如果不模糊, 边缘是垂直峭壁, 光照效果会很生硬;模糊后变成斜坡, 光照更自然 */}
10
<feGaussianBlur in="SourceAlpha" stdDeviation="2" result="blur" />
11
12
{/* 3. 应用光照 */}
13
{/* surfaceScale: 5 让文字看起来很厚 */}
14
<feDiffuseLighting in="blur" surfaceScale="5" lightingColor="white" result="light">
15
<feDistantLight azimuth="135" elevation="45" />
16
</feDiffuseLighting>
17
18
{/* 4. 合成:将光照结果叠加到原始颜色上 */}
19
{/* 使用 arithmetic 模式:result = k1*in*in2 + k2*in + k3*in2 + k4 */}
20
{/* 这里主要保留了光照的阴影细节并与原色混合 */}
21
<feComposite
22
in="light"
23
in2="SourceGraphic"
24
operator="arithmetic"
25
k1="1"
26
k2="0"
27
k3="0"
28
k4="0"
29
/>
30
</filter>
31
</defs>
32
<text
33
x="50%"
34
y="50%"
35
textAnchor="middle"
36
dy=".3em"
37
fontFamily="Verdana"
38
fontWeight="bold"
39
fontSize="60"
40
fill="#4a90e2"
41
filter="url(#demo2-diffuse-lighting)"
42
>
43
SVG 3D
44
</text>
45
</svg>
46
</div>
47
);
48
}
49

4案例:点光源照射

这个案例模拟一个黑暗房间里, 一盏灯照亮物体的效果. 这展示了 fePointLight 的威力, 以及如何利用 SVG 模拟光影衰减.

  • 这里使用了 <fePointLight>. 光源被固定在画布中心上方 (x=150, y=150, z=40).
  • 使用了 <feComposite operator="multiply">. 这是关键步骤:光照图(亮处白, 暗处黑)乘以原图颜色.
  • 结果:光源正下方的物体最亮, 远离中心的物体逐渐隐入黑暗, 非常有氛围感.
预览
index.tsx
01
export default function App() {
02
return (
03
<div className="w-full h-full flex flex-col items-center justify-center rounded-xl p-8 relative overflow-hidden">
04
<svg width="300" height="300" viewBox="0 0 300 300" xmlns="http://www.w3.org/2000/svg">
05
<defs>
06
<filter id="demo3-diffuse-lighting">
07
{/* 1. 光照层 */}
08
{/* 注意:这里我们用 SourceGraphic, 假设它是一个有 alpha 变化的复杂图形 */}
09
{/* Z 轴位置设为 40, 模拟光源悬浮在物体上方 */}
10
<feDiffuseLighting
11
in="SourceGraphic"
12
surfaceScale={10}
13
lightingColor="#ffcc00"
14
result="light"
15
>
16
<fePointLight x={150} y={150} z={40} />
17
</feDiffuseLighting>
18
19
{/* 2. 混合层 */}
20
{/* 将光照结果与原始图形混合. Multiply (正片叠底) 模式非常适合做光影 */}
21
{/* 只有被光照亮的地方才会显示颜色, 其他地方变暗 */}
22
<feComposite in="SourceGraphic" in2="light" operator="multiply" />
23
</filter>
24
</defs>
25
26
{/* 背景:暗色 */}
27
<rect width="100%" height="100%" fill="#111" />
28
29
{/* 一个复杂的图形组 */}
30
<g filter="url(#demo3-diffuse-lighting)">
31
{/* 创造一些圆圈, 模拟凸起物 */}
32
<circle cx="100" cy="100" r="40" fill="#44aa88" />
33
<circle cx="200" cy="100" r="30" fill="#cc5555" />
34
<circle cx="150" cy="200" r="50" fill="#4488aa" />
35
<rect x="0" y="0" width="300" height="300" fill="rgba(255,255,255,0.2)" />
36
</g>
37
</svg>
38
</div>
39
)
40
}
41
0
专栏首页
到顶
专栏目录