Home > Mobile >  Elliptical light source using SVG filters
Elliptical light source using SVG filters

Time:04-13

I am trying to apply a Vignette effect on images with SVG filters. I am trying to implement this with the <fePointLight> primitive, but I find this a bit limited in that it is always has a circular shape. Is it possible to change the width such that the lighting effect takes on a wide elliptical shape? This is currently the filter I am using:

<filter id="vignette">
    <feFlood id="flood-5" result="blackfield-6" x="0%" y="0%" width="100%" height="100%" flood-color="#000000" flood-opacity="1"/>
    <feSpecularLighting id="specular-5" result="Spotlight-6" lighting-color="#FFFFFF" surfaceScale="1" specularConstant="1" specularExponent="100">
        <fePointLight id="pointlight-5" x="720" y="450" z="1200"/>
    </feSpecularLighting>
    <feBlend id="svg-7" result="A-6" in="blackfield-6" in2="Spotlight-6" mode="lighten"/>
    <feBlend id="blend-5" result="B-6" in="A-6" in2="SourceGraphic" mode="multiply"/>
</filter>

I am aware that it is possible to do this with a radial gradient effect on a separate shape, but I have a requirement that it must be done purely using SVG filters.

CodePudding user response:

The values of the x=350 and y=240 attributes of the fePointLight filter are chosen so that the point is in the center of the image.
Different values for the z attribute of the fePointLight filter render the light source at different depths in relation to the drawing. The nearest position corresponds to the largest size.

Please watch in full screen
Hover over image

#img {
width:700px;
height:481px;
}
#img:hover {
filter:url(#spotlight);
}

 
<img id="img" src="https://i.stack.imgur.com/mBuDo.jpg" >
      
<svg  width="700" height="481" viewBox="0 0 700 481" xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs>
    <filter id="spotlight">
      <feSpecularLighting result="spotlight" specularConstant="3.5"
          specularExponent="70" lighting-color="grey">
        <fePointLight x="350" y="240" z="520"/>
      </feSpecularLighting>
      <feComposite in="SourceGraphic" in2="spotlight" operator="in"/>
    </filter>
  </defs>
  
</svg>

Other image

#img {
width:700px;
height:481px;
}
#img:hover {
filter:url(#spotlight);
}
 <img id="img" src="https://i.stack.imgur.com/GlhkD.jpg" >
      
<svg  width="700" height="481" viewBox="0 0 700 481" xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs>
    <filter id="spotlight">
      <feSpecularLighting result="spotlight" specularConstant="3.5"
          specularExponent="70" lighting-color="grey">
        <fePointLight x="350" y="240" z="520"/>
      </feSpecularLighting>
      <feComposite in="SourceGraphic" in2="spotlight" operator="in"/>
    </filter>
  </defs>
  

CodePudding user response:

If you want that sort of effect (elliptical light), you probably want to be using a spotlight rather than a point light.

If you offset the light position to one side and shine the cone down at a shallow-ish angle, you will get an elliptical spot.

<svg width="600" height="529">
  <defs>
    <filter id="spotlight">
      <feSpecularLighting result="spotlight" specularConstant="1.5"
          specularExponent="4" lighting-color="#FFF">
        <feSpotLight x="-200" y="265" z="400" limitingConeAngle="10" pointsAtX="300" pointsAtY="265" />
      </feSpecularLighting>
      <feComposite in="SourceGraphic" in2="spotlight" operator="out" k1="0" k2="1" k3="1" k4="0"/>
    </filter>
  </defs>

  <rect x="0" y="0" width="600" height="529" style="fill: skyblue; filter:url(#spotlight);"/>
</svg>

Note that the lighting filter components can be unreliable to use. Each browser has differences in interpretation of the standard. Not to mention some bugs. A point in case is the above example, which looks different in Firefox and Chrome.

But good luck with your project.

  • Related