~starkingdoms/starkingdoms

ref: f6a70c23cb477f78145ea82bcbb1787ff0170188 starkingdoms/crates/client/src/rendering/mod.rs -rw-r--r-- 5.9 KiB
f6a70c23 — ghostly_zsh ebo + init code cleanup 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
136
137
138
139
140
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,
    element_buffer: glow::Buffer,
    gl: Option<glow::Context>,
}

const VERTICES: [f32; 8] = [
    -1.0, -1.0,
    1.0, -1.0,
    1.0, 1.0,
    -1.0, 1.0,
];
const INDICES: [u32; 6] = [
    0, 1, 2,
    2, 3, 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 shaders = [
                ("vertex", include_str!("../shaders/vertex.glsl"), glow::VERTEX_SHADER),
                ("fragment", include_str!("../shaders/fragment.glsl"), glow::FRAGMENT_SHADER),
            ];
            let program = gl.create_program().expect("Failed to create program");

            for (name, source, shader_type) in shaders {
                let shader = gl.create_shader(shader_type).expect("Failed to create vertex shader");
                gl.shader_source(shader, &format!("{}\n{}", shader_version, source));
                gl.compile_shader(shader);
                if !gl.get_shader_compile_status(shader) {
                    tracing::error!("error in {} shader: {}", name, gl.get_shader_info_log(shader));
                }
                gl.attach_shader(program, shader);
                gl.delete_shader(shader);
            }
            gl.link_program(program);

            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));
            let element_buffer = gl.create_buffer().expect("Failed to create element buffer");
            gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, Some(element_buffer));
            gl.buffer_data_u8_slice(glow::ARRAY_BUFFER,
                std::slice::from_raw_parts(VERTICES.as_ptr() as *const u8, 8*4),
                glow::STATIC_DRAW);
            gl.buffer_data_u8_slice(glow::ELEMENT_ARRAY_BUFFER,
                std::slice::from_raw_parts(INDICES.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;
            self.element_buffer = element_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_elements(glow::TRIANGLES, 6, glow::UNSIGNED_INT, 0);
                }

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