~starkingdoms/starkingdoms

ref: da320031c94d4360d10b8f57bb5fe399c0deb47e starkingdoms/crates/client/src/rendering/mod.rs -rw-r--r-- 5.8 KiB
da320031 — ghostly_zsh resize canvas from wasm, not html 8 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
use glow::HasContext;
use wasm_bindgen::{prelude::Closure, JsCast};
use web_sys::{Event, HtmlCanvasElement};
use winit::{application::ApplicationHandler, dpi::LogicalSize, event::WindowEvent, event_loop::ActiveEventLoop, platform::web::{WindowAttributesExtWebSys, WindowExtWebSys}, raw_window_handle::HasWindowHandle, window::{Window, WindowAttributes}};

pub mod init;

#[derive(Default)]
pub struct App {
    window: Option<Window>,
    program: glow::Program,
    vertex_array: glow::VertexArray,
    vertex_buffer: glow::Buffer,
    gl: Option<glow::Context>,
}

const VERTICES: [f32; 6] = [
    0.0, 1.0,
    -1.0, -1.0,
    1.0, -1.0,
];

impl ApplicationHandler for App {
    fn resumed(&mut self, event_loop: &ActiveEventLoop) {
        #[cfg(target_arch = "wasm32")]
        let attributes = {
            let document = web_sys::window().unwrap().document().unwrap();
            let canvas = document.get_element_by_id("canvas").unwrap();
            let canvas = canvas.dyn_into::<web_sys::HtmlCanvasElement>()
                .map_err(|_| ()).unwrap();
            canvas.set_width(web_sys::window().unwrap().inner_width().unwrap().as_f64().unwrap() as u32);
            canvas.set_height(web_sys::window().unwrap().inner_height().unwrap().as_f64().unwrap() as u32);
            Window::default_attributes()
                .with_title("StarKingdoms.TK")
                .with_canvas(Some(canvas))
        };
        #[cfg(not(target_arch = "wasm32"))]
        let attributes = {
            Window::default_attributes().with_title("StarKingdoms.TK");
        };
        self.window = Some(event_loop.create_window(attributes).unwrap());
        let window = self.window.as_ref().unwrap();
        #[cfg(target_arch = "wasm32")]
        let context = window.canvas().unwrap().get_context("webgl2")
            .unwrap().unwrap()
            .dyn_into::<web_sys::WebGl2RenderingContext>()
            .unwrap();
        #[cfg(not(target_arch = "wasm32"))]
        unsafe {
        }
        let (gl, shader_version) = (glow::Context::from_webgl2_context(context), "#version 300 es");
        unsafe {
            let vertex_shader = gl.create_shader(glow::VERTEX_SHADER).expect("Failed to create vertex shader");
            let fragment_shader = gl.create_shader(glow::FRAGMENT_SHADER).expect("Failed to create fragment shader");

            let vertex_source = include_str!("../shaders/vertex.glsl");
            let fragment_source = include_str!("../shaders/fragment.glsl");

            gl.shader_source(vertex_shader, &format!("{}\n{}", shader_version, vertex_source));
            gl.compile_shader(vertex_shader);
            if !gl.get_shader_compile_status(vertex_shader) {
                tracing::error!("error in vertex shader: {}", gl.get_shader_info_log(vertex_shader));
            }
            gl.shader_source(fragment_shader, &format!("{}\n{}", shader_version, fragment_source));
            gl.compile_shader(fragment_shader);
            if !gl.get_shader_compile_status(fragment_shader) {
                tracing::error!("error in fragment shader: {}", gl.get_shader_info_log(fragment_shader));
            }

            let program = gl.create_program().expect("Failed to create program");
            gl.attach_shader(program, vertex_shader);
            gl.attach_shader(program, fragment_shader);
            gl.link_program(program);

            gl.delete_shader(vertex_shader);
            gl.delete_shader(fragment_shader);

            gl.use_program(Some(program));

            let vertex_array = gl.create_vertex_array().expect("Failed to create vertex array");
            gl.bind_vertex_array(Some(vertex_array));
            let vertex_buffer = gl.create_buffer().expect("Failed to create vertex buffer");
            gl.bind_buffer(glow::ARRAY_BUFFER, Some(vertex_buffer));
            gl.buffer_data_u8_slice(glow::ARRAY_BUFFER,
                std::slice::from_raw_parts(VERTICES.as_ptr() as *const u8, 6*4),
                glow::STATIC_DRAW);

            gl.vertex_attrib_pointer_f32(0, 2, glow::FLOAT, false, 2*std::mem::size_of::<f32>() as i32, 0);
            gl.enable_vertex_attrib_array(0);

            gl.clear_color(1.0, 1.0, 1.0, 1.0);
            gl.viewport(0, 0, window.inner_size().width as i32, window.inner_size().height as i32);

            self.program = program;
            self.vertex_array = vertex_array;
            self.vertex_buffer = vertex_buffer;
        }
        #[cfg(target_arch = "wasm32")]
        web_sys::window().unwrap().set_onresize(Some(Closure::<dyn Fn(Event)>::new(move |_| {
            let document = web_sys::window().unwrap().document().unwrap();
            let canvas = document.get_element_by_id("canvas").unwrap();
            let canvas = canvas.dyn_into::<web_sys::HtmlCanvasElement>()
                .map_err(|_| ()).unwrap();
            canvas.set_width(web_sys::window().unwrap().inner_width().unwrap().as_f64().unwrap() as u32);
            canvas.set_height(web_sys::window().unwrap().inner_height().unwrap().as_f64().unwrap() as u32);
        }).into_js_value().as_ref().unchecked_ref()));
        self.gl = Some(gl);
    }
    fn window_event(
        &mut self,
        event_loop: &ActiveEventLoop,
        window_id: winit::window::WindowId,
        event: winit::event::WindowEvent,
    ) {
        match event {
            WindowEvent::Resized(size) => {
                unsafe {
                    self.gl.as_ref().unwrap().viewport(0, 0, size.width as i32, size.height as i32);
                }
            }
            WindowEvent::RedrawRequested => {
                let window = self.window.as_ref().unwrap();
                let gl = self.gl.as_ref().unwrap();

                unsafe {
                    gl.clear(glow::COLOR_BUFFER_BIT);
                    gl.draw_arrays(glow::TRIANGLES, 0, 3);
                }

                window.request_redraw();
            }
            _ => {}
        }
    }
}