summaryrefslogtreecommitdiffstats
path: root/examples/integration_opengl
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2021-08-13 20:01:28 +0700
committerLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2021-08-13 20:12:07 +0700
commit77a0b68aa176782e95048795aec15c20a3e60ec6 (patch)
treee4e7c2a34995a91b99a657539f92c8637f52c513 /examples/integration_opengl
parenta646b11109aa451614d3fdf688e600aa48b87a56 (diff)
downloadiced-77a0b68aa176782e95048795aec15c20a3e60ec6.tar.gz
iced-77a0b68aa176782e95048795aec15c20a3e60ec6.tar.bz2
iced-77a0b68aa176782e95048795aec15c20a3e60ec6.zip
Rename `integration` examples
Diffstat (limited to 'examples/integration_opengl')
-rw-r--r--examples/integration_opengl/Cargo.toml13
-rw-r--r--examples/integration_opengl/README.md16
-rw-r--r--examples/integration_opengl/src/controls.rs110
-rw-r--r--examples/integration_opengl/src/main.rs175
-rw-r--r--examples/integration_opengl/src/scene.rs93
5 files changed, 407 insertions, 0 deletions
diff --git a/examples/integration_opengl/Cargo.toml b/examples/integration_opengl/Cargo.toml
new file mode 100644
index 00000000..0917f2ec
--- /dev/null
+++ b/examples/integration_opengl/Cargo.toml
@@ -0,0 +1,13 @@
+[package]
+name = "integration_opengl"
+version = "0.1.0"
+authors = ["Héctor Ramón Jiménez <hector0193@gmail.com>"]
+edition = "2018"
+publish = false
+
+[dependencies]
+iced_glutin = { path = "../../glutin" }
+iced_glow = { path = "../../glow" }
+iced_winit = { path = "../../winit" }
+env_logger = "0.8"
+glow = "0.6"
diff --git a/examples/integration_opengl/README.md b/examples/integration_opengl/README.md
new file mode 100644
index 00000000..08cce7a6
--- /dev/null
+++ b/examples/integration_opengl/README.md
@@ -0,0 +1,16 @@
+## OpenGL integration
+
+A demonstration of how to integrate Iced in an existing graphical OpenGL application.
+
+The __[`main`]__ file contains all the code of the example.
+
+<div align="center">
+ <a href="https://imgbox.com/9P9ETcod" target="_blank"><img src="https://images2.imgbox.com/2a/51/9P9ETcod_o.gif" alt="image host"/></a>
+</div>
+
+You can run it with `cargo run`:
+```
+cargo run --package integration_gl
+```
+
+[`main`]: src/main.rs
diff --git a/examples/integration_opengl/src/controls.rs b/examples/integration_opengl/src/controls.rs
new file mode 100644
index 00000000..13b7fbc2
--- /dev/null
+++ b/examples/integration_opengl/src/controls.rs
@@ -0,0 +1,110 @@
+use iced_glow::Renderer;
+use iced_glutin::{
+ slider, Align, Clipboard, Color, Column, Command, Element, Length, Program,
+ Row, Slider, Text,
+};
+
+pub struct Controls {
+ background_color: Color,
+ sliders: [slider::State; 3],
+}
+
+#[derive(Debug, Clone)]
+pub enum Message {
+ BackgroundColorChanged(Color),
+}
+
+impl Controls {
+ pub fn new() -> Controls {
+ Controls {
+ background_color: Color::BLACK,
+ sliders: Default::default(),
+ }
+ }
+
+ pub fn background_color(&self) -> Color {
+ self.background_color
+ }
+}
+
+impl Program for Controls {
+ type Renderer = Renderer;
+ type Message = Message;
+ type Clipboard = Clipboard;
+
+ fn update(
+ &mut self,
+ message: Message,
+ _clipboard: &mut Clipboard,
+ ) -> Command<Message> {
+ match message {
+ Message::BackgroundColorChanged(color) => {
+ self.background_color = color;
+ }
+ }
+
+ Command::none()
+ }
+
+ fn view(&mut self) -> Element<Message, Renderer> {
+ let [r, g, b] = &mut self.sliders;
+ let background_color = self.background_color;
+
+ let sliders = Row::new()
+ .width(Length::Units(500))
+ .spacing(20)
+ .push(
+ Slider::new(r, 0.0..=1.0, background_color.r, move |r| {
+ Message::BackgroundColorChanged(Color {
+ r,
+ ..background_color
+ })
+ })
+ .step(0.01),
+ )
+ .push(
+ Slider::new(g, 0.0..=1.0, background_color.g, move |g| {
+ Message::BackgroundColorChanged(Color {
+ g,
+ ..background_color
+ })
+ })
+ .step(0.01),
+ )
+ .push(
+ Slider::new(b, 0.0..=1.0, background_color.b, move |b| {
+ Message::BackgroundColorChanged(Color {
+ b,
+ ..background_color
+ })
+ })
+ .step(0.01),
+ );
+
+ Row::new()
+ .width(Length::Fill)
+ .height(Length::Fill)
+ .align_items(Align::End)
+ .push(
+ Column::new()
+ .width(Length::Fill)
+ .align_items(Align::End)
+ .push(
+ Column::new()
+ .padding(10)
+ .spacing(10)
+ .push(
+ Text::new("Background color")
+ .color(Color::WHITE),
+ )
+ .push(sliders)
+ .push(
+ Text::new(format!("{:?}", background_color))
+ .size(14)
+ .color(Color::WHITE),
+ ),
+ ),
+ )
+ .into()
+ }
+}
diff --git a/examples/integration_opengl/src/main.rs b/examples/integration_opengl/src/main.rs
new file mode 100644
index 00000000..925102e3
--- /dev/null
+++ b/examples/integration_opengl/src/main.rs
@@ -0,0 +1,175 @@
+mod controls;
+mod scene;
+
+use controls::Controls;
+use scene::Scene;
+
+use glow;
+use glow::*;
+use iced_glow::{Backend, Renderer, Settings, Viewport};
+use iced_glutin::glutin;
+use iced_glutin::glutin::event::{Event, WindowEvent};
+use iced_glutin::glutin::event_loop::ControlFlow;
+use iced_glutin::{program, Clipboard, Debug, Size};
+use iced_winit::conversion;
+use iced_winit::winit;
+use winit::{dpi::PhysicalPosition, event::ModifiersState};
+
+pub fn main() {
+ env_logger::init();
+ let (gl, event_loop, windowed_context, shader_version) = {
+ let el = glutin::event_loop::EventLoop::new();
+ let wb = glutin::window::WindowBuilder::new()
+ .with_title("OpenGL integration example")
+ .with_inner_size(glutin::dpi::LogicalSize::new(1024.0, 768.0));
+ let windowed_context = glutin::ContextBuilder::new()
+ .with_vsync(true)
+ .build_windowed(wb, &el)
+ .unwrap();
+ unsafe {
+ let windowed_context = windowed_context.make_current().unwrap();
+ let gl = glow::Context::from_loader_function(|s| {
+ windowed_context.get_proc_address(s) as *const _
+ });
+ // Enable auto-conversion from/to sRGB
+ gl.enable(glow::FRAMEBUFFER_SRGB);
+
+ // Enable alpha blending
+ gl.enable(glow::BLEND);
+ gl.blend_func(glow::SRC_ALPHA, glow::ONE_MINUS_SRC_ALPHA);
+
+ // Disable multisampling by default
+ gl.disable(glow::MULTISAMPLE);
+ (gl, el, windowed_context, "#version 410")
+ }
+ };
+
+ let physical_size = windowed_context.window().inner_size();
+ let mut viewport = Viewport::with_physical_size(
+ Size::new(physical_size.width, physical_size.height),
+ windowed_context.window().scale_factor(),
+ );
+
+ let mut cursor_position = PhysicalPosition::new(-1.0, -1.0);
+ let mut modifiers = ModifiersState::default();
+ let mut clipboard = Clipboard::connect(&windowed_context.window());
+
+ let mut renderer = Renderer::new(Backend::new(&gl, Settings::default()));
+
+ let mut debug = Debug::new();
+
+ let controls = Controls::new();
+ let mut state = program::State::new(
+ controls,
+ viewport.logical_size(),
+ conversion::cursor_position(cursor_position, viewport.scale_factor()),
+ &mut renderer,
+ &mut debug,
+ );
+ let mut resized = false;
+
+ event_loop.run(move |event, _, control_flow| {
+ let scene = Scene::new(&gl, &shader_version);
+ *control_flow = ControlFlow::Wait;
+
+ match event {
+ Event::LoopDestroyed => return,
+ Event::WindowEvent { event, .. } => {
+ match event {
+ WindowEvent::CursorMoved { position, .. } => {
+ cursor_position = position;
+ }
+ WindowEvent::ModifiersChanged(new_modifiers) => {
+ modifiers = new_modifiers;
+ }
+ WindowEvent::Resized(physical_size) => {
+ viewport = Viewport::with_physical_size(
+ Size::new(
+ physical_size.width,
+ physical_size.height,
+ ),
+ windowed_context.window().scale_factor(),
+ );
+
+ resized = true;
+ }
+ WindowEvent::CloseRequested => {
+ scene.cleanup(&gl);
+ *control_flow = ControlFlow::Exit
+ }
+ _ => (),
+ }
+
+ // Map window event to iced event
+ if let Some(event) = iced_winit::conversion::window_event(
+ &event,
+ windowed_context.window().scale_factor(),
+ modifiers,
+ ) {
+ state.queue_event(event);
+ }
+ }
+ Event::MainEventsCleared => {
+ // If there are events pending
+ if !state.is_queue_empty() {
+ // We update iced
+ let _ = state.update(
+ viewport.logical_size(),
+ conversion::cursor_position(
+ cursor_position,
+ viewport.scale_factor(),
+ ),
+ &mut renderer,
+ &mut clipboard,
+ &mut debug,
+ );
+
+ // and request a redraw
+ windowed_context.window().request_redraw();
+ }
+ }
+ Event::RedrawRequested(_) => {
+ if resized {
+ let size = windowed_context.window().inner_size();
+
+ unsafe {
+ gl.viewport(
+ 0,
+ 0,
+ size.width as i32,
+ size.height as i32,
+ );
+ }
+
+ resized = false;
+ }
+
+ let program = state.program();
+ {
+ // We clear the frame
+ scene.clear(&gl, program.background_color());
+
+ // Draw the scene
+ scene.draw(&gl);
+ }
+
+ // And then iced on top
+ let mouse_interaction = renderer.backend_mut().draw(
+ &gl,
+ &viewport,
+ state.primitive(),
+ &debug.overlay(),
+ );
+ // Update the mouse cursor
+ windowed_context.window().set_cursor_icon(
+ iced_winit::conversion::mouse_interaction(
+ mouse_interaction,
+ ),
+ );
+
+ windowed_context.swap_buffers().unwrap();
+ }
+ _ => (),
+ }
+ });
+}
diff --git a/examples/integration_opengl/src/scene.rs b/examples/integration_opengl/src/scene.rs
new file mode 100644
index 00000000..596381b3
--- /dev/null
+++ b/examples/integration_opengl/src/scene.rs
@@ -0,0 +1,93 @@
+use glow::*;
+use iced_glow::Color;
+
+pub struct Scene {
+ program: glow::Program,
+ vertex_array: glow::VertexArray,
+}
+
+impl Scene {
+ pub fn new(gl: &glow::Context, shader_version: &str) -> Self {
+ unsafe {
+ let vertex_array = gl
+ .create_vertex_array()
+ .expect("Cannot create vertex array");
+ gl.bind_vertex_array(Some(vertex_array));
+
+ let program = gl.create_program().expect("Cannot create program");
+
+ let (vertex_shader_source, fragment_shader_source) = (
+ r#"const vec2 verts[3] = vec2[3](
+ vec2(0.5f, 1.0f),
+ vec2(0.0f, 0.0f),
+ vec2(1.0f, 0.0f)
+ );
+ out vec2 vert;
+ void main() {
+ vert = verts[gl_VertexID];
+ gl_Position = vec4(vert - 0.5, 0.0, 1.0);
+ }"#,
+ r#"precision highp float;
+ in vec2 vert;
+ out vec4 color;
+ void main() {
+ color = vec4(vert, 0.5, 1.0);
+ }"#,
+ );
+
+ let shader_sources = [
+ (glow::VERTEX_SHADER, vertex_shader_source),
+ (glow::FRAGMENT_SHADER, fragment_shader_source),
+ ];
+
+ let mut shaders = Vec::with_capacity(shader_sources.len());
+
+ for (shader_type, shader_source) in shader_sources.iter() {
+ let shader = gl
+ .create_shader(*shader_type)
+ .expect("Cannot create shader");
+ gl.shader_source(shader, &format!("{}\n{}", shader_version, shader_source));
+ gl.compile_shader(shader);
+ if !gl.get_shader_compile_status(shader) {
+ panic!(gl.get_shader_info_log(shader));
+ }
+ gl.attach_shader(program, shader);
+ shaders.push(shader);
+ }
+
+ gl.link_program(program);
+ if !gl.get_program_link_status(program) {
+ panic!(gl.get_program_info_log(program));
+ }
+
+ for shader in shaders {
+ gl.detach_shader(program, shader);
+ gl.delete_shader(shader);
+ }
+
+ gl.use_program(Some(program));
+ Self { program, vertex_array }
+ }
+ }
+
+ pub fn clear(&self, gl: &glow::Context, background_color: Color) {
+ let [r, g, b, a] = background_color.into_linear();
+ unsafe {
+ gl.clear_color(r, g, b, a);
+ gl.clear(glow::COLOR_BUFFER_BIT);
+ }
+ }
+
+ pub fn draw(&self, gl: &glow::Context) {
+ unsafe {
+ gl.draw_arrays(glow::TRIANGLES, 0, 3);
+ }
+ }
+
+ pub fn cleanup(&self, gl: &glow::Context) {
+ unsafe {
+ gl.delete_program(self.program);
+ gl.delete_vertex_array(self.vertex_array);
+ }
+ }
+} \ No newline at end of file