svgsvg-filtersbump-mapping

SVG filter bump mapping with diffuse lighting spills out


I am trying to create a bump mapping effect in SVG using luminanceToAlpha conversion of an image and then altering the location of a point light on the overall surface.

Here is the short fiddle I created, https://jsfiddle.net/5g2qncq8/6/

Code snippet:

<defs>
<filter id="bump" x="0" y="0" height="100%" width="100%" >
<feColorMatrix in="SourceGraphic" type="luminanceToAlpha" result="bumpMap"/>
<feDiffuseLighting in="bumpMap" surfaceScale="1" diffuseConstant="10" result="shading"> 
<fePointLight in="SourceGraphic" id="light" x="300" y="300" z="10">
</fePointLight>
</feDiffuseLighting>
<feBlend in="SourceGraphic" mode="multiply" result="lit"/>
</filter>
</defs>

When you scroll over the image, the location of the point light is updated and the image goes darker as the pointer is further away from it. The problem that I have is, while the house is actually polygon shaped, I see some extra greyish rectangular area (over the house) when the point light is away. Why does this happen?

It obviously disappears when the light is shone on top of the house. Can someone suggest ways to get rid of this grey area?

I know that I could be missing something obvious. Any help or pointers are appreciated. Cheers!


Solution

  • This happens because the feBlend formula is cr = (1-qa)*cb + (1-qb)ca + cacb. If your light is A (say opaque mid-grey) and your transparent black background is B, then the color of the pixel will be (1-1)(.0/.0/.0) + (1-0)(0.5/.05/.05) +.5*.0 ==>> grey.

    And the opacity is qr = 1 - (1-qa)(1-qb): 1 - (1-1)(1-0) = 1.

    In other words, if you have at least one opaque source, you're getting an opaque result.

    You can clip out the background by adding:

      <feComposite operator="in" in2="SourceGraphic"/>
    

    to the end of your filter.