Maybe I'm not understanding <feComposite/>
, but it seems it cannot be used in a following <feGaussianBlur/>
's in
- I can only use SourceGraphic
, which isn't what I want.
Basically, I have a filter that creates two shapes (one of the original path, but fills it with a color, and one of the original shape, but offsets and blurs it). I want to combine those two shapes into a 3rd one using <feComposite/>
, and then apply some more filter items to that third one (a blur). But the blur is applied to shapes #1 and #2, instead of the combined shape #3.
You can see the problem here:
<svg name="wave-shadow-glow" x="25" y="25" width="108" height="108" overflow="visible"
stroke-width="4.5" fill="red" stroke="#00B0F0">
<defs>
<symbol id="maincontainereffects" overflow="visible">
<path d="M0,13.5 C 36,-31.5 72,58.5 108,13.5 L 108,94.5 C 72,139.5 36,49.5 0,94.5 Z "
filter="url(#mainFilter-effects0sp5)" stroke="none"></path>
</symbol>
<filter id="mainFilter-effects0sp5" color-interpolation-filters="sRGB" x="-100%" y="-100%" width="300%"
height="300%">
<!--shape #1. original, but make it black-->
<feColorMatrix in="SourceGraphic" type="matrix" values="
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 1 0" result="InnerShadowBlack"></feColorMatrix>
<!--shape #2. original, but offset it... -->
<feOffset in="SourceGraphic" dx="-30" dy="0" result="InnerSourceOffset"></feOffset>
<!--shape #2 cont. ...and blur it
(in reality, I don't want to blur it, but rather "feather" it, but...
that's a story for another day...) -->
<feGaussianBlur in="InnerSourceOffset" stdDeviation="4" result="InnerSourceBlurred"></feGaussianBlur>
<!--shape #3. combine the two above. don't need shapes #1 and #2 anymore-->
<feComposite operator="atop" in="InnerSourceBlurred" in2="InnerShadowBlack" result="InnerShadow">
</feComposite>
<!--shape #4. create a green blurred shape of shape #3 in order to put it behind shape #3 in the shape #5 merge-->
<!-- NOTE: this is where the problem comes from.
If I use "SourceGraphic" in "in", it works fine. But I can't use "InnerShadow" because
the glow will appear around shapes #1 and #2 seperately-->
<feGaussianBlur in="InnerShadow" stdDeviation="3.33" result="firstGlowBlur"></feGaussianBlur>
<feColorMatrix in="firstGlowBlur" type="matrix" values="0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 2 2 2 1 0"
result="firstColorMatrix">
</feColorMatrix>
<feGaussianBlur in="firstColorMatrix" stdDeviation="2.222" result="Glow"></feGaussianBlur> -->
<!--shape #5. merge shapes #3 and #4-->
<feMerge result="InnerShadowAndGlow">
<feMergeNode in="Glow"></feMergeNode>
<feMergeNode in="InnerShadow"></feMergeNode>
</feMerge>
</filter>
</defs>
<use id="maincontainerwitheffect" href="#maincontainereffects"></use>
</svg>
As noted though the first <feGaussianBlur/>
in shape #4 uses InnerShadow
, which is what I want, because I may start with a different shape than SourceGraphic
(i.e. before all all of these filter items, I may use something like an feMorphology
to make the first image smaller.
Using SourceGraphic
does work and produces the right result - it just isn't what a need for this filter - I need the glow around InnerShadow
.
<svg name="wave-shadow-glow" x="25" y="25" width="108" height="108" overflow="visible"
stroke-width="4.5" fill="red" stroke="#00B0F0">
<defs>
<symbol id="maincontainereffects" overflow="visible">
<path d="M0,13.5 C 36,-31.5 72,58.5 108,13.5 L 108,94.5 C 72,139.5 36,49.5 0,94.5 Z "
filter="url(#mainFilter-effects0sp5)" stroke="none"></path>
</symbol>
<filter id="mainFilter-effects0sp5" color-interpolation-filters="sRGB" x="-100%" y="-100%" width="300%"
height="300%">
<!--shape #1. original, but make it black-->
<feColorMatrix in="SourceGraphic" type="matrix" values="
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 1 0" result="InnerShadowBlack"></feColorMatrix>
<!--shape #2. original, but offset it... -->
<feOffset in="SourceGraphic" dx="-30" dy="0" result="InnerSourceOffset"></feOffset>
<!--shape #2 cont. ...and blur it
(in reality, I don't want to blur it, but rather "feather" it, but...
that's a story for another day...) -->
<feGaussianBlur in="InnerSourceOffset" stdDeviation="4" result="InnerSourceBlurred"></feGaussianBlur>
<!--shape #3. combine the two above. don't need shapes #1 and #2 anymore-->
<feComposite operator="atop" in="InnerSourceBlurred" in2="InnerShadowBlack" result="InnerShadow">
</feComposite>
<!--shape #4. create a green blurred shape of shape #3 in order to put it behind shape #3 in the shape #5 merge-->
<!-- NOTE: this is where the problem comes from.
If I use "SourceGraphic" in "in", it works fine. But I can't use "InnerShadow" because the glow will appear around shapes #1 and #2 separately -->
<feGaussianBlur in="SourceGraphic" stdDeviation="3.33" result="firstGlowBlur"></feGaussianBlur>
<feColorMatrix in="firstGlowBlur" type="matrix" values="0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 2 2 2 1 0"
result="firstColorMatrix">
</feColorMatrix>
<feGaussianBlur in="firstColorMatrix" stdDeviation="2.222" result="Glow"></feGaussianBlur> -->
<!--shape #5. merge shapes #3 and #4-->
<feMerge result="InnerShadowAndGlow">
<feMergeNode in="Glow"></feMergeNode>
<feMergeNode in="InnerShadow"></feMergeNode>
</feMerge>
</filter>
</defs>
<use id="maincontainerwitheffect" href="#maincontainereffects"></use>
</svg>
Am I misunderstanding <feComposite/>
in that it can only be used to display, but can't be used in subsequent filter operations?
CodePudding user response:
It is not the feComposite
that is responsible for the error, but the second feMatrix
. I don't get the math here completely, but this is what I see in Inkscape if I apply everything up to that filter primitive, before further blurring:
What you really wanted to do was color the shape green and widen the preexisting blur radius. That can be done with the matrix
0 0 0 0 0
0 0 0 0 1 <- add green
0 0 0 0 0
0 0 0 10 0 <- raise opacity
<svg name="wave-shadow-glow" x="25" y="25" width="108" height="108" overflow="visible"
stroke-width="4.5" fill="red" stroke="#00B0F0">
<defs>
<symbol id="maincontainereffects" overflow="visible">
<path d="M0,13.5 C 36,-31.5 72,58.5 108,13.5 L 108,94.5 C 72,139.5 36,49.5 0,94.5 Z "
filter="url(#mainFilter-effects0sp5)" stroke="none"></path>
</symbol>
<filter id="mainFilter-effects0sp5" color-interpolation-filters="sRGB" x="-100%" y="-100%" width="300%"
height="300%">
<feColorMatrix in="SourceGraphic" type="matrix" values="
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 1 0" result="InnerShadowBlack"></feColorMatrix>
<feOffset in="SourceGraphic" dx="-30" dy="0" result="InnerSourceOffset"></feOffset>
<feGaussianBlur in="InnerSourceOffset" stdDeviation="4" result="InnerSourceBlurred"></feGaussianBlur>
<feComposite operator="atop" in="InnerSourceBlurred" in2="InnerShadowBlack" result="InnerShadow">
</feComposite>
<feGaussianBlur in="InnerShadow" stdDeviation="3.33" result="firstGlowBlur"></feGaussianBlur>
<feColorMatrix in="firstGlowBlur" type="matrix" values="
0 0 0 0 0
0 0 0 0 1
0 0 0 0 0
0 0 0 10 0" result="firstColorMatrix"></feColorMatrix>
<feGaussianBlur in="firstColorMatrix" stdDeviation="2.222" result="Glow"></feGaussianBlur>
<feMerge result="InnerShadowAndGlow">
<feMergeNode in="Glow"></feMergeNode>
<feMergeNode in="InnerShadow"></feMergeNode>
</feMerge>
</filter>
</defs>
<use id="maincontainerwitheffect" href="#maincontainereffects"></use>
</svg>
CodePudding user response:
The filter is working properly as you've written it, but shouldn't you be using the blurred version of InnerShadow if you want a blur around it? aka:
<feMerge result="InnerShadowAndGlow">
<feMergeNode in="Glow"></feMergeNode>
<feMergeNode in="firstGlowBlur"></feMergeNode>
</feMerge>