Add brightness option and run/dry wrapper scripts
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
5e6bc54d08
commit
0ff391bfa1
5 changed files with 38 additions and 6 deletions
|
|
@ -11,7 +11,9 @@ stairs show. On exit it sends a black frame. The stairs power must be on
|
|||
nix-shell --run "python treppe_gl.py shaders/flow.glsl"
|
||||
nix-shell --run "python treppe_gl.py shaders/pulse.glsl --dry-run"
|
||||
|
||||
Options: `--host`, `--port`, `--fps`, `--dry-run` (send nothing),
|
||||
Wrappers: `./treppe-run.sh <shader> [brightness]` and `./treppe-dry.sh <shader> [brightness]` (dry run, nothing is sent).
|
||||
|
||||
Options: `--brightness 0-100` (scales output, default 100), `--host`, `--port`, `--fps`, `--dry-run` (send nothing),
|
||||
`--no-window` (headless), `--white {extract,alpha,off}`.
|
||||
|
||||
Shaders define `mainImage(out vec4 fragColor, in vec2 fragCoord)` and may
|
||||
|
|
|
|||
|
|
@ -59,3 +59,12 @@ def test_udp_loopback():
|
|||
tx = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
tx.sendto(t.BLACK_FRAME, rx.getsockname())
|
||||
assert rx.recv(2048) == t.BLACK_FRAME
|
||||
|
||||
|
||||
def test_brightness_scales_and_clamps():
|
||||
px = np.array([[1.0, 0.5, 0.25, 1.0]] + [[0, 0, 0, 0]] * 15)
|
||||
half = t.to_rgbw(px, "extract", 50)[0]
|
||||
np.testing.assert_allclose(half, [0.375, 0.125, 0.0, 0.125])
|
||||
assert t.to_rgbw(px, "extract", 0).max() == 0
|
||||
np.testing.assert_allclose(t.to_rgbw(px, "extract", 500),
|
||||
t.to_rgbw(px, "extract", 100))
|
||||
|
|
|
|||
8
treppe-dry.sh
Executable file
8
treppe-dry.sh
Executable file
|
|
@ -0,0 +1,8 @@
|
|||
#!/usr/bin/env bash
|
||||
# Usage: treppe-dry.sh <shader.glsl> [brightness 0-100, default 100]
|
||||
set -euo pipefail
|
||||
here=$(dirname "$(realpath "$0")")
|
||||
[ $# -ge 1 ] || { echo "usage: $0 <shader.glsl> [brightness 0-100]" >&2; exit 2; }
|
||||
shader=$(realpath "$1")
|
||||
cd "$here"
|
||||
exec nix-shell --run "python treppe_gl.py '$shader' --brightness ${2:-100} --dry-run"
|
||||
8
treppe-run.sh
Executable file
8
treppe-run.sh
Executable file
|
|
@ -0,0 +1,8 @@
|
|||
#!/usr/bin/env bash
|
||||
# Usage: treppe-run.sh <shader.glsl> [brightness 0-100, default 100]
|
||||
set -euo pipefail
|
||||
here=$(dirname "$(realpath "$0")")
|
||||
[ $# -ge 1 ] || { echo "usage: $0 <shader.glsl> [brightness 0-100]" >&2; exit 2; }
|
||||
shader=$(realpath "$1")
|
||||
cd "$here"
|
||||
exec nix-shell --run "python treppe_gl.py '$shader' --brightness ${2:-100}"
|
||||
15
treppe_gl.py
15
treppe_gl.py
|
|
@ -35,23 +35,26 @@ WHITE_MODES = ("extract", "alpha", "off")
|
|||
|
||||
# --- Protocol --------------------------------------------------------------
|
||||
|
||||
def to_rgbw(pixels, white="extract"):
|
||||
def to_rgbw(pixels, white="extract", brightness=100.0):
|
||||
"""
|
||||
Convert float RGBA pixels (STEPS x 4, 0..1) to RGBW (STEPS x 4).
|
||||
|
||||
extract: w = min(r, g, b), subtracted from r, g, b
|
||||
alpha: the shader's alpha channel is the white value
|
||||
off: w = 0
|
||||
|
||||
brightness (0..100, percent) scales the result linearly.
|
||||
"""
|
||||
scale = np.float32(min(max(brightness, 0.0), 100.0) / 100.0)
|
||||
px = np.clip(np.asarray(pixels, dtype=np.float32), 0.0, 1.0)
|
||||
rgb = px[:, :3]
|
||||
if white == "extract":
|
||||
w = rgb.min(axis=1, keepdims=True)
|
||||
return np.hstack([rgb - w, w])
|
||||
return np.hstack([rgb - w, w]) * scale
|
||||
if white == "alpha":
|
||||
return np.hstack([rgb, px[:, 3:4]])
|
||||
return np.hstack([rgb, px[:, 3:4]]) * scale
|
||||
if white == "off":
|
||||
return np.hstack([rgb, np.zeros((len(px), 1), dtype=np.float32)])
|
||||
return np.hstack([rgb, np.zeros((len(px), 1), dtype=np.float32)]) * scale
|
||||
raise ValueError("unknown white mode: {}".format(white))
|
||||
|
||||
|
||||
|
|
@ -380,7 +383,7 @@ def run(args):
|
|||
last = now
|
||||
|
||||
pixels = renderer.render_strip(t, dt, frame)
|
||||
rgbw = to_rgbw(pixels, args.white)
|
||||
rgbw = to_rgbw(pixels, args.white, args.brightness)
|
||||
if sock:
|
||||
sock.sendto(encode_frame(rgbw), target)
|
||||
|
||||
|
|
@ -414,6 +417,8 @@ def parse_args(argv=None):
|
|||
p.add_argument("--port", type=int, default=PORT_DEFAULT)
|
||||
p.add_argument("--fps", type=float, default=60.0)
|
||||
p.add_argument("--white", choices=WHITE_MODES, default="extract")
|
||||
p.add_argument("--brightness", type=float, default=100.0,
|
||||
help="0..100 percent, scales what is sent (default 100)")
|
||||
p.add_argument("--dry-run", action="store_true",
|
||||
help="do not send anything over the network")
|
||||
p.add_argument("--no-window", dest="window", action="store_false",
|
||||
|
|
|
|||
Loading…
Reference in a new issue