Welcome to the world of Skydimo script development! This guide will help you learn how to create your own RGB lighting effects using Lua scripts, whether you’re a beginner or an advanced user. This feature is available in the Skydimo beta version.
Table of Contents
Open Table of Contents
Features Overview
- Creative Freedom: Write unique lighting effects with Lua code
- AI Assistant: Generate custom effects with a single sentence, AI helps you write and optimize code
- Audio Response: Make lights dance to music, supports real-time FFT spectrum analysis
- Multi-tab Management: Edit multiple scripts simultaneously, easy switching and organization
- Hot Reload: Changes take effect immediately, no need to restart software
- Import/Export: Share your creations or use community scripts
- Full Control: Speed, brightness, color temperature, and hue all at your fingertips
Quick Start
Your First Script: Rainbow Gradient
In Skydimo → “Scripts” page, create a new script and enter:
function get_color(x, y, width, height, env)
-- Generate rainbow colors based on position and time
local hue = (x / width * 360 + env.time * 60) % 360
return hsv(hue, 255, 255)
end
Steps:
- Click “Register Mode” button in the top right (buttons from left to right: Register/Update Mode, Restore, Unregister, Export, Import)
- Find the newly registered script in the mode list
- Click to enable, device will display flowing rainbow gradient effect
Code Explanation:
get_color: Function called for each pixelx / width: Generate 0–1 position ratioenv.time: Continuously growing time value, makes colors flowhsv(): Convert hue, saturation, brightness to RGB color
Lua Script Basics
What is Lua?
Lua is a lightweight, easy-to-learn programming language. Skydimo uses Lua 5.4.
Basic Syntax Quick Reference
-- Single line comment
--[[
Multi-line comment
Can write multiple lines
]]
-- Variable definition (no type declaration needed)
local speed = 100
local name = "Rainbow"
local enabled = true
-- Math operations
local result = (10 + 5) * 2 / 3
-- Conditional statements
if x > 10 then
-- Execute code
elseif x == 5 then
-- Another case
else
-- Default case
end
-- Loops
for i = 1, 10 do
-- Repeat 10 times
end
-- Function definition
local function calculate(a, b)
return a + b
end
Core API Specification
Required Function: get_color(x, y, width, height, env)
Purpose: Calculate color value for each LED (called multiple times per frame)
Parameters:
x,y: Current pixel coordinates (starting from 0)width,height: Device total width/heightenv: Environment variable object
Return Value: A 32-bit integer, format 0x00BBGGRR (Blue-Green-Red order, each channel 0–255)
Example:
function get_color(x, y, width, height, env)
return rgb(255, 0, 0) -- Pure red
end
Optional Function: begin_frame(env)
Purpose: Executed once at the beginning of each frame, for pre-computation or initializing frame-level variables.
-- Global variable stores pre-computed results
local wave_offset = 0
function begin_frame(env)
-- Calculate wave offset once per frame
wave_offset = math.sin(env.time) * 50
end
function get_color(x, y, width, height, env)
-- Use pre-computed value directly
local hue = (x / width * 360 + wave_offset) % 360
return hsv(hue, 255, 255)
end
Environment Variables
Common fields in the env environment object:
env.time: Cumulative time since startup (seconds, float)env.dt: Time step from previous frame to current frame (seconds)env.fps: Current frame rate (frames/second)env.random: Random number seed 0–1 (changes per frame)env.bpm: Beat Per Minute, for rhythm-driven effects (optional)env.audio: Audio data object (optional)env.audio.level: Overall volume envelope 0–1env.audio.fft: Spectrum array, low to high frequencyenv.audio.sampleRate: Audio sample rateenv.audio.enabled: Whether audio input is enabled
Built-in Function Library
Color construction and transformation:
rgb(r, g, b): Return 32-bit colorhsv(h, s, v): HSV to RGB, h: 0–360, s/v: 0–255saturate(v): Clamp value to 0–1clamp(v, min, max): Range clippingmix(a, b, t)/lerp(a, b, t): Linear blendingsmoothstep(edge0, edge1, x): Smooth stepmap(x, inMin, inMax, outMin, outMax): Range mapping
Noise and random:
random(): 0–1 randomnoise1(x)/noise2(x, y): Smooth noise
Audio Visualization
Example spectrum visualization:
local spectrum = {}
function begin_frame(env)
if env.audio and env.audio.fft then
spectrum = env.audio.fft
end
end
function get_color(x, y, width, height, env)
if not spectrum or #spectrum == 0 then
return rgb(10, 10, 10)
end
local band = math.max(1, math.floor((x / width) * #spectrum))
local amp = spectrum[band] or 0
local h = (band / #spectrum) * 360
local v = math.floor(math.min(255, amp * 255 * 1.5))
return hsv(h, 255, v)
end
Runtime Mechanism
Rendering loop sequence:
- Call
begin_frame(env)at frame start (if implemented) - Then call
get_color(x, y, width, height, env)for each pixel - Submit frame color buffer to device
Performance tips:
- Do complex calculations in
begin_frameand cache results - Avoid creating many temporary tables
- Use pre-computed lookup tables when possible
AI-Assisted Development
Describe your desired effect in the script editor (e.g., “low frequency drives warm color bars, beat pulse enhances brightness”), and AI will generate initial code. Continue suggesting modifications to iterate quickly.
Practical Examples
1) Spectrum Bar Chart (Horizontal)
local smoothed = {}
function begin_frame(env)
if not (env.audio and env.audio.fft) then return end
local fft = env.audio.fft
for i = 1, #fft do
local v = fft[i]
smoothed[i] = smoothed[i] and (smoothed[i] * 0.6 + v * 0.4) or v
end
end
function get_color(x, y, width, height, env)
if not smoothed or #smoothed == 0 then return rgb(0,0,0) end
local band = math.max(1, math.floor((x / width) * #smoothed))
local level = smoothed[band] or 0
local barH = math.floor(level * height)
if (height - 1 - y) <= barH then
local hue = (band / #smoothed) * 360
return hsv(hue, 255, 255)
else
return rgb(0, 0, 0)
end
end
Best Practices
- Prioritize heavy computation in
begin_frameand data preprocessing - Cache frequently accessed global objects with local variables
- Carefully create temporary tables, avoid
table.insertexpansion overhead in loops - Protect parameters and return values with boundary checks
- Keep color and brightness ranges consistent (0–255), clip if exceeding
FAQ
Q1: What is the return format of get_color?
A: Returns a 32-bit integer, format 0x00BBGGRR.
Q2: Why doesn’t audio visualization respond?
A: Check env.audio.enabled and input device; also confirm if runtime environment has granted microphone permission.
Q3: How to improve frame rate?
A: Reduce complex calculations in get_color; put reusable values in begin_frame; avoid creating temporary tables.
Q4: Does it support running multiple scripts simultaneously?
A: Depends on host implementation; recommend activating one script per device for debugging and performance assurance.