A shader sea, a splash and a dive
The brief. Into the wave: the sea under a camera, a swell, spray toward the lens and a wet lens, a dive into the water, then the sea washes into an end card.
Open in the playground Source on GitHub
What it uses
- Components
- Camera
- Shaders
- Scenes and transitions
- Text
- Groups and layout
- Together and in order
- Randomness and background tasks
- Markers, eases, tunables
The code
examples/src/ocean.rs in oxframe-sdk, for oxframe 0.20.2. In the
playground it compiles in the browser and you can change it.
//! The target scene of hybrid rendering: waves under a camera, a splash
//! toward the lens, a dive into the water, and the sea washing into the
//! shore. Every shader here runs on the CPU, so it renders without a GPU.
//!
//! Drag the `swell` and `splash` markers in the editor to retime the beats.
use oxframe::prelude::*;
#[oxframe::scene]
pub async fn ocean(view: View) {
let cam = view.add(Camera::new());
let sea = cam.add(
shaders::waves()
.amp(0.04)
.deep(Accent)
.foam(Surface)
.width(pct(100))
.height(pct(55))
.to_edge(Edge::Bottom),
);
let title = view.add(
Txt::new()
.text("Into the wave")
.display()
.to_edge(Edge::Top),
);
let spray = view.add(
Particles::new()
.seed(7)
.gravity(1400.0)
.fill(Text) // white foam in the dark theme
.toward_camera(),
);
// Added last, so the drops bend everything above.
let lens = view.add(shaders::lens_drops().wetness(0.0).seed(3).fullscreen());
all((title.fade_in(), cam.zoom().to(1.1, 2.0))).await;
wait_for(0.4).await;
wait_until("swell").await;
sea.amp().to(0.14, 1.2).await;
wait_until("splash").await;
all((spray.burst((0.0, 140.0), 400), lens.wetness().to(1.0, 0.4))).await;
cam.center_on(sea, 0.6).await;
cam.zoom().to(4.0, 0.8).await; // into the wave
}
#[oxframe::scene]
pub async fn shore(view: View) {
// Added before the transition, so the rising water uncovers calm sea.
view.add(
shaders::waves()
.amp(0.01)
.speed(0.3)
.deep(Accent)
.foam(Surface)
.width(pct(100))
.height(pct(12))
.to_edge(Edge::Bottom),
);
transition(Transition::shader(shaders::water_wipe())).await;
view.add(EndCard::new("Made with oxframe")).enter().await;
}
pub fn project() -> Project {
Project::new("ocean")
.size(960, 540)
.fps(30)
.scene(ocean())
.scene(shore())
}