Home > Software design >  "result" of feComposite is not being used as "in" in a subsequent filter operati
"result" of feComposite is not being used as "in" in a subsequent filter operati

Time:01-05

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:

enter image description here

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>
  • Related