Search code examples
svgfirefoxsvg-filters

SVG filter lightsources not working in Firefox


I have the following SVG to render checkers on a board where both the board and checkers have a nice bevelled effect. I'm very happy with the effect on Chrome (and Safari) but Firefox seems to ignore the effect.

Would appreciate help understanding why it doesn't work as all the primitives show as supported in Firefox (caniuse.com).

<svg width="800" height="200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <filter id="counter" filterUnits="objectBoundingBox">
    <feGaussianBlur in="SourceAlpha" stdDeviation="2" result="blur" />
    <feSpecularLighting in="blur" surfaceScale="2" specularConstant="0.3" specularExponent="10" result="lightingOut" lightingColor="white">
      <fePointLight x="-2000" y="-2000" z="500" />
    </feSpecularLighting>
    <feComposite in="lightingOut" in2="SourceAlpha" operator="in" result="composite1" />
    <feComposite in="SourceGraphic" in2="composite1" operator="arithmetic" k1="0" k2="1" k3="1" />
  </filter>

  <rect width="400" height="200" fill="#ffffff" />
  <rect x="50" y="10" width="300" rx="10" ry="10" height="180" fill="#666666" filter="url(#counter)" />
  <circle cx="120" cy="100" r="20" filter="url(#counter)" fill="black" />
  <circle cx="250" cy="100" r="20" filter="url(#counter)" fill="#3333ff" />
</svg>

Codepen: https://codepen.io/jugglingcats/pen/RwWLQjJ

Many thanks


Solution

  • Firefox is not ignoring the effect, it's just very faint. If you increase surfaceScale and bring the point light nearer to the drawing surface, you'll be able to see it more clearly.

    There are a lot of inconsistencies in lightsource implementations cross-browser - for example FireFox uses sRGB color space by default for lightsources, so you have to set Chrome to use it explicitly. Then, you need to tweak things until you have something that looks the same. For example, specularConstant doesn't seem to be doing the same thing in each browser at 0.3 - but setting it to "1" seems to be consistent. Here is a filter that looks mostly the same. I had to switch out the fePointLight for a feDistantLight to avoid positioning calculation inconsistencies.

     <filter id="counter2" color-interpolation-filters="sRGB">
        <feGaussianBlur in="SourceAlpha" stdDeviation="2" result="blur" />
        <feSpecularLighting in="blur" surfaceScale="10" specularConstant="1" specularExponent="10" result="lightingOut" lightingColor="white">
          <feDistantLight azimuth="225" elevation="0" />
        </feSpecularLighting>
        <feComposite in="lightingOut" in2="SourceAlpha" operator="in" result="composite1" />
        <feComposite in="SourceGraphic" in2="composite1" operator="arithmetic" k1="0" k2="1" k3="1" />
      </filter>