Donner SVG Editor & Engine
SVG-native editor and embeddable SVG2 + CSS3 engine in C++20, with GPU (WebGPU) and compact CPU renderers, built for correctness, security, and performance.
Loading...
Searching...
No Matches
<feSpecularLighting>

<feSpecularLighting> is the shiny-highlight companion of <feDiffuseLighting>.

Where diffuse lighting gives you the matte component of the Phong reflection model - the soft, bright-toward-the-light look of a pool ball - specular lighting gives you the glossy component: the small, bright hotspot you see on a wet or metallic surface when a light reflects off it toward your eye. Use it to add shiny highlights to shapes; it's how you get the classic glossy-button look.

Like <feDiffuseLighting>, it reads the input's alpha channel as a height map (more opaque = taller surface at that spot) and uses the resulting surface normals to compute shading. The surface normal is the imaginary arrow sticking out of the terrain at each point; specular lighting is brightest where that arrow points exactly halfway between the light and the viewer. It must contain exactly one child light source - <feDistantLight>, <fePointLight>, or <feSpotLight> - and because the specular output is non-opaque (black everywhere except the highlight), you almost always composite it on top of a diffuse pass or the source graphic with <feComposite> using operator="arithmetic". As with diffuse lighting, feeding a solid alpha shape to this primitive produces a flat bump, so every example below first blurs SourceAlpha to get a smooth, rounded height map.

Example 1: basic specular highlight with a distant light

<filter id="f" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur in="SourceAlpha" stdDeviation="4" result="blur" />
<feSpecularLighting in="blur" surfaceScale="6" specularConstant="1.2"
specularExponent="20" lighting-color="white">
<feDistantLight azimuth="45" elevation="60" />
</feSpecularLighting>
</filter>

Everything outside the small bright hotspot is black - that's the empty (RGBA=0) background feSpecularLighting emits. In real use you'd composite this over something.

Example 2: same bump, point light

Using a <fePointLight> instead of a distant light - the hotspot sits under wherever the point light is, rather than from a fixed direction.

<feSpecularLighting in="blur" surfaceScale="6" specularConstant="1.2"
specularExponent="20" lighting-color="white">
<fePointLight x="40" y="40" z="40" />
</feSpecularLighting>

Moving the point's (x, y, z) drags the highlight around the surface - this is the primary knob for making highlights feel interactive. (See <feSpotLight> for a cone-shaped alternative that clips everything outside a narrow beam.)

Example 3: specularExponent

specularExponent is the "shininess" exponent from the Phong model. Small values (1-5) produce a broad, soft sheen; large values (50+) produce a tight, sharp mirror-like highlight.

specularExponent=1 20 80

Example 4: specularConstant

specularConstant is the overall brightness multiplier (the "ks" in Phong). At 0.3 the highlight is a faint sheen; at 2.0 it clips to fully white over a much larger area.

specularConstant=0.3 1.0 2.0

Example 5: putting it together - glossy button

This is the "why do I care" example. We take a colored circle, run it through <feDiffuseLighting> to give it matte shading, then add a <feSpecularLighting> pass for the glossy highlight, and composite both onto the original colored shape. The final result is a classic glossy-button look.

<filter id="glossy" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur in="SourceAlpha" stdDeviation="4" result="blur" />
<!-- Matte shading, multiplied into the source color -->
<feDiffuseLighting in="blur" surfaceScale="6" diffuseConstant="1.2"
lighting-color="white" result="diffuse">
<feDistantLight azimuth="45" elevation="60" />
</feDiffuseLighting>
<feComposite in="diffuse" in2="SourceGraphic" operator="arithmetic"
k1="1" k2="0" k3="0" k4="0" result="litColor" />
<!-- Glossy highlight, added on top -->
<feSpecularLighting in="blur" surfaceScale="6" specularConstant="1.4"
specularExponent="30" lighting-color="white" result="spec">
<feDistantLight azimuth="45" elevation="60" />
</feSpecularLighting>
<feComposite in="spec" in2="SourceAlpha" operator="in" result="specClipped" />
<feComposite in="specClipped" in2="litColor" operator="arithmetic"
k1="0" k2="1" k3="1" k4="0" />
</filter>
<circle cx="70" cy="70" r="50" fill="#3377cc" filter="url(#glossy)" />

Notice that both lighting primitives share the same blurred-alpha input and the same light source parameters - that's what makes the highlight sit in the right place relative to the matte shading. Varying the light's azimuth/elevation rotates both effects together.

Attributes
Attribute Default Description
surfaceScale 1 Height multiplier applied to the alpha channel.
specularConstant 1 Specular reflectance (ks). Overall highlight brightness.
specularExponent 1 Phong shininess exponent. Larger values give a tighter, sharper highlight.
lighting-color white Color of the light. Presentation attribute; can be set via CSS.

kernelUnitLength is not implemented; surface normals use the renderer's filter sample spacing.

Inherits standard filter primitive attributes (in, result, x, y, width, height) from donner::svg::SVGFilterPrimitiveStandardAttributes.