Skip to content

Blend modes, opacity and shadows

Blend modes, opacity and shadows

Run it here, in your browser

f.blend_mode() changes how new drawing mixes with what is already on the canvas: "multiply" darkens like overlapping inks, "screen" lightens like overlapping lights. f.opacity() makes everything after it see-through, and f.shadow() gives it a soft shadow.

How it works

  • f.blend_mode(mode) decides how a new shape mixes with what is under it. trio() draws the same three circles in each mode, then sets "normal" again.
  • "multiply" darkens, as when inks overlap. "screen" and "add" lighten, as when lights overlap. That is why they sit on a dark panel: on white there would be nothing to see.
  • f.opacity(amount) makes everything after it see-through. 255 is solid and 0 is invisible. The three green squares use 255, 170 and 85. The 255 call afterwards puts it back.
  • f.shadow(x_offset, y_offset, blur=...) adds a soft shadow under what you draw next. It moves right and down by the first two numbers. f.no_shadow() switches it off.

Make it yours

  • Try other modes in the trio() calls: "overlay", "darken", "lighten" or "difference".
  • Change the three numbers in [255, 170, 85] to make the squares more or less see-through.
  • Change the shadow: a bigger blur makes it softer, and negative offsets throw it up and left.
  • Give the shadow a colour: f.shadow(6, 8, blur=10, color=(255, 0, 0, 120)).
  • Change the three circle colours in the list inside trio().

The code

Copy it into a file and run it.

"""Blend modes, opacity and shadows

f.blend_mode() changes how new drawing mixes with what is already on the canvas: "multiply"
darkens like overlapping inks, "screen" lightens like overlapping lights. f.opacity() makes
everything after it see-through, and f.shadow() gives it a soft shadow.

How it works:
- f.blend_mode(mode) decides how a new shape mixes with what is under it. trio() draws the same
  three circles in each mode, then sets "normal" again.
- "multiply" darkens, as when inks overlap. "screen" and "add" lighten, as when lights overlap.
  That is why they sit on a dark panel: on white there would be nothing to see.
- f.opacity(amount) makes everything after it see-through. 255 is solid and 0 is invisible.
  The three green squares use 255, 170 and 85. The 255 call afterwards puts it back.
- f.shadow(x_offset, y_offset, blur=...) adds a soft shadow under what you draw next. It moves right
  and down by the first two numbers. f.no_shadow() switches it off.

Make it yours:
- Try other modes in the trio() calls: "overlay", "darken", "lighten" or "difference".
- Change the three numbers in [255, 170, 85] to make the squares more or less see-through.
- Change the shadow: a bigger blur makes it softer, and negative offsets throw it up and left.
- Give the shadow a colour: f.shadow(6, 8, blur=10, color=(255, 0, 0, 120)).
- Change the three circle colours in the list inside trio().
"""
import funground as f


def trio(x, y, mode, label_colour="black"):
    f.blend_mode(mode)
    f.no_stroke()
    for dx, dy, colour in [(0, 0, "red"), (40, 0, "lime"), (20, 34, "blue")]:
        f.fill(colour)
        f.circle(x + dx, y + dy, 70)
    f.blend_mode("normal")
    f.fill(label_colour)
    f.text_align("center")
    f.text(mode, x + 20, y + 80)
    f.text_align("left")


def setup():
    f.size(640, 400)


def draw():
    f.background("white")
    f.fill((40, 40, 40))
    f.rect(320, 0, 320, 200)                          # a dark half, so "screen" and "add" show
    f.text_size(16)
    trio(60, 60, "normal")
    trio(200, 60, "multiply")
    trio(390, 60, "screen", "white")
    trio(530, 60, "add", "white")

    for i, amount in enumerate([255, 170, 85]):
        f.opacity(amount)
        f.fill("seagreen")
        f.rect(40 + i * 60, 230, 90, 90)
    f.opacity(255)
    f.fill("black")
    f.text("opacity 255, 170, 85", 40, 340)

    f.shadow(6, 8, blur=10)
    f.fill("gold")
    f.stroke("darkgoldenrod")
    f.stroke_width(3)
    f.rect(350, 230, 110, 90)
    f.no_stroke()
    f.fill("tomato")
    f.text_size(32)
    f.text("Shadow", 485, 255)
    f.no_shadow()


f.run()

View on GitHub ยท Back to the gallery