Alexander
Alexander

Reputation: 278

how to make a svg scatter filter?

I try to turn a precise shapes into a series of scatted dots that have a higher density in the middle of the source image.

Example: White Circle on Black Background → Messier 92 (sorry i hive not enough reputation to embed the image)

Consequently a shape other then a circle should still be recognizable. Here is the best I was able to do:

I would call such an effect a scatter filter. Please tell me if you have a better name.

<svg height='100' width='100'>
  <filter id="cluster" filterUnits="userSpaceOnUse">
    <feGaussianBlur in="SourceGraphic" result='blurred' stdDeviation="10" />
    <feTurbulence type="turbulence" baseFrequency="9" numOctaves="4" result="turbulence" /> 
    <feDisplacementMap in2="turbulence" in="blurred" scale="10" xChannelSelector="R" yChannelSelector="G"  />
  </filter>
  <rect x='0' y='0' height='100' width='100' fill='black' />
  <circle cx='50' cy='50' fill='white' r='30' filter='url(#cluster)' />
</svg>

It is basically a fancy blur. The results look better with increased scale in feDisplacementMap.

<svg height='100' width='100'>
  <filter id="cluster" filterUnits="userSpaceOnUse">
    <feGaussianBlur in="SourceGraphic" result='blurred' stdDeviation="10" />
    <feTurbulence type="turbulence" baseFrequency="9" numOctaves="4" result="turbulence" /> 
    <feDisplacementMap in2="turbulence" in="blurred" scale="50" xChannelSelector="R" yChannelSelector="G"  />
  </filter>
  <rect x='0' y='0' height='100' width='100' fill='black' />
  <circle cx='50' cy='50' fill='white' r='30' filter='url(#cluster)' />
</svg>

But that also displaces the image. Can I undo this? Or not do it in the first place? Maybe by using something other than feDisplacementMap?

Upvotes: 2

Views: 206

Answers (1)

Michael Mullany
Michael Mullany

Reputation: 31740

The main problem with your filter is its very high baseFrequency - you need to dial that waaay down. And fractalNoise is better than turbulence as a feTurbulence type for a scatter filter. As long as your displacement map is centered at 0.5 of the channel, your image shouldn't be displaced in x/y on average. It's only a problem if you've got a bright or dark displacement map (which is not the case with feTurbulence). Finally - a higher displacement scale will give you the pointy look you're looking for - like so.

It can take a bunch of trial and error to get the exact look that you want. This is a link to a filter editor for shadows that might give you some ideas https://codepen.io/mullany/pen/sJopz

<svg height="220px" width="260px" viewBox="0 0 800 600">
  <defs>
    <filter id="scatter">
      <feTurbulence baseFrequency=".2" type="fractalNoise" numOctaves="3"/>
      <feDisplacementMap in="SourceGraphic" xChannelSelector="G" yChannelSelector="B" scale="300"/>
      <feComposite operator="in" in2="finalMask"/>
    </filter>
    </defs>
  
  <g filter="url(#scatter)">
  <polyline points="10,10  10,300, 300,400" transform="translate(60 60)" fill="blue"/>
  
  <polyline points="500,10  110,300, 300,400" transform="translate(260 60)" fill="red"/>
  </g>
</svg>

Upvotes: 2

Related Questions