glium: 이미지 회전

오늘도 닷넷데브는 잘 돌아갑니다.

[Cargo.toml]

[package]
name = "glium_dotnetdev"
version = "0.1.0"
edition = "2021"

[dependencies]
glium = "*"
glutin = "*"
winit = "*"
image = "*"
reqwest = "*"
tokio = { version = "1", features = ["full"] }

[main.rs]

#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
#[macro_use]
extern crate glium;
extern crate image;

use glium::{glutin, Surface};
use glium::index::PrimitiveType;
use std::fs::File;
use std::io::{Cursor, copy};
use image::GenericImageView;

type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;
 
async fn fetch_url(url: String, file_name: String) -> Result<()> {
    let response = reqwest::get(url).await?;
    let mut file = File::create(file_name)?;
    let mut content =  Cursor::new(response.bytes().await?);
    copy(&mut content, &mut file)?;
    Ok(())
}
 
#[tokio::main]
async fn main() {
    let img_filename = "dotnetdev.png";
    fetch_url("https://discourse-dotnetdev-upload.ewr1.vultrobjects.com/original/1X/733ba4d0a11f167d295a4a7257e40bcbc93d91bb.png".to_string(), img_filename.to_string()).await.unwrap();
    let image = image::open(img_filename).expect("File not found!");
    let image_dimensions = image.dimensions();
    let (img_cx, img_cy) = image_dimensions;

    let event_loop = glutin::event_loop::EventLoop::new();
    let wb = glutin::window::WindowBuilder::new()
        .with_title("glium - 닷넷데브".to_owned())
        .with_inner_size(winit::dpi::PhysicalSize {
            width: img_cx as f64, height: img_cy as f64 })
        .with_visible(false);
    let cb = glutin::ContextBuilder::new();
    let display = glium::Display::new(wb, cb, &event_loop).unwrap();
    {
        let gl_window = display.gl_window();
        let window = gl_window.window();
        if let Some(monitor) = window.current_monitor() {
            let screen_size = monitor.size();
            let window_size = window.outer_size();
            window.set_outer_position(winit::dpi::PhysicalPosition {
                x: screen_size.width.saturating_sub(window_size.width) as f64 / 2. + monitor.position().x as f64,
                y: screen_size.height.saturating_sub(window_size.height) as f64 / 2. + monitor.position().y as f64,
            });
            window.set_visible(true);
        }
    }

    // building a texture with "OpenGL" drawn on it
    let image = glium::texture::RawImage2d::from_raw_rgba_reversed(&image.into_rgba8(), image_dimensions);
    let opengl_texture = glium::texture::CompressedSrgbTexture2d::new(&display, image).unwrap();

    // building the vertex buffer, which contains all the vertices that we will draw
    let vertex_buffer = {
        #[derive(Copy, Clone)]
        struct Vertex {
            position: [f32; 2],
            tex_coords: [f32; 2],
        }

        implement_vertex!(Vertex, position, tex_coords);

        glium::VertexBuffer::new(&display,
            &[
                Vertex { position: [-1.0, -1.0], tex_coords: [0.0, 0.0] },
                Vertex { position: [-1.0,  1.0], tex_coords: [0.0, 1.0] },
                Vertex { position: [ 1.0,  1.0], tex_coords: [1.0, 1.0] },
                Vertex { position: [ 1.0, -1.0], tex_coords: [1.0, 0.0] }
            ]
        ).unwrap()
    };

    // building the index buffer
    let index_buffer = glium::IndexBuffer::new(&display, PrimitiveType::TriangleStrip,
        &[1 as u16, 2, 0, 3]).unwrap();

    // compiling shaders and linking them together
    let program = glium::Program::from_source(&display, r"
        #version 140

        uniform mat4 matrix;

        in vec2 position;
        in vec2 tex_coords;

        out vec2 v_tex_coords;

        void main() {
            gl_Position = matrix * vec4(position, 0.0, 1.0);
            v_tex_coords = tex_coords;
        }", r"
        #version 140
        uniform sampler2D tex;
        in vec2 v_tex_coords;
        out vec4 color;

        void main() {
            color = texture(tex, v_tex_coords);
        }", None).unwrap();

    let mut t: f32 = -0.5;
    let mut accel: f32 = 0.002;
    event_loop.run(move |event, _, control_flow| {

        match event {
            glutin::event::Event::WindowEvent { event, .. } => match event {
                glutin::event::WindowEvent::CloseRequested => {
                    *control_flow = glutin::event_loop::ControlFlow::Exit;
                    return;
                },
                _ => return,
            },
            glutin::event::Event::NewEvents(cause) => match cause {
                glutin::event::StartCause::ResumeTimeReached { .. } => (),
                glutin::event::StartCause::Init => (),
                _ => return,
            },
            _ => return,
        }

        let next_frame_time = std::time::Instant::now() +
            std::time::Duration::from_nanos(16_666_667);
         *control_flow = glutin::event_loop::ControlFlow::WaitUntil(next_frame_time);

        // we update `t`
        t += accel;
        accel += 0.001;
        //if t > 0.5 { t = -0.5; }

        let mut target = display.draw();
        target.clear_color(0.0, 0.0, 0.0, 1.0);

        let uniforms = uniform! {
            matrix: [
                [ t.cos(), t.sin(), 0.0, 0.0],
                [-t.sin(), t.cos(), 0.0, 0.0],
                [0.0, 0.0, 1.0, 0.0],
                [0.0, 0.0, 0.0, 1.0f32],
            ],
            tex: &opengl_texture
        };

        target.draw(&vertex_buffer, &index_buffer, &program, &uniforms,
                    &Default::default()).unwrap();
        target.finish().unwrap();
    });
}
2개의 좋아요