13. Shaders and effects
Water, a wet lens, rings and a rising sea: presets that paint pixels, animated like any other property.
Loading live preview…
Source of learn_13_shaders — edit in the playground
//! Lesson 13 — Shaders and effects.
//!
//! Presets paint pixels with a shader: water as a node, drops on the lens
//! over everything drawn before them, rings on a node, and water rising
//! into the next scene. Their parameters are signals, so you animate them
//! like any other property.
use oxframe::prelude::*;
#[oxframe::scene]
pub async fn sea(view: View) {
let water = view.add(
shaders::waves()
.deep(Accent)
.foam(Surface)
.width(pct(100))
.height(pct(40))
.to_edge(Edge::Bottom),
);
let title = view.add(Txt::new().text("Shaders").display().to_edge(Edge::Top));
// Added last: it bends everything drawn before it.
let lens = view.add(shaders::lens_drops().wetness(0.0).fullscreen());
title.fade_in().await;
water.amp().to(0.12, 1.0).await;
// An effect changes one node's own pixels.
let rings = water.effect(shaders::ripple().strength(0.0));
rings.strength().to(1.0, 0.4).await;
rings.strength().to(0.0, 0.8).await;
lens.wetness().to(1.0, 0.5).await;
wait_for(0.4).await;
}
#[oxframe::scene]
pub async fn land(view: View) {
// Added before the transition, so the rising water uncovers it.
view.add(Txt::new().text("Dry land").display());
transition(Transition::shader(shaders::water_wipe())).await;
wait_for(0.6).await;
}
// Try: `.wetness(0.3)` for a light drizzle, or `water_wipe().wave(0.1)`.
pub fn project() -> Project {
Project::new("shaders").scene(sea()).scene(land())
}A shader is a node
shaders::waves() paints water inside its box. Place it like a rectangle, with .width(pct(100)), .height(..) and .to_edge(Edge::Bottom). .amp() is the wave height, and it is a signal: water.amp().to(0.12, 1.0) makes the sea grow. .deep(Accent) takes its color from the theme.
Shaders that read the picture
shaders::lens_drops() puts drops on the lens over everything drawn before it, so add
it last and make it .fullscreen(). Start dry with .wetness(0.0); a
splash is lens.wetness().to(1.0, 0.5).
node.effect(shaders::ripple()) changes one node's own pixels: rings spread from its
center. It returns a handle whose .strength() you animate. The colors move and the outline
stays, so use it on water, text or an image.
Transition::shader(shaders::water_wipe()) is a transition from lesson 11 painted by a shader:
water rises over the frame and the next scene is under it.
Make events signals
A splash at two seconds is a signal change at that moment, not a formula of time. That way the
editor shows it on the timeline and oxframe check sees it. A shader can only read
finished pixels: inside a fading group or a blur, check reports input_cycle. Rendering video has the details.
Next
Lesson 14 plots functions and data on axes that follow animated ranges.