Blending Values
Before this: Numbers, Vectors and Colors
Next steps: Easing
A blend picks a value part way between two others, such as a color between
blue and red. This lesson fades a light with Blend and turns one range of
numbers into another with Remap.
Contents
button Held -> chip pressed
chip lamp -> light Color
chip text -> decal Text
switch Enabled -> light Enabled
Code
@left in pressed: exec
var presses: int = 0
let t = presses.Value / 10.0
@right out lamp = Blend(Color(0.0, 0.2, 1.0), Color(1.0, 0.1, 0.0), t, clampAlpha = true)
@right out text = "${presses.Value} presses"
on pressed {
presses += 1
}
Blend(a, b, t) mixes a and b. t says how far along: 0.0 gives a,
1.0 gives b, and 0.5 gives the value halfway. It works channel by channel:
each channel is a + (b - a) * t.
presses counts the button’s presses, the way
Remembering Values does, and presses.Value / 10.0 turns it
into t: a tenth more blue-to-red for each press. clampAlpha = true
stops t at 1.0, so after ten presses the light stays red.
After five presses, what are the light’s red, green and blue amounts? What color is it after fifteen?
Run
- Compile the chip and paste it in-game. Place a Button, a Point Light and a brick with a Text Decal.
- Turn off the Point Light’s Use Brick Color: while it is on, the light takes the brick’s color and ignores the wire.
- Wire the Button’s Held to
pressed,lampto the Point Light’s Color, andtextto the Text Decal’s Text. Give the light’s Enabled a Switch, flipped on. - Press the button. The light starts blue and moves toward red, one step per press. At five presses it is purple: red 0.5, green 0.15, blue 0.5. From ten presses on it stays red.
Under the Hood
Open the chip. Past the counter’s Var and its add, there is a
Divide for t and one Blend gate, with the two colors typed into its
Input A and Input B and t wired to its Blend input. Clamp Alpha is ticked in the Blend gate’s settings.
lerp(a, b, t) is the same Blend gate without the setting. lerp is the
name most other languages use, and Blend adds clampAlpha.
The setting is part of the gate, chosen when the chip is built, so it takes only a constant. A value worked out while the circuit runs is an error:
@left in presses: int
@left in stop: bool
@right out lamp = Blend(Color(0.0, 0.2, 1.0), Color(1.0, 0.1, 0.0), presses / 10.0, clampAlpha = stop)
Error: [WS028] 'clampAlpha' is constant-only gate config and cannot take a variable or computed value
Other values blend too
Blend and lerp take two numbers, two vectors, two colors, two rotators or
two quaternions, and give back the same kind. On two points, t = 0.5 is
the point halfway between them:
@left in pressed: exec
var presses: int = 0
let start = Vec(0.0, 0.0, 0.0)
let finish = Vec(100.0, 0.0, 50.0)
let spot = lerp(start, finish, presses.Value / 4.0)
@right out text = spot as string
on pressed {
presses += 1
}
Two presses make t 0.5, and the sign shows X=50.000 Y=0.000 Z=25.000.
Four presses reach finish. With no clampAlpha, six presses carry on past
it to X=150.000 Y=0.000 Z=75.000.
On two rotations, the blend turns the shortest way round. Rotations covers rotators and quaternions.
From one range to another
Remap moves a number from one range to the same place in another. A Rigid
Slider reports how far along it is, and Remap turns that into a brightness:
@left in up: bool
@left in position: float
@right out target: float = if up then 100.0 else 0.0
@right out brightness = Remap(position, 0.0, 100.0, 0.0, 4.0)
Remap(value, inMin, inMax, outMin, outMax) finds where value sits between
inMin and inMax, then gives the number at the same place between
outMin and outMax. A position of 25 is a quarter of the way from 0 to
100, so the brightness is a quarter of the way from 0 to 4: 1.0. It is a
lerp that works out its own t:
lerp(outMin, outMax, (value - inMin) / (inMax - inMin)).
if up then 100.0 else 0.0 picks 100 while the switch is on and 0 while it
is off (Choosing a Value).
- Place a Rigid Slider, a short platform welded to its moving end, a Switch and a Point Light. In the slider’s settings, turn on Positions Are Percentages.
- Wire the Switch’s Enabled to
up,targetto the slider’s Target Position, and the slider’s Current Position toposition. Wirebrightnessto the Point Light’s Brightness. - Flip the switch. The platform slides out, and the light brightens as it goes. Flip it back: the light dims as the platform returns.
Modify
- Make the light dim as the platform slides out: swap the output range,
Remap(position, 0.0, 100.0, 4.0, 0.0). - Color the light by the slider’s position too. Add
@right out lamp = Blend(Color(0.0, 0.2, 1.0), Color(1.0, 0.1, 0.0), position / 100.0, clampAlpha = true)to the Remap chip and wire it to the light’s Color. - Make the fade in the first chip start over.
(presses.Value % 11) / 10.0counts 0.0 to 1.0 in tenths and then goes back to 0.0.
Make
Make a heat lamp with three colors. A counted button runs it from green
through yellow to red over twenty presses: green to yellow for the
first ten, yellow to red for the next ten. Blend twice, and choose between
the two blends with if presses.Value < 10 then ... else ....
button Held -> chip pressed
chip lamp -> light Color
switch Enabled -> light Enabled
Good to Know
tmust be afloat.presses.Value / 10is anintdivided by anint, which drops the fraction: it is 0 until the tenth press and then jumps (Numbers). The compiler accepts it without a warning. Write10.0.Remapdoes not stop at the ends: a value pastinMaxgives a number pastoutMax. Wrap it inclamp(...)when the input can overshoot.Blendon two colors mixes the channel numbers.a.ColorBlend(b, t)mixes colors in a color space of your choice (blendSpace = Oklab), which can look more even to the eye.- A Point Light’s Use Brick Color overrides a wired Color. Turn it off whenever a wire sets the color.
See Math, Color, Value conversions and Gate config properties in the reference.
Next: Easing.