Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Integration with egui #115

Unanswered
Quick-Flash asked this question in Q&A
Nov 26, 2025 · 1 comments · 1 reply
Discussion options

How easy is it to get ranim working in an egui project? This could add some really great visuals to egui.

You must be logged in to vote

Replies: 1 comment 1 reply

Comment options

If you want to use ranim to create some UI elements, it might not suit to you, because ranim is designed to produce scientific or mathematical visualization videos (similar to 3b1b/manim).

If you want to display ranim scenes in egui, there are mainly two solutions:

One is to use wgpu + winit + egui, rendering both ranim and egui to the window's surface (this is how ranim-app display ranim scene).

Another is to use eframe + egui_wgpu, rendering to egui's canvas through egui_wgpu::Callback.

You must be logged in to vote
1 reply
Comment options

Now, ranim-app is refactored with eframe in #114, and drawing a ranim scene in eframe is quite easy.

First, you constructs wgpu and ranim-render related things:

fn prepare_renderer(&mut self, frame: &eframe::Frame) {
 if self.renderer.is_some() {
 return;
 }
 tracing::info!("preparing renderer...");
 let Some(render_state) = frame.wgpu_render_state() else {
 tracing::info!("frame.wgpu_render_state() is none");
 tracing::info!("{:?}", frame.info());
 return;
 };
 tracing::info!("constructing renderer...");
 // Construct WgpuContext using eframe's resources.
 // NOTE: We assume ranim-render doesn't strictly depend on the instance for the operations we do here.
 let ctx = WgpuContext {
 instance: wgpu::Instance::default(), // Dummy instance
 adapter: wgpu::Adapter::clone(&render_state.adapter),
 device: wgpu::Device::clone(&render_state.device),
 queue: wgpu::Queue::clone(&render_state.queue),
 };
 let renderer = Renderer::new(&ctx, 2560, 1440, 8); // TODO: dynamic size
 // Register texture with egui
 let texture_view = &renderer.render_textures.linear_render_view;
 let id = render_state.renderer.write().register_native_texture(
 &render_state.device,
 texture_view,
 wgpu::FilterMode::Linear,
 );
 self.texture_id = Some(id);
 self.renderer = Some(renderer);
 self.wgpu_ctx = Some(ctx);
}

Then in each cycle, you simply call ranim's API to render a scene, then in ui you use Painter to draw the texture as an image:

fn render_animation(&mut self) {
 if let (Some(ctx), Some(renderer)) = (self.wgpu_ctx.as_ref(), self.renderer.as_mut()) {
 // ...
 self.store
 .update(self.timeline.eval_at_sec(self.timeline_state.current_sec));
 renderer.render_store_with_pool(ctx, self.clear_color, &self.store, &mut self.pool);
 self.pool.clean();
 }
}
// In ui, something like this
if let Some(tid) = texture_id {
 // Maintain aspect ratio
 // TODO: We could update renderer size here if we want dynamic resolution
 let available_size = ui.available_size();
 let aspect_ratio = self
 .renderer
 .as_ref()
 .map(|r| r.ratio())
 .unwrap_or(1280.0 / 7.0);
 let mut size = available_size;
 
 if size.x / size.y > aspect_ratio {
 size.x = size.y * aspect_ratio;
 } else {
 size.y = size.x / aspect_ratio;
 }
 
 ui.centered_and_justified(|ui| {
 ui.image(egui::load::SizedTexture::new(tid, size));
 });
} else {
 ui.centered_and_justified(|ui| {
 ui.spinner();
 });
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
Q&A
Labels
None yet
Converted from issue

This discussion was converted from issue #100 on January 15, 2026 13:28.

AltStyle によって変換されたページ (->オリジナル) /