Skip to main content

hello/
hello.rs

1use glfw::*;
2use glow::HasContext as _;
3use impellers::*;
4
5pub fn main() {
6    let mut gtx = init(fail_on_errors).unwrap();
7    gtx.window_hint(WindowHint::OpenGlProfile(OpenGlProfileHint::Core));
8    gtx.window_hint(WindowHint::ContextVersionMajor(4));
9    gtx.window_hint(WindowHint::SRgbCapable(true));
10    gtx.window_hint(WindowHint::ScaleToMonitor(true));
11    let (mut window, ev_receiver) = gtx
12        .create_window(800, 600, "rust-glfw-impeller demo", WindowMode::Windowed)
13        .expect("failed to create window");
14    window.set_all_polling(true);
15    window.make_current();
16
17    // initialize impeller context using opengl fn pointers
18    let mut itx = unsafe {
19        impellers::Context::new_opengl_es(|s| {
20            window
21                .get_proc_address(s)
22                .map(|f| f as _)
23                .unwrap_or(std::ptr::null_mut())
24        })
25    }
26    .unwrap();
27    let glow_ctx: glow::Context = unsafe {
28        glow::Context::from_loader_function(|s| {
29            window
30                .get_proc_address(s)
31                .map(|f| f as _)
32                .unwrap_or(std::ptr::null_mut())
33        })
34    };
35    // enter event loop
36    while !window.should_close() {
37        // check events
38        gtx.poll_events();
39        for (_, event) in flush_messages(&ev_receiver) {
40            match event {
41                WindowEvent::Close => {
42                    window.set_should_close(true);
43                }
44                WindowEvent::FramebufferSize(_, _) => {
45                    // glViewPort here
46                }
47                _ => {}
48            }
49        }
50
51        let (width, height) = window.get_framebuffer_size();
52        let mut surface = unsafe {
53            itx.wrap_fbo(
54                0,
55                PixelFormat::RGBA8888,
56                ISize::new(width.into(), height.into()),
57            )
58        }
59        .expect("failed to wrap window's framebuffer");
60        // create a display list
61        let clear_display_list = {
62            // create a display list builder
63            let mut builder = DisplayListBuilder::new(None);
64            // paint controls the properties of draw commands
65            let mut paint = Paint::default();
66            // eg: lets set the color to black. So, any drawing command with this paint will use that color.
67            paint.set_color(Color::BLACKBERRY);
68            // fill the bounds with a color (^^that we set above)
69            builder.draw_paint(&paint);
70            let current_time = gtx.get_time(); // time in seconds since start of the program
71                                               // lets set the color to a color that changes with time.
72                                               // sin/cos/tan will always be in the range of -1 to 1, so lets use abs to keep it in between 0 and 1.
73            paint.set_color(Color::new_srgb(
74                current_time.sin().abs() as _,
75                current_time.cos().abs() as _,
76                current_time.tan().abs() as _,
77            ));
78            builder.draw_rect(&Rect::from_size(Size::new(200.0, 200.0)), &paint);
79            // finish recording the drawing commands. This is only a "list" and we haven't drawn anything yet.
80            builder.build().expect("failed to build a display_list")
81        };
82        let animating_dl = {
83            // create a display list builder
84            let mut builder = DisplayListBuilder::new(None);
85            // paint controls the properties of draw commands
86            let mut paint = Paint::default();
87            let current_time = gtx.get_time(); // time in seconds since start of the program
88                                               // lets set the color to a color that changes with time.
89                                               // sin/cos/tan will always be in the range of -1 to 1, so lets use abs to keep it in between 0 and 1.
90            paint.set_color(Color::new_srgb(
91                current_time.sin().abs() as _,
92                current_time.cos().abs() as _,
93                current_time.tan().abs() as _,
94            ));
95            builder.draw_rect(&Rect::from_size(Size::new(200.0, 200.0)), &paint);
96            // finish recording the drawing commands. This is only a "list" and we haven't drawn anything yet.
97            builder.build().expect("failed to build a display_list")
98        };
99        let oval_dl = {
100            // create a display list builder
101            let mut builder = DisplayListBuilder::new(None);
102            // paint controls the properties of draw commands
103            let mut paint = Paint::default();
104            // eg: lets set the color to black. So, any drawing command with this paint will use that color.
105            paint.set_color(Color::GRANNY_APPLE);
106            builder.draw_oval(&Rect::from_size(Size::new(200.0, 200.0)), &paint);
107            // finish recording the drawing commands. This is only a "list" and we haven't drawn anything yet.
108            builder.build().expect("failed to build a display_list")
109        };
110        let main_display_list = {
111            let mut builder = DisplayListBuilder::new(None);
112            builder.draw_display_list(&clear_display_list, 1.0);
113            builder.draw_display_list(&animating_dl, 1.0);
114            builder.draw_display_list(&oval_dl, 1.0);
115            // finish recording the drawing commands. This is only a "list" and we haven't drawn anything yet.
116            builder.build().expect("failed to build a display_list")
117        };
118        // Now, draw the display_list on the surface. All the commands we recorded in the display_list will be drawn.
119        // you can redraw the display_list multiple times to animate it on any number of surfaces.
120        unsafe {
121            glow_ctx.clear_color(1.0, 0.0, 0.0, 1.0);
122            glow_ctx.clear(glow::COLOR_BUFFER_BIT);
123        }
124        surface
125            .draw_display_list(&main_display_list)
126            .expect("failed to draw on surface");
127        // submit frame and wait for vsync
128        window.swap_buffers();
129    }
130
131    // drop the window/sdl or whatever
132}