(click anywhere to close)
OPEN MENU

[SVG] Filters III

category: Website | course: SVG | difficulty:
IN PRINT
QUICK CONTENTS:Intro
1. Colours
2. Lighting

This last chapter on filters tries to explain the two biggest groups: colours and lighting.

Colours

To just flood fill the whole filter with a certain colour, use

<feFlood flood-color=”color” flood-opacity=”opacity” />

<svg>
    <defs>
        <filter id="ourFilter" width="200" height="200">
            <feFlood flood-color="green" />
        </filter>
    </defs>
    <rect x="10" y="10" width="70" height="70" filter="url(#ourFilter)" />
</svg>

To transform any colour you put in, use

<feColorMatrix type=”value” values=”values” />

The possible types are

Value

Description

matrix

Sets the colour using matrix specified in values.

saturate

Saturates the colour by the amount specified in values

hueRotate

Changes the hue by the amount of degrees specified in values

luminanceToAlpha

Uses the colour’s luminance to set the alpha component of the colour, making it greyscale. Doesn’t need a values attribute.

This matrix is essentially a 5x4 matrix of values separated by spaces. The first four values of each row multiply the current R, G, B and A value with their number. The fifth value is a constant, and is automatically multiplied by 1. The value that comes out of each row sets the value for the R, G, B and A channel of the new colour, respectively. This process is repeated for all pixels.

<svg>
    <defs>
        <filter id="ourFilter" width="200" height="200">
            <feColorMatrix values="0 0 0 0 5
                                   0 0 0 0 0
                                   0 0 0 0 0
                                   0 0 0 0 0.5" type="matrix" />
        </filter>
    </defs>
    <rect x="10" y="10" width="70" height="70" filter="url(#ourFilter)" />
</svg>

To be able to transform colour channels separately, instead of all at the same time, use

<feComponentTransfer color-interpolation-filters=”value”>

The possible values are linearRGB (default) and sRGB. The second is a special form of RGB which can be used for very dark or light colours – for others it doesn’t work at all like you want it to. 

Within the <feComponentTransfer> element, you can specify these child elements

<feFuncR type=”type” /> <feFuncG type=”type” /> <feFuncB type=”type” /> <feFuncA type=”type” />

Of course, you don’t necessarily need to specify all of them – only the colour channels you want changed.

Depending on the type, several other attributes must be specified.

Value

Attributes

Description

identity

 

Changes nothing – just passes on the input value as the output value.

linear

intercept, slope

Applies a simple linear formula to each pixel:

output = intercept + slope*input

gamma

offset, amplitude, exponent

Applies the gamma function:

output = offset + amplitude*(input^exponent)

table

tableValues

Divides the input range by the amount of numbers specified in the attribute. These ranges are mapped to the corresponding ranges specified within the attribute.

discrete

tableValues

Divides the input range by the amount of numbers specified in the attribute. These ranges are mapped to the corresponding value within the attribute.

<svg>
    <defs>
        <filter id="ourFilter" width="200" height="200">
            <feComponentTransfer>
                <!-- A bit of red is added everywhere, but especially at the orange side, because it already contained some red -->
                <feFuncR type="linear" intercept="0.3" slope="0.4"/>
                <!-- The area around the rectangle with alpha 0 is mapped to alpha 0.3. The rectangle itself had alpha 1, so it's mapped to 0.8.-->
                <feFuncA type="discrete" tableValues="0.3 0.8" />
            </feComponentTransfer>
        </filter>
        <linearGradient id="linGrad" x1="0%" y1="0%" x2="100%" y2="100%">
            <stop stop-color="orange" offset="0%" />
            <stop stop-color="green" offset="100%"/>
        </linearGradient>
    </defs>
    <rect x="10" y="10" width="70" height="70" fill="url(#linGrad)" filter="url(#ourFilter)" />
</svg>

Lighting

Lighting is usually viewed as a fundamental concept you need to master for 3D graphics, but it has its uses in 2D graphics as well. For example, there are lots of 2D games that create artificial lighting to create atmosphere, or numerous websites that simulate lighting to highlight certain parts or make them seem 3D. In SVG, two types of lighting are naturally supported.

Specular vs Diffuse

To be able to use any lighting, you need to wrap it inside one of these elements:

<feSpecularLighting lighting-color=”color”> … your lights … </feSpecularLighting>

<feDiffuseLighting lighting-color=”color”> … your lights … </feDiffuseLighting>

The main difference is that specular lighting acts as if your graphic was a plain, smooth surface, while diffuse pretends it’s a rough surface. In the first case, most light is reflected back at you, which leads to light, well-lit areas. In the second case, light waves fly in all directions, which generally leads to dark areas outside of the spot that the light focusses on. Diffuse lighting has a more subdued effect than specular.

With specular, you can set the attributes specularExponent and specularConstant. The first determines the area of the falloff (how slowly light fades away), while the second sets a base level of lightness. With diffuse, two similar attributes diffuseExponent and diffuseConstant exist.

Obviously, the lighting-color sets the colour of the light that is applied.

Blending Light & Shape

To blend the created lighting and the original shape, it’s best to use an <feComposite> element with the operator set to algorithm. It might be a good exercise to see for yourself why we should use the parameters given below – or just ignore that and believe me these are the real deal:

For specular lighting, use k1=0, k2=1, k3=1 and k4=0.

<svg>
    <defs>
    <filter id="ourFilter" width="200" height="200">
        <feGaussianBlur in="SourceAlpha" stdDeviation="4" result="blur1"/>
        <feSpecularLighting result="specOut" in="blur1" specularExponent="20" lighting-color="#bbbbbb">
            <fePointLight x="50" y="100" z="200"/>
        </feSpecularLighting>
        <feComposite in="SourceGraphic" in2="specOut" operator="arithmetic" k1="0" k2="1" k3="1" k4="0"/>
    </filter>
    </defs>
    <rect x="10" y="10" width="70" height="70" fill="orange" filter="url(#ourFilter)" />
</svg>

For diffuse lighting, use k1=1, k2=0, k3=0 and k4=0.

<svg>
    <defs>
    <filter id="ourFilter" width="200" height="200">
        <feGaussianBlur in="SourceAlpha" stdDeviation="10" result="blur1"/>
        <feDiffuseLighting result="specOut" in="blur1" diffuseExponent="20" diffuseConstant="10" lighting-color="#bbbbbb">
            <fePointLight x="50" y="100" z="10"/>
        </feDiffuseLighting>
        <feComposite in="SourceGraphic" in2="specOut" operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
    </filter>
    </defs>
    <rect x="10" y="10" width="100" height="100" fill="orange" filter="url(#ourFilter)" />
</svg>

Point Light

A point light can be viewed like a light bulb – a small, round (local) area of lighting. The syntax is:

<fePointLight x=”xPos” y=”yPos” z=”zPos” />

Note that the Z-axis is the imaginary axis pointing out of the screen, directly at the user. The previous two examples used point lights.

Distant Light

A distant light can be viewed like the sun – it shines from a certain direction and lights nearly everything in its path, except the few bits of graphic at the far end. The syntax is:

<feDistantLight azimuth=”angleXY” elevation=”angleZ” />                  

The angleXY value determines the angle or direction of the light in the XY plane. The angleZ value determines the angle in the Z plane.

<svg>
    <defs>
    <filter id="ourFilter" width="200" height="200">
        <feGaussianBlur in="SourceAlpha" stdDeviation="4" result="blur1"/>
        <feSpecularLighting result="specOut" in="blur1" specularExponent="20" lighting-color="#bbbbbb">
            <feDistantLight azimuth="45" elevation="45"/>
        </feSpecularLighting>
        <feComposite in="SourceGraphic" in2="specOut" operator="arithmetic" k1="0" k2="1" k3="1" k4="0"/>
    </filter>
    </defs>
    <rect x="10" y="10" width="120" height="120" fill="red" filter="url(#ourFilter)" />
</svg>

Spot Light

A spot light is some sort of compromise between the previous two types. It shines from a certain direction, but is contained within a circle. It’s very similar to a spot light used in, for example, theatres in real life.

<feSpotLight x=”xPos” y=”yPos” z=”zPos” pointsAtX=”targetX” pointsAtY=”targetY” pointsAtZ=”targetZ” />

The x, y and z attributes determine the actual position of the spotlight, while the pointsAtX, pointsAtY and pointsAtZ attributes determine what it actually points towards.

Additionally, the limitingConeAngle attribute can be set to restrict the angle under which light is projected. No light is projected outside of this cone.

<svg>
    <defs>
    <filter id="ourFilter" width="200" height="200">
        <feGaussianBlur in="SourceAlpha" stdDeviation="4" result="blur1"/>
        <feSpecularLighting result="specOut" in="blur1" specularExponent="20" lighting-color="#bbbbbb">
            <feSpotLight x="120" y="60" z="100" pointsAtX="70" pointsAtY="60" pointsAtZ="0" limitingConeAngle="20"/>
        </feSpecularLighting>
        <feComposite in="SourceGraphic" in2="specOut" operator="arithmetic" k1="0" k2="1" k3="1" k4="0"/>
    </filter>
    </defs>
    <rect x="10" y="10" width="120" height="120" fill="red" filter="url(#ourFilter)" />
</svg>
CONTINUE WITH THIS COURSE
Do you like my tutorials?
To keep this site running, donate some motivational food!
Crisps
(€2.00)
Chocolate Milk
(€3.50)
Pizza
(€5.00)