Search code examples
jqueryhtmlsvgsvg-filters

Additive alpha blending with masks


I want to create the illusion of glowing light in the dark, in the example I have two rect masks on top of each other but as you can see there is an alpha blending issue. Is there a way to merge the 2 mask rects together?

Mouse-over the window on the codepen link to see what I mean.

<svg width="976" height="549" xmlns="http://www.w3.org/2000/svg">
    <defs>
        <radialGradient id="lightsource">
            <stop offset="0%" stop-color="black" />
            <stop offset="50%" stop-color="black" />
            <stop offset="100%" stop-color="white" />
        </radialGradient>
        <mask id="mask1" x="0" y="0" width="976" height="549">
        <rect x="0" y="0" width="976" height="549" fill="white" />
        <ellipse ry="60" rx="64" id="svg_1" cy="122.5" cx="101.5" stroke-width="none" fill="url(#lightsource)"/>
        <ellipse ry="60" rx="64" id="svg_2" cy="175.5" cx="216" stroke-width="none" fill="url(#lightsource)"/>
        </mask>
    </defs>
    <g>
        <rect x="0" y="0" id="cool" width="976" height="549" mask="url(#mask1)" fill="black" />
    </g>
</svg>

http://codepen.io/anon/pen/cFAqx


Solution

  • Yes, just use a <feBlend> filter. In this case, it would make more sense to blend two copies of the same gradient mask after offsetting them in the positive and negative X directions.

    <defs>
      <radialGradient id="lightsource">
        <stop offset="0%" stop-color="black" />
        <stop offset="50%" stop-color="black" />
        <stop offset="100%" stop-color="white" />
      </radialGradient>
      <mask id="mask1" x="0" y="0" width="976" height="549">
        <rect x="0" y="0" width="976" height="549" fill="white" />
        <ellipse filter="url(#f1)" ry="60" rx="64" id="svg" cy="122.5" cx="101.5" stroke-width="none" fill="url(#lightsource)"/>
      </mask>
      <filter id="f1" x="-100%" y="0" width="300%" height="100%">
        <feOffset result="light1" in="SourceGraphic" dx="-50" dy="0" />
        <feOffset result="light2" in="SourceGraphic" dx="50" dy="0" />
        <feBlend in="light1" in2="light2" mode="darken" />
      </filter>
    </defs>
    

    Here, the <filter> element creates two copies of the ellipse and combines them with a darken filter. I've updated your codepen to show it working: http://codepen.io/anon/pen/LtcIj

    Edit: Actually, a multiply blend might look better.