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, program: glow::Program, vertex_array: glow::VertexArray, vertex_buffer: glow::Buffer, gl: Option, } 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::() .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::() .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::() 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::::new(move |_| { let document = web_sys::window().unwrap().document().unwrap(); let canvas = document.get_element_by_id("canvas").unwrap(); let canvas = canvas.dyn_into::() .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(); } _ => {} } } }